diff --git a/.gitignore b/.gitignore index 52e8d75..315ecbb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ spire_ffi/target/ -.env -infra/.env +.env* +infra/.env* infra/compose*.yml .DS_Store node_modules/ diff --git a/infra/setup.ts b/infra/setup.ts index 8332a1e..81eed1e 100644 --- a/infra/setup.ts +++ b/infra/setup.ts @@ -4,6 +4,7 @@ import * as colors from "jsr:@std/fmt@0.225.2/colors"; import * as path from "jsr:@std/path@0.225.2"; const ENV_PATH = path.join("infra", ".env"); +const SPIRE_ENV_PATH = path.join("infra", ".env.spire"); const COMPOSE_PATH = path.join("infra", "compose.yml"); const SPIRE_COMPOSE_PATH = path.join("infra", "compose.spire.yml"); @@ -28,33 +29,33 @@ const DEFAULT_AUTH_CONFIG: AuthSetupConfig = { }; export async function readEnv(): Promise> { - try { - const text = await Deno.readTextFile(ENV_PATH); - const config: Partial = {}; - for (const line of text.split("\n")) { - const trimmed = line.trim(); - if (!trimmed || trimmed.startsWith("#")) continue; - const [key, ...rest] = trimmed.split("="); - const val = rest.join("=").trim(); - if (key === "REG") config.reg = val; - if (key === "GHCR_REG") config.ghcrReg = val; - if (key === "SYSTEM_DOMAIN") config.domainName = val; - if (key === "POSTGRES_PASSWORD") config.dbPassword = val; - if (key === "DB_DATA_PATH") config.dbDataPath = val; - if (key === "SPIRE_DATA_PATH") config.spireDataPath = val; - if (key === "APP_SECRET") config.appSecret = val; + const config: Partial = {}; + for (const filePath of [ENV_PATH, SPIRE_ENV_PATH]) { + try { + const text = await Deno.readTextFile(filePath); + for (const line of text.split("\n")) { + const trimmed = line.trim(); + if (!trimmed || trimmed.startsWith("#")) continue; + const [key, ...rest] = trimmed.split("="); + const val = rest.join("=").trim(); + if (key === "REG") config.reg = val; + if (key === "GHCR_REG") config.ghcrReg = val; + if (key === "SYSTEM_DOMAIN") config.domainName = val; + if (key === "POSTGRES_PASSWORD") config.dbPassword = val; + if (key === "DB_DATA_PATH") config.dbDataPath = val; + if (key === "SPIRE_DATA_PATH") config.spireDataPath = val; + if (key === "APP_SECRET") config.appSecret = val; + } + } catch (_e) { + // Ignore and check next } - return config; - } catch (_e) { - // Ignore and check next - return {}; } + return config; } export function generateEnv(config: AuthSetupConfig): string { return `# --- Container Registry --- REG=${config.reg} -GHCR_REG=${config.ghcrReg || "ghcr.atyg.org"} # --- Network & Routing --- SYSTEM_DOMAIN=${config.domainName} @@ -72,9 +73,6 @@ POSTGRES_DB=authdb POSTGRES_PASSWORD=${config.dbPassword} DB_DATA_PATH=${config.dbDataPath || "/volume1/docker/auth-yes/data"} -# --- SPIRE Configuration --- -SPIRE_DATA_PATH=${config.spireDataPath || "/volume1/docker/spire"} - # --- Valkey Configuration --- VALKEY_HOST=auth-valkey VALKEY_PORT=6379 @@ -82,6 +80,16 @@ VALKEY_URL=redis://auth-valkey:6379 `; } +export function generateSpireEnv(config: AuthSetupConfig): string { + return `# --- Container Registry --- +REG=${config.reg} +GHCR_REG=${config.ghcrReg || "ghcr.atyg.org"} + +# --- SPIRE Storage & Persistence --- +SPIRE_DATA_PATH=${config.spireDataPath || "/volume1/docker/spire"} +`; +} + export function generateDockerCompose(): string { return `version: "3.8" @@ -262,6 +270,9 @@ export async function generateAuthSetupFiles( const envContent = generateEnv(config); await Deno.writeTextFile(ENV_PATH, envContent); + const spireEnvContent = generateSpireEnv(config); + await Deno.writeTextFile(SPIRE_ENV_PATH, spireEnvContent); + const composeContent = generateDockerCompose(); await Deno.writeTextFile(COMPOSE_PATH, composeContent); @@ -270,15 +281,18 @@ export async function generateAuthSetupFiles( console.log( colors.green( - `\n✓ Successfully generated ${ENV_PATH}, ${COMPOSE_PATH}, and ${SPIRE_COMPOSE_PATH}!`, + `\n✓ Successfully generated ${ENV_PATH}, ${SPIRE_ENV_PATH}, ${COMPOSE_PATH}, and ${SPIRE_COMPOSE_PATH}!`, ), ); console.log( - colors.green("Setup complete. You may now deploy your stack by running:\n"), + colors.green("Setup complete. You may deploy your stacks by running:\n"), ); console.log( colors.cyan( - "podman-compose --project-name auth-yes --env-file infra/.env -f infra/compose.yml up -d\n", + "1. Deploy SPIRE Stack:\n" + + " podman-compose --project-name spire --env-file infra/.env.spire -f infra/compose.spire.yml up -d\n\n" + + "2. Deploy Auth-Yes Stack:\n" + + " podman-compose --project-name auth-yes --env-file infra/.env -f infra/compose.yml up -d\n", ), ); } @@ -713,7 +727,10 @@ if (import.meta.main) { ); console.log(generateSpireDockerCompose()); }) - .command("dump_env", "Output current environment configuration (.env)") + .command( + "dump_env", + "Output current environment configuration (.env and .env.spire)", + ) .action(async () => { const loadedEnv = await readEnv(); const currentConfig: AuthSetupConfig = { @@ -729,7 +746,7 @@ if (import.meta.main) { ); console.log( colors.bold( - colors.green(" ENVIRONMENT CONFIGURATION (infra/.env)"), + colors.green(" STACK 1: Auth-Yes Environment (infra/.env)"), ), ); console.log( @@ -740,6 +757,28 @@ if (import.meta.main) { ), ); console.log(generateEnv(currentConfig)); + console.log( + colors.bold( + colors.blue( + "================================================================", + ), + ), + ); + console.log( + colors.bold( + colors.green( + " STACK 2: SPIRE Stack Environment (infra/.env.spire)", + ), + ), + ); + console.log( + colors.bold( + colors.blue( + "================================================================\n", + ), + ), + ); + console.log(generateSpireEnv(currentConfig)); }) .command("secrets", "Inspect secrets status and persistence paths") .action(async () => { @@ -768,7 +807,7 @@ if (import.meta.main) { console.log( `${ colors.cyan("Local Artifact Files:") - } ${ENV_PATH}, ${COMPOSE_PATH}, ${SPIRE_COMPOSE_PATH}`, + } ${ENV_PATH}, ${SPIRE_ENV_PATH}, ${COMPOSE_PATH}, ${SPIRE_COMPOSE_PATH}`, ); console.log( `${colors.cyan("PostgreSQL Password:")} ${ @@ -910,7 +949,7 @@ if (import.meta.main) { console.log(colors.gray("\n# 4. Deploy fresh stacks:")); console.log( colors.cyan( - "podman-compose --project-name spire --env-file infra/.env -f infra/compose.spire.yml up -d", + "podman-compose --project-name spire --env-file infra/.env.spire -f infra/compose.spire.yml up -d", ), ); console.log( @@ -947,12 +986,12 @@ if (import.meta.main) { ); console.log( colors.cyan( - "podman-compose --project-name spire --env-file infra/.env -f infra/compose.spire.yml pull", + "podman-compose --project-name spire --env-file infra/.env.spire -f infra/compose.spire.yml pull", ), ); console.log( colors.cyan( - "podman-compose --project-name spire --env-file infra/.env -f infra/compose.spire.yml up -d\n", + "podman-compose --project-name spire --env-file infra/.env.spire -f infra/compose.spire.yml up -d\n", ), ); console.log(