mirror of
https://github.com/fosrl/pangolin.git
synced 2026-01-28 22:00:51 +00:00
traefik config update for custom Cert Resolver
This commit is contained in:
@@ -19,7 +19,7 @@ export const domains = pgTable("domains", {
|
||||
verified: boolean("verified").notNull().default(false),
|
||||
failed: boolean("failed").notNull().default(false),
|
||||
tries: integer("tries").notNull().default(0),
|
||||
certResolver: varchar("certResolver").default("letsencrypt"),
|
||||
certResolver: varchar("certResolver"),
|
||||
customCertResolver: varchar("customCertResolver")
|
||||
});
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ export const domains = sqliteTable("domains", {
|
||||
verified: integer("verified", { mode: "boolean" }).notNull().default(false),
|
||||
failed: integer("failed", { mode: "boolean" }).notNull().default(false),
|
||||
tries: integer("tries").notNull().default(0),
|
||||
certResolver: text("certResolver").default("letsencrypt"),
|
||||
certResolver: text("certResolver"),
|
||||
customCertResolver: text("customCertResolver")
|
||||
});
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ export const configSchema = z
|
||||
.nonempty("base_domain must not be empty")
|
||||
.transform((url) => url.toLowerCase()),
|
||||
cert_resolver: z.string().optional().default("letsencrypt"),
|
||||
custom_cert_resolver: z.string().optional(),
|
||||
prefer_wildcard_cert: z.boolean().optional().default(false)
|
||||
})
|
||||
)
|
||||
@@ -187,6 +188,7 @@ export const configSchema = z
|
||||
https_entrypoint: z.string().optional().default("websecure"),
|
||||
additional_middlewares: z.array(z.string()).optional(),
|
||||
cert_resolver: z.string().optional().default("letsencrypt"),
|
||||
custom_cert_resolver: z.string().optional(),
|
||||
prefer_wildcard_cert: z.boolean().optional().default(false),
|
||||
certificates_path: z.string().default("/var/certificates"),
|
||||
monitor_interval: z.number().default(5000),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { db, targetHealthCheck } from "@server/db";
|
||||
import { db, targetHealthCheck, domains } from "@server/db";
|
||||
import {
|
||||
and,
|
||||
eq,
|
||||
@@ -75,11 +75,15 @@ export async function getTraefikConfig(
|
||||
siteType: sites.type,
|
||||
siteOnline: sites.online,
|
||||
subnet: sites.subnet,
|
||||
exitNodeId: sites.exitNodeId
|
||||
exitNodeId: sites.exitNodeId,
|
||||
// Domain cert resolver fields
|
||||
domainCertResolver: domains.certResolver,
|
||||
domainCustomCertResolver: domains.customCertResolver
|
||||
})
|
||||
.from(sites)
|
||||
.innerJoin(targets, eq(targets.siteId, sites.siteId))
|
||||
.innerJoin(resources, eq(resources.resourceId, targets.resourceId))
|
||||
.leftJoin(domains, eq(domains.domainId, resources.domainId))
|
||||
.leftJoin(
|
||||
targetHealthCheck,
|
||||
eq(targetHealthCheck.targetId, targets.targetId)
|
||||
@@ -161,7 +165,10 @@ export async function getTraefikConfig(
|
||||
pathMatchType: row.pathMatchType, // the targets will all have the same pathMatchType
|
||||
rewritePath: row.rewritePath,
|
||||
rewritePathType: row.rewritePathType,
|
||||
priority: priority // may be null, we fallback later
|
||||
priority: priority,
|
||||
// Store domain cert resolver fields
|
||||
domainCertResolver: row.domainCertResolver,
|
||||
domainCustomCertResolver: row.domainCustomCertResolver
|
||||
});
|
||||
}
|
||||
|
||||
@@ -242,18 +249,73 @@ export async function getTraefikConfig(
|
||||
|
||||
const configDomain = config.getDomain(resource.domainId);
|
||||
|
||||
let certResolver: string, preferWildcardCert: boolean;
|
||||
if (!configDomain) {
|
||||
certResolver = config.getRawConfig().traefik.cert_resolver;
|
||||
preferWildcardCert =
|
||||
config.getRawConfig().traefik.prefer_wildcard_cert;
|
||||
let certResolverFromConfig: string | undefined;
|
||||
let preferWildcardCert = false;
|
||||
|
||||
const rawTraefikCfg = config.getRawConfig().traefik || {};
|
||||
const globalDefaultResolver: string | undefined = rawTraefikCfg.cert_resolver;
|
||||
const availableResolvers = rawTraefikCfg.custom_cert_resolver
|
||||
? Object.keys(rawTraefikCfg.custom_cert_resolver)
|
||||
: [];
|
||||
|
||||
// Priority 1: Read from YAML config (if exists)
|
||||
if (configDomain) {
|
||||
certResolverFromConfig =
|
||||
configDomain.cert_resolver ??
|
||||
configDomain.custom_cert_resolver;
|
||||
preferWildcardCert = !!(configDomain.prefer_wildcard_cert);
|
||||
}
|
||||
|
||||
// Priority 2: Override with database domain settings (if exists)
|
||||
let finalCertResolver: string | undefined;
|
||||
let finalCustomCertResolver: string | undefined;
|
||||
|
||||
if (resource.domainCertResolver) {
|
||||
finalCertResolver = resource.domainCertResolver;
|
||||
if (resource.domainCertResolver === "custom" && resource.domainCustomCertResolver) {
|
||||
finalCustomCertResolver = resource.domainCustomCertResolver;
|
||||
}
|
||||
} else {
|
||||
certResolver = configDomain.cert_resolver;
|
||||
preferWildcardCert = configDomain.prefer_wildcard_cert;
|
||||
// Fall back to config
|
||||
finalCertResolver = certResolverFromConfig;
|
||||
}
|
||||
|
||||
// Resolve the final resolver name
|
||||
let resolverName: string | undefined;
|
||||
|
||||
if (finalCertResolver) {
|
||||
if (finalCertResolver === "custom") {
|
||||
// Check database custom resolver first, then config
|
||||
const customResolver = finalCustomCertResolver || configDomain?.custom_cert_resolver;
|
||||
|
||||
if (customResolver && typeof customResolver === "string" && customResolver.trim()) {
|
||||
resolverName = customResolver.trim();
|
||||
} else {
|
||||
resolverName = globalDefaultResolver;
|
||||
logger.warn(
|
||||
`Domain ${resource.domainId} requested custom cert resolver but none set; falling back to global resolver ${resolverName}`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Validate against available resolvers
|
||||
if (
|
||||
availableResolvers.length === 0 ||
|
||||
availableResolvers.includes(finalCertResolver)
|
||||
) {
|
||||
resolverName = finalCertResolver;
|
||||
} else {
|
||||
logger.warn(
|
||||
`Unknown cert resolver "${finalCertResolver}" for domain ${resource.domainId}; falling back to global resolver.`
|
||||
);
|
||||
resolverName = globalDefaultResolver;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
resolverName = globalDefaultResolver;
|
||||
}
|
||||
|
||||
const tls = {
|
||||
certResolver: certResolver,
|
||||
certResolver: resolverName,
|
||||
...(preferWildcardCert
|
||||
? {
|
||||
domains: [
|
||||
|
||||
Reference in New Issue
Block a user