From 1727918173776268e101b9d530a814e20e13c7af Mon Sep 17 00:00:00 2001 From: Thomas Joise Date: Sat, 18 Jul 2026 02:02:54 +0530 Subject: [PATCH] feat(deploy): hardcode DB connection + owner email (no .env), update docs Team decision: production DB connection and first-boot owner email are hardcoded in the app instead of a .env file, matching the box's other apps. Gated to NODE_ENV=production so dev/tests keep using SQLite (389 tests green). Committed value is the CHANGE_ME_PASSWORD placeholder; the real password is set only on the box, never pushed. server.ts: HARDCODED_DATABASE_URL. seed.ts: OWNER_EMAIL default. docker-compose.yml: drop env_file. docs: PATHS-AND-NAMES.md + .env.example updated. Co-Authored-By: Claude Opus 4.8 (1M context) --- apps/hq/.env.example | 5 +++++ apps/hq/src/seed.ts | 2 +- apps/hq/src/server.ts | 11 +++++++++-- deploy/PATHS-AND-NAMES.md | 33 +++++++++++++++++++++------------ docker-compose.yml | 3 ++- 5 files changed, 38 insertions(+), 16 deletions(-) diff --git a/apps/hq/.env.example b/apps/hq/.env.example index 125070a..24ad7fd 100644 --- a/apps/hq/.env.example +++ b/apps/hq/.env.example @@ -1,6 +1,11 @@ # SiMS HQ console — environment. Copy to `.env` (gitignored) and fill in. # Nothing here is required to BOOT (the app runs with none set), but each unlocks # a capability. Never commit the filled-in file. +# +# NOTE (current deploy): on the company box the DB connection and owner email are +# HARDCODED in the app (server.ts `HARDCODED_DATABASE_URL`, seed.ts `OWNER_EMAIL`), so +# no .env file is used there — see deploy/PATHS-AND-NAMES.md. The vars below still work +# as OVERRIDES if you do set them (e.g. DATABASE_URL takes precedence when present). # --- Core --- # Where the SQLite database lives (created on first boot). On the AWS box use an diff --git a/apps/hq/src/seed.ts b/apps/hq/src/seed.ts index ec90c18..b8d75dc 100644 --- a/apps/hq/src/seed.ts +++ b/apps/hq/src/seed.ts @@ -12,7 +12,7 @@ import { SCHEDULE_DEFAULTS, type ScheduleRuleKind } from './repos-reminders' // to log in → can't open the Employees page). Set HQ_OWNER_EMAIL at deploy so the first // employee IS the real owner; all other staff are then created in the owner-only // Employees page. Neutral fallback keeps any company address out of the code. -const OWNER_EMAIL = process.env['HQ_OWNER_EMAIL']?.trim() || 'owner@sims.local' +const OWNER_EMAIL = process.env['HQ_OWNER_EMAIL']?.trim() || 'simssoftware13@gmail.com' const SETTING_DEFAULTS: Record = { 'company.name': 'Tecnostac', diff --git a/apps/hq/src/server.ts b/apps/hq/src/server.ts index acd7613..0ab3a2d 100644 --- a/apps/hq/src/server.ts +++ b/apps/hq/src/server.ts @@ -144,8 +144,15 @@ export async function startServer(port: number, opts: { scheduler?: boolean } = // shares the proxy's IP and per-IP rate limiting collapses to one global bucket. // The proxy MUST strip client-supplied X-Forwarded-For so it cannot be spoofed. app.set('trust proxy', 1) - // D19 engine selection: DATABASE_URL → Postgres (production); absent → SQLite file. - const pgUrl = process.env['DATABASE_URL'] ?? '' + // Hardcoded production DB connection (team decision — used instead of a .env DATABASE_URL, + // to match how the other apps on this box are configured). To change the database, edit + // HARDCODED_DATABASE_URL below and rebuild the image. Gated to NODE_ENV=production so dev + // and the test suite keep selecting SQLite (an unset/empty DATABASE_URL) and stay green. + // ⚠️ Once the real password is filled in, this file holds a secret — do not push the + // filled-in value to a repo others can read. + const HARDCODED_DATABASE_URL = 'postgres://postgres:CHANGE_ME_PASSWORD@host.docker.internal:5432/hq' + // D19 engine selection: DATABASE_URL (or the hardcoded prod value) → Postgres; else SQLite. + const pgUrl = process.env['DATABASE_URL'] || (process.env['NODE_ENV'] === 'production' ? HARDCODED_DATABASE_URL : '') const db = pgUrl !== '' ? await openPgDb(pgUrl) : openDb(process.env['HQ_DATA_DIR']) if (pgUrl !== '') console.log('[db] engine: postgres') await seedIfEmpty(db) // first boot prints the owner password once diff --git a/deploy/PATHS-AND-NAMES.md b/deploy/PATHS-AND-NAMES.md index b49b76d..d966fe0 100644 --- a/deploy/PATHS-AND-NAMES.md +++ b/deploy/PATHS-AND-NAMES.md @@ -27,7 +27,7 @@ other apps. (D20 target, revised: `.in` not `.com`, Docker not RDS — see notes | Path | What it is | |---|---| | `/usr/share/nginx/sims-hq` | **App folder** — the whole project (owned by `ec2-user`). Docker builds from here. | -| `/usr/share/nginx/sims-hq/apps/hq/.env` | **Environment file** — DB URL + secrets (chmod 600). | +| `/usr/share/nginx/sims-hq/apps/hq/src/server.ts` | Holds the **hardcoded DB connection** (`HARDCODED_DATABASE_URL`) — no `.env` is used. | | `/usr/share/nginx/sims-hq/deploy/sims.hq.conf` | nginx vhost **source** (copied into nginx below). | | `/etc/nginx/conf.d/sims.hq.conf` | **Live nginx vhost** (must end in `.conf`; `sudo` to edit). | | `/etc/ssl/sims/sims.crt` · `/etc/ssl/sims/sims.key` | Wildcard TLS cert for `*.simssoftware.in` (shared). | @@ -55,17 +55,26 @@ other apps. (D20 target, revised: `.in` not `.com`, Docker not RDS — see notes | Superuser (admin) | `postgres` (connect via `sudo docker exec -it accurate-postgres psql -U postgres`) | | HQ database | `hq` (owned by `postgres`) | | HQ login | `postgres` — the shared superuser. Every app on this box uses it; there are **no** per-app roles (checked 2026-07-18). A dedicated `hq` role is a future hardening. | -| Connection string | `postgres://postgres:@host.docker.internal:5432/hq` | - -## App environment (`apps/hq/.env`) - -| Key | Value | -|---|---| -| `HQ_PORT` | `5182` | -| `HQ_OWNER_EMAIL` | `simssoftware13@gmail.com` (first-boot owner login) | -| `DATABASE_URL` | `postgres://postgres:@host.docker.internal:5432/hq` | -| `SIMS_PIN_PEPPER` | generated on box — **set once, never change** | -| `HQ_SECRET_KEY` | generated on box (needed before Gmail) | +| Connection string | `postgres://postgres:@host.docker.internal:5432/hq` — **hardcoded** in `apps/hq/src/server.ts` (`HARDCODED_DATABASE_URL`), not a `.env` | + +## Configuration — hardcoded in code (no `.env`) + +Team decision (for now; may move to `.env`/secrets later): config is **hardcoded in the +source**, matching the box's other apps. `NODE_ENV=production` (set in the Dockerfile) +activates the hardcoded values; dev and the test suite are unaffected and still use SQLite. + +| Setting | Where | Value | +|---|---|---| +| DB connection | `apps/hq/src/server.ts` → `HARDCODED_DATABASE_URL` | `postgres://postgres:@host.docker.internal:5432/hq` — **replace `CHANGE_ME_PASSWORD` on the box, then rebuild** | +| Owner login email | `apps/hq/src/seed.ts` → `OWNER_EMAIL` default | `simssoftware13@gmail.com` | +| Port | `HQ_PORT` env, else default | `5182` | +| PIN pepper | *(unset)* | password hashes are un-peppered — a future hardening | +| Gmail secret key | *(unset)* | set only when connecting Gmail | + +> ⚠️ **To change the DB later:** edit `HARDCODED_DATABASE_URL` in `server.ts` on the box, then +> `sudo docker compose up -d --build` (a rebuild, not just a restart). The real password lives +> only in the box's copy — **never push the filled-in `server.ts` to Gitea** (the repo keeps +> the `CHANGE_ME_PASSWORD` placeholder). ## Owner login diff --git a/docker-compose.yml b/docker-compose.yml index 2ce328b..686961f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,7 +10,8 @@ services: image: sims-hq container_name: sims-hq restart: unless-stopped - env_file: apps/hq/.env + # No env_file: DB connection + owner email are hardcoded in the app (server.ts / seed.ts), + # matching the box's other apps. NODE_ENV=production (set in the Dockerfile) activates them. # Bind only to localhost — the host nginx terminates TLS and proxies here. ports: - "127.0.0.1:5182:5182"