diff --git a/.env.example b/.env.example index dba5c774..38fac0f0 100644 --- a/.env.example +++ b/.env.example @@ -64,6 +64,11 @@ PUBLIC_OBJECT_SEARCH_PATHS=/tx-public/public S3_BUCKET_PRIVATE=tx-private S3_BUCKET_PUBLIC=tx-public +# S3-compatible endpoint URL. For MinIO running in compose this is the +# in-network DNS name. For AWS S3 leave blank (the SDK uses the default +# regional endpoint). For Cloudflare R2 / Backblaze B2, set the vendor URL. +S3_ENDPOINT=http://minio:9000 + # MinIO root credentials. Used both as MINIO_ROOT_USER/PASSWORD and as the # API server's S3 access key. Change before first boot. S3_ACCESS_KEY_ID=tx-minio-admin @@ -72,6 +77,11 @@ S3_SECRET_ACCESS_KEY=change-me-minio-secret-min-20-chars # Region label is cosmetic for MinIO but @aws-sdk requires one. S3_REGION=us-east-1 +# Path-style addressing is required by MinIO and most non-AWS S3 backends. +# Set to "false" only when targeting real AWS S3 (which prefers virtual-host +# style). Defaults to "true" inside the API server. +S3_FORCE_PATH_STYLE=true + # Local-FS driver settings (only consulted when STORAGE_DRIVER=local). # Filesystem root for uploaded objects. Defaults to ./storage relative to # the API server's working directory. diff --git a/scripts/src/seed.ts b/scripts/src/seed.ts index b9bf47a8..db7bee89 100644 --- a/scripts/src/seed.ts +++ b/scripts/src/seed.ts @@ -89,19 +89,22 @@ async function main() { } } - // Create admin user. Passwords are read from env vars so seeded - // credentials never need to be committed; the dev-only fallbacks are - // safe for fresh local installs but unsafe in production. - const adminPassword = - process.env.SEED_ADMIN_PASSWORD ?? - (process.env.NODE_ENV === "production" - ? (() => { throw new Error("SEED_ADMIN_PASSWORD must be set in production"); })() - : "admin123"); - const userPassword = - process.env.SEED_USER_PASSWORD ?? - (process.env.NODE_ENV === "production" - ? (() => { throw new Error("SEED_USER_PASSWORD must be set in production"); })() - : "user123"); + // Create admin user. Passwords are read exclusively from env vars so + // credentials are never committed and never appear in source. Both vars + // are required in every environment (including local dev) — copy them + // into a local `.env` from `.env.example` before running the seed. + const adminPassword = process.env.SEED_ADMIN_PASSWORD; + const userPassword = process.env.SEED_USER_PASSWORD; + if (!adminPassword) { + throw new Error( + "SEED_ADMIN_PASSWORD must be set (see .env.example). Refusing to seed.", + ); + } + if (!userPassword) { + throw new Error( + "SEED_USER_PASSWORD must be set (see .env.example). Refusing to seed.", + ); + } const adminHash = await bcrypt.hash(adminPassword, 10); const [adminUser] = await db .insert(usersTable) @@ -865,9 +868,9 @@ async function main() { } console.log("\nāœ… Seeding complete!"); - console.log("\nDemo accounts:"); - console.log(` Admin: username=admin, password=${adminPassword}`); - console.log(` User: username=ahmed, password=${userPassword}`); + console.log("\nDemo accounts seeded (passwords from env, not logged):"); + console.log(" Admin: username=admin"); + console.log(" User: username=ahmed"); process.exit(0); }