diff --git a/.gitignore b/.gitignore index 8e974863..19d75ece 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ tsconfig.tsbuildinfo /caddy-data /caddy-config .DS_Store +/caddy-proxy-manager.wiki diff --git a/app/(dashboard)/proxy-hosts/actions.ts b/app/(dashboard)/proxy-hosts/actions.ts index df15d6d4..723da4a4 100644 --- a/app/(dashboard)/proxy-hosts/actions.ts +++ b/app/(dashboard)/proxy-hosts/actions.ts @@ -28,6 +28,18 @@ function parseOptionalText(value: FormDataEntryValue | null): string | null { return trimmed.length > 0 ? trimmed : null; } +function parseOptionalNumber(value: FormDataEntryValue | null): number | null { + if (!value || typeof value !== "string") { + return null; + } + const trimmed = value.trim(); + if (trimmed.length === 0) { + return null; + } + const num = Number(trimmed); + return isNaN(num) ? null : num; +} + function parseAuthentikConfig(formData: FormData): ProxyHostAuthentikInput | undefined { if (!formData.has("authentik_present")) { return undefined; @@ -90,8 +102,8 @@ export async function createProxyHostAction( name: String(formData.get("name") ?? "Untitled"), domains: parseCsv(formData.get("domains")), upstreams: parseCsv(formData.get("upstreams")), - certificate_id: formData.get("certificate_id") ? Number(formData.get("certificate_id")) : null, - access_list_id: formData.get("access_list_id") ? Number(formData.get("access_list_id")) : null, + certificate_id: parseOptionalNumber(formData.get("certificate_id")), + access_list_id: parseOptionalNumber(formData.get("access_list_id")), hsts_subdomains: parseCheckbox(formData.get("hsts_subdomains")), skip_https_hostname_validation: parseCheckbox(formData.get("skip_https_hostname_validation")), enabled: parseCheckbox(formData.get("enabled")), @@ -125,10 +137,10 @@ export async function updateProxyHostAction( domains: formData.get("domains") ? parseCsv(formData.get("domains")) : undefined, upstreams: formData.get("upstreams") ? parseCsv(formData.get("upstreams")) : undefined, certificate_id: formData.has("certificate_id") - ? (formData.get("certificate_id") ? Number(formData.get("certificate_id")) : null) + ? parseOptionalNumber(formData.get("certificate_id")) : undefined, access_list_id: formData.has("access_list_id") - ? (formData.get("access_list_id") ? Number(formData.get("access_list_id")) : null) + ? parseOptionalNumber(formData.get("access_list_id")) : undefined, hsts_subdomains: boolField("hsts_subdomains"), skip_https_hostname_validation: boolField("skip_https_hostname_validation"), diff --git a/src/lib/caddy.ts b/src/lib/caddy.ts index 908408dd..2b2cdadf 100644 --- a/src/lib/caddy.ts +++ b/src/lib/caddy.ts @@ -1,4 +1,4 @@ -import { chmodSync, mkdirSync, writeFileSync } from "node:fs"; +import { mkdirSync, writeFileSync } from "node:fs"; import { join } from "node:path"; import crypto from "node:crypto"; import db, { nowIso } from "./db"; @@ -14,11 +14,6 @@ import { const CERTS_DIR = process.env.CERTS_DIRECTORY || join(process.cwd(), "data", "certs"); mkdirSync(CERTS_DIR, { recursive: true, mode: 0o700 }); -try { - chmodSync(CERTS_DIR, 0o700); -} catch (error) { - console.warn("Unable to enforce restrictive permissions on certificate directory:", error); -} const DEFAULT_AUTHENTIK_HEADERS = [ "X-Authentik-Username", @@ -197,12 +192,6 @@ function writeCertificateFiles(cert: CertificateRow) { const keyPath = join(CERTS_DIR, `certificate-${cert.id}.key.pem`); writeFileSync(certPath, cert.certificate_pem, { encoding: "utf-8", mode: 0o600 }); writeFileSync(keyPath, cert.private_key_pem, { encoding: "utf-8", mode: 0o600 }); - try { - chmodSync(certPath, 0o600); - chmodSync(keyPath, 0o600); - } catch (error) { - console.warn("Unable to enforce restrictive permissions on certificate files:", error); - } return { certificate_file: certPath, key_file: keyPath }; }