feat: allow adding trusted domains in instance setup (#11169)

# Which Problems Are Solved

When running Zitadel behind a reverse proxy and especially when the API
and the login UI don't run on the same domain, Zitadel needs to be
configured to trust the corresponding domains and use them in public
responses, like email links and more.
This can be done by adding a trusted domain. However it's currently only
possible through the API and not in the instance setup process.

# How the Problems Are Solved

Added a possibility to configure multiple trusted domains in the first
instance setup process.

# Additional Changes

None

# Additional Context

- closes #11153
This commit is contained in:
Livio Spring
2026-02-23 06:06:33 +00:00
committed by GitHub
parent 2c260a1f10
commit 71fab2e574
5 changed files with 90 additions and 11 deletions
+30 -3
View File
@@ -365,19 +365,28 @@ func instanceElementsConfig() *SecretGenerators {
}
}
func setupInstanceFilters(instanceID, orgID, projectID, appID, domain string) []expect {
func setupInstanceFilters(instanceID, orgID, projectID, appID, domain string, trustedDomains []string) []expect {
return slices.Concat(
setupInstanceElementsFilters(instanceID),
orgFilters(orgID, true, true, true),
generatedDomainFilters(instanceID, orgID, projectID, appID, domain),
generatedTrustedDomainsFilters(trustedDomains),
)
}
func setupInstanceEvents(ctx context.Context, instanceID, orgID, projectID, appID, instanceName, orgName string, defaultLanguage language.Tag, domain string, externalSecure bool) []eventstore.Command {
func setupInstanceEvents(
ctx context.Context,
instanceID, orgID, projectID, appID, instanceName, orgName string,
defaultLanguage language.Tag,
domain string,
externalSecure bool,
trustedDomains []string,
) []eventstore.Command {
return slices.Concat(
setupInstanceElementsEvents(ctx, instanceID, instanceName, defaultLanguage),
orgEvents(ctx, instanceID, orgID, orgName, projectID, domain, externalSecure, true, true, true),
generatedDomainEvents(ctx, instanceID, orgID, projectID, appID, domain),
generatedTrustedDomainEvents(ctx, instanceID, trustedDomains),
instanceCreatedMilestoneEvent(ctx, instanceID),
)
}
@@ -391,6 +400,7 @@ func setupInstanceConfig() *InstanceSetup {
LoginClient: instanceSetupLoginClientConfig(),
}
conf.CustomDomain = ""
conf.TrustedDomains = []string{"trusted-domain.com", "another-trusted-domain.com"}
return conf
}
@@ -409,6 +419,14 @@ func generatedDomainEvents(ctx context.Context, instanceID, orgID, projectID, ap
}
}
func generatedTrustedDomainEvents(ctx context.Context, instanceID string, trustedDomains []string) []eventstore.Command {
commands := make([]eventstore.Command, len(trustedDomains))
for i, trustedDomain := range trustedDomains {
commands[i] = instance.NewTrustedDomainAddedEvent(ctx, &instance.NewAggregate(instanceID).Aggregate, trustedDomain)
}
return commands
}
func instanceCreatedMilestoneEvent(ctx context.Context, instanceID string) []eventstore.Command {
return []eventstore.Command{
milestone.NewReachedEvent(ctx, milestone.NewInstanceAggregate(instanceID), milestone.InstanceCreated),
@@ -463,6 +481,14 @@ func generatedDomainFilters(instanceID, orgID, projectID, appID, generatedDomain
}
}
func generatedTrustedDomainsFilters(trustedDomains []string) []expect {
filters := make([]expect, len(trustedDomains))
for i := range trustedDomains {
filters[i] = expectFilter()
}
return filters
}
func humanFilters(orgID string) []expect {
return []expect{
expectFilter(),
@@ -1324,7 +1350,7 @@ func TestCommandSide_setUpInstance(t *testing.T) {
fields: fields{
eventstore: expectEventstore(
slices.Concat(
setupInstanceFilters("INSTANCE", "ORG", "PROJECT", "console-id", "DOMAIN"),
setupInstanceFilters("INSTANCE", "ORG", "PROJECT", "console-id", "DOMAIN", []string{"trusted-domain.com", "another-trusted-domain.com"}),
[]expect{
expectPush(
setupInstanceEvents(context.Background(),
@@ -1337,6 +1363,7 @@ func TestCommandSide_setUpInstance(t *testing.T) {
language.English,
"DOMAIN",
false,
[]string{"trusted-domain.com", "another-trusted-domain.com"},
)...,
),
},