From f5eadc9e1e860e37527b0f0dd9b66d2c6a0fe6dd Mon Sep 17 00:00:00 2001 From: Owen Date: Wed, 29 Oct 2025 12:14:33 -0700 Subject: [PATCH] Various fixes --- server/lib/readConfigFile.ts | 3 +- server/lib/traefik/getTraefikConfig.ts | 91 ++++++++++--------- .../private/lib/traefik/getTraefikConfig.ts | 91 +++++++++++-------- server/setup/scriptsPg/1.12.0.ts | 20 ++++ server/setup/scriptsSqlite/1.12.0.ts | 25 ++++- 5 files changed, 146 insertions(+), 84 deletions(-) diff --git a/server/lib/readConfigFile.ts b/server/lib/readConfigFile.ts index d37a03d8..571708ef 100644 --- a/server/lib/readConfigFile.ts +++ b/server/lib/readConfigFile.ts @@ -204,7 +204,8 @@ export const configSchema = z .optional() .default(["newt", "wireguard", "local"]), allow_raw_resources: z.boolean().optional().default(true), - file_mode: z.boolean().optional().default(false) + file_mode: z.boolean().optional().default(false), + pp_transport_prefix: z.string().optional().default("pp-transport-v") }) .optional() .default({}), diff --git a/server/lib/traefik/getTraefikConfig.ts b/server/lib/traefik/getTraefikConfig.ts index 4352173b..2aafa025 100644 --- a/server/lib/traefik/getTraefikConfig.ts +++ b/server/lib/traefik/getTraefikConfig.ts @@ -265,37 +265,36 @@ export async function getTraefikConfig( const domainCertResolver = resource.domainCertResolver; const preferWildcardCert = resource.preferWildcardCert; - let resolverName: string | undefined; - let preferWildcard: boolean | undefined; - // Handle both letsencrypt & custom cases - if (domainCertResolver) { - resolverName = domainCertResolver.trim(); - } else { - resolverName = globalDefaultResolver; - } + let resolverName: string | undefined; + let preferWildcard: boolean | undefined; + // Handle both letsencrypt & custom cases + if (domainCertResolver) { + resolverName = domainCertResolver.trim(); + } else { + resolverName = globalDefaultResolver; + } - if ( - preferWildcardCert !== undefined && - preferWildcardCert !== null - ) { - preferWildcard = preferWildcardCert; - } else { - preferWildcard = globalDefaultPreferWildcard; - } + if ( + preferWildcardCert !== undefined && + preferWildcardCert !== null + ) { + preferWildcard = preferWildcardCert; + } else { + preferWildcard = globalDefaultPreferWildcard; + } - const tls = { - certResolver: resolverName, - ...(preferWildcard - ? { - domains: [ - { - main: wildCard - } - ] - } - : {}) - }; - + const tls = { + certResolver: resolverName, + ...(preferWildcard + ? { + domains: [ + { + main: wildCard + } + ] + } + : {}) + }; const additionalMiddlewares = config.getRawConfig().traefik.additional_middlewares || []; @@ -534,14 +533,14 @@ export async function getTraefikConfig( })(), ...(resource.stickySession ? { - sticky: { - cookie: { - name: "p_sticky", // TODO: make this configurable via config.yml like other cookies - secure: resource.ssl, - httpOnly: true - } - } - } + sticky: { + cookie: { + name: "p_sticky", // TODO: make this configurable via config.yml like other cookies + secure: resource.ssl, + httpOnly: true + } + } + } : {}) } }; @@ -587,6 +586,8 @@ export async function getTraefikConfig( ...(protocol === "tcp" ? { rule: "HostSNI(`*`)" } : {}) }; + const ppPrefix = config.getRawConfig().traefik.pp_transport_prefix; + config_output[protocol].services[serviceName] = { loadBalancer: { servers: (() => { @@ -642,18 +643,18 @@ export async function getTraefikConfig( })(), ...(resource.proxyProtocol && protocol == "tcp" ? { - serversTransport: `pp-transport-v${resource.proxyProtocolVersion || 1}` + serversTransport: `${ppPrefix}${resource.proxyProtocolVersion || 1}@file` // TODO: does @file here cause issues? } : {}), ...(resource.stickySession ? { - sticky: { - ipStrategy: { - depth: 0, - sourcePort: true - } - } - } + sticky: { + ipStrategy: { + depth: 0, + sourcePort: true + } + } + } : {}) } }; diff --git a/server/private/lib/traefik/getTraefikConfig.ts b/server/private/lib/traefik/getTraefikConfig.ts index bbbdbcfd..36d3c668 100644 --- a/server/private/lib/traefik/getTraefikConfig.ts +++ b/server/private/lib/traefik/getTraefikConfig.ts @@ -109,7 +109,7 @@ export async function getTraefikConfig( domainNamespaceId: domainNamespaces.domainNamespaceId, // Certificate certificateStatus: certificates.status, - domainCertResolver: domains.certResolver, + domainCertResolver: domains.certResolver }) .from(sites) .innerJoin(targets, eq(targets.siteId, sites.siteId)) @@ -214,7 +214,7 @@ export async function getTraefikConfig( rewritePath: row.rewritePath, rewritePathType: row.rewritePathType, priority: priority, // may be null, we fallback later - domainCertResolver: row.domainCertResolver, + domainCertResolver: row.domainCertResolver }); } @@ -330,29 +330,43 @@ export async function getTraefikConfig( wildCard = resource.fullDomain; } - const configDomain = config.getDomain(resource.domainId); + const globalDefaultResolver = + config.getRawConfig().traefik.cert_resolver; + const globalDefaultPreferWildcard = + config.getRawConfig().traefik.prefer_wildcard_cert; - let certResolver: string, preferWildcardCert: boolean; - if (!configDomain) { - certResolver = config.getRawConfig().traefik.cert_resolver; - preferWildcardCert = - config.getRawConfig().traefik.prefer_wildcard_cert; + const domainCertResolver = resource.domainCertResolver; + const preferWildcardCert = resource.preferWildcardCert; + + let resolverName: string | undefined; + let preferWildcard: boolean | undefined; + // Handle both letsencrypt & custom cases + if (domainCertResolver) { + resolverName = domainCertResolver.trim(); } else { - certResolver = configDomain.cert_resolver; - preferWildcardCert = configDomain.prefer_wildcard_cert; + resolverName = globalDefaultResolver; + } + + if ( + preferWildcardCert !== undefined && + preferWildcardCert !== null + ) { + preferWildcard = preferWildcardCert; + } else { + preferWildcard = globalDefaultPreferWildcard; } tls = { - certResolver: certResolver, - ...(preferWildcardCert + certResolver: resolverName, + ...(preferWildcard ? { - domains: [ - { - main: wildCard, - }, - ], - } - : {}), + domains: [ + { + main: wildCard + } + ] + } + : {}) }; } else { // find a cert that matches the full domain, if not continue @@ -604,14 +618,14 @@ export async function getTraefikConfig( })(), ...(resource.stickySession ? { - sticky: { - cookie: { - name: "p_sticky", // TODO: make this configurable via config.yml like other cookies - secure: resource.ssl, - httpOnly: true - } - } - } + sticky: { + cookie: { + name: "p_sticky", // TODO: make this configurable via config.yml like other cookies + secure: resource.ssl, + httpOnly: true + } + } + } : {}) } }; @@ -657,6 +671,8 @@ export async function getTraefikConfig( ...(protocol === "tcp" ? { rule: "HostSNI(`*`)" } : {}) }; + const ppPrefix = config.getRawConfig().traefik.pp_transport_prefix; + config_output[protocol].services[serviceName] = { loadBalancer: { servers: (() => { @@ -712,18 +728,18 @@ export async function getTraefikConfig( })(), ...(resource.proxyProtocol && protocol == "tcp" // proxy protocol only works for tcp ? { - serversTransport: `pp-transport-v${resource.proxyProtocolVersion || 1}` + serversTransport: `${ppPrefix}${resource.proxyProtocolVersion || 1}@file` // TODO: does @file here cause issues? } : {}), ...(resource.stickySession ? { - sticky: { - ipStrategy: { - depth: 0, - sourcePort: true - } - } - } + sticky: { + ipStrategy: { + depth: 0, + sourcePort: true + } + } + } : {}) } }; @@ -771,9 +787,10 @@ export async function getTraefikConfig( loadBalancer: { servers: [ { - url: `http://${config.getRawConfig().server + url: `http://${ + config.getRawConfig().server .internal_hostname - }:${config.getRawConfig().server.next_port}` + }:${config.getRawConfig().server.next_port}` } ] } diff --git a/server/setup/scriptsPg/1.12.0.ts b/server/setup/scriptsPg/1.12.0.ts index 7150a52c..4476b37b 100644 --- a/server/setup/scriptsPg/1.12.0.ts +++ b/server/setup/scriptsPg/1.12.0.ts @@ -107,6 +107,26 @@ export default async function migration() { await db.execute(sql`ALTER TABLE "resources" ADD CONSTRAINT "resources_skipToIdpId_idp_idpId_fk" FOREIGN KEY ("skipToIdpId") REFERENCES "public"."idp"("idpId") ON DELETE set null ON UPDATE no action;`); await db.execute(sql`ALTER TABLE "orgs" DROP COLUMN "settings";`); + + // get all of the domains + const domainsQuery = await db.execute(sql`SELECT "domainId", "baseDomain" FROM "domains"`); + const domains = domainsQuery.rows as { + domainId: string; + baseDomain: string; + }[]; + + for (const domain of domains) { + // insert two records into the dnsRecords table for each domain + await db.execute(sql` + INSERT INTO "dnsRecords" ("domainId", "recordType", "baseDomain", "value", "verified") + VALUES (${domain.domainId}, 'A', ${`*.${domain.baseDomain}`}, ${'Server IP Address'}, true) + `); + await db.execute(sql` + INSERT INTO "dnsRecords" ("domainId", "recordType", "baseDomain", "value", "verified") + VALUES (${domain.domainId}, 'A', ${domain.baseDomain}, ${'Server IP Address'}, true) + `); + } + await db.execute(sql`COMMIT`); console.log("Migrated database"); } catch (e) { diff --git a/server/setup/scriptsSqlite/1.12.0.ts b/server/setup/scriptsSqlite/1.12.0.ts index 8aa86724..d8a679b0 100644 --- a/server/setup/scriptsSqlite/1.12.0.ts +++ b/server/setup/scriptsSqlite/1.12.0.ts @@ -15,7 +15,7 @@ export default async function migration() { db.transaction(() => { db.prepare( - `UPDATE 'resourceRules' SET 'match' = 'COUNTRY' WHERE 'match' = 'GEOIP'` + `UPDATE 'resourceRules' SET match = 'COUNTRY' WHERE match = 'GEOIP'` ).run(); db.prepare( @@ -195,6 +195,29 @@ export default async function migration() { db.prepare( `ALTER TABLE 'user' ADD 'lastPasswordChange' integer;` ).run(); + + // get all of the domains + const domains = db.prepare(`SELECT domainId, baseDomain from domains`).all() as { + domainId: number; + baseDomain: string; + }[]; + + for (const domain of domains) { + // insert two records into the dnsRecords table for each domain + const insert = db.prepare( + `INSERT INTO 'dnsRecords' (domainId, recordType, baseDomain, value, verified) VALUES (?, 'A', ?, ?, 1)` + ); + insert.run( + domain.domainId, + `*.${domain.baseDomain}`, + `Server IP Address` + ); + insert.run( + domain.domainId, + `${domain.baseDomain}`, + `Server IP Address` + ); + } })(); db.pragma("foreign_keys = ON");