feat(domains): add custom certificate resolver support

- Extend domain configuration to support custom certificate resolvers
- Add new "custom" certificate type option in domain forms
- Update database schema and validation to include custom certificate resolver
- Implement custom certificate resolver handling in Traefik and Docker domain configurations
- Enhance domain management with more flexible SSL/TLS certificate options
This commit is contained in:
Mauricio Siu
2025-03-08 20:46:31 -06:00
parent 4730845a40
commit cc8ffca4d4
12 changed files with 5367 additions and 67 deletions

View File

@@ -41,6 +41,7 @@ export const domains = pgTable("domain", {
composeId: text("composeId").references(() => compose.composeId, {
onDelete: "cascade",
}),
customCertResolver: text("customCertResolver"),
applicationId: text("applicationId").references(
() => applications.applicationId,
{ onDelete: "cascade" },
@@ -76,6 +77,7 @@ export const apiCreateDomain = createSchema.pick({
https: true,
applicationId: true,
certificateType: true,
customCertResolver: true,
composeId: true,
serviceName: true,
domainType: true,
@@ -107,6 +109,7 @@ export const apiUpdateDomain = createSchema
port: true,
https: true,
certificateType: true,
customCertResolver: true,
serviceName: true,
domainType: true,
})

View File

@@ -10,4 +10,5 @@ export const applicationStatus = pgEnum("applicationStatus", [
export const certificateType = pgEnum("certificateType", [
"letsencrypt",
"none",
"custom",
]);

View File

@@ -10,7 +10,8 @@ export const domain = z
.max(65535, { message: "Port must be 65535 or below" })
.optional(),
https: z.boolean().optional(),
certificateType: z.enum(["letsencrypt", "none"]).optional(),
certificateType: z.enum(["letsencrypt", "none", "custom"]).optional(),
customCertResolver: z.string(),
})
.superRefine((input, ctx) => {
if (input.https && !input.certificateType) {
@@ -20,6 +21,14 @@ export const domain = z
message: "Required",
});
}
if (input.certificateType === "custom" && !input.customCertResolver) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
path: ["customCertResolver"],
message: "Required when certificate type is custom",
});
}
});
export const domainCompose = z
@@ -32,7 +41,8 @@ export const domainCompose = z
.max(65535, { message: "Port must be 65535 or below" })
.optional(),
https: z.boolean().optional(),
certificateType: z.enum(["letsencrypt", "none"]).optional(),
certificateType: z.enum(["letsencrypt", "none", "custom"]).optional(),
customCertResolver: z.string(),
serviceName: z.string().min(1, { message: "Service name is required" }),
})
.superRefine((input, ctx) => {
@@ -43,4 +53,12 @@ export const domainCompose = z
message: "Required",
});
}
if (input.certificateType === "custom" && !input.customCertResolver) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
path: ["customCertResolver"],
message: "Required when certificate type is custom",
});
}
});