diff --git a/CHANGELOG.md b/CHANGELOG.md index d42455e..97241e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,17 @@ for what changed inside the apps it composes. ## [Unreleased] +## [1.1.16] - 2026-07-18 + +### Bumped +- proxy -> [v1.1.14](https://github.com/theta42/proxy/releases/tag/v1.1.14) +- sso-manager-node -> [v1.1.14](https://github.com/theta42/sso-manager-node/releases/tag/v1.1.14) + +Both: bumped `@simpleworkjs/conf` to 1.2.0 and `jq-repeat` to 2.2.0. + +### Changed +- `./config/sso-secrets.js` and `./config/proxy-secrets.js` are now loaded via each app's `CONF_SECRETS` env var (set by the entrypoint) instead of being symlinked into `/app/conf/secrets.js` — neither container needs write access to its own `conf/` directory anymore. No change to the config file format or bind mounts; existing `./config/` directories keep working as-is. + ## [1.1.15] - 2026-07-17 ### Bumped @@ -195,7 +206,8 @@ First tagged release. Establishes the `vX.Y.Z` tag convention going forward. - proxy -> [v1.1.0](https://github.com/theta42/proxy/releases/tag/v1.1.0) - sso-manager-node -> [v1.1.0](https://github.com/theta42/sso-manager-node/releases/tag/v1.1.0) -[Unreleased]: https://github.com/theta42/theta-env/compare/v1.1.15...HEAD +[Unreleased]: https://github.com/theta42/theta-env/compare/v1.1.16...HEAD +[1.1.16]: https://github.com/theta42/theta-env/compare/v1.1.15...v1.1.16 [1.1.15]: https://github.com/theta42/theta-env/compare/v1.1.14...v1.1.15 [1.1.14]: https://github.com/theta42/theta-env/compare/v1.1.13...v1.1.14 [1.1.13]: https://github.com/theta42/theta-env/compare/v1.1.12...v1.1.13 diff --git a/README.md b/README.md index 3bd572d..80a792b 100644 --- a/README.md +++ b/README.md @@ -172,7 +172,8 @@ operator-owned and `setup.env` is ignored. ### Configuration — `./config/` (no `.env` files) All config and secrets live in a bind-mounted `./config/` directory (gitignored), -read by each app's `@simpleworkjs/conf` from a symlinked `secrets.js`: +read by each app's `@simpleworkjs/conf` via the `CONF_SECRETS` env var, which +the entrypoint points at the mounted file: - **`./config/sso-secrets.js`** — SSO config: `ldap` (base, admin password, user/group bases), `oauth` (issuer, `jwtSecret`), `smtp`, `name`, plus diff --git a/docker-compose.yml b/docker-compose.yml index 9971f49..aebf56e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -13,11 +13,12 @@ # Config + secrets live in bind-mounted ./config/ (gitignored): # ./config/sso-secrets.js — SSO app + orchestrator config # ./config/proxy-secrets.js — proxy OIDC/LDAP/auth config -# Each app's entrypoint symlinks its file into /app/conf/secrets.js so -# @simpleworkjs/conf reads it. No app_* env is passed (app_* env would override -# secrets.js). The sso-manager mounts ./config read-write so the bootstrap can -# write the generated OAuth client creds back into proxy-secrets.js; the proxy -# mounts it read-only. +# Each app's entrypoint points CONF_SECRETS at its file so @simpleworkjs/conf +# (>= 1.2.0) reads it directly -- no app_* env is passed (app_* env would +# override secrets.js), and no write access to /app/conf is needed. The +# sso-manager mounts ./config read-write so the bootstrap can write the +# generated OAuth client creds back into proxy-secrets.js; the proxy mounts +# it read-only. # # Compose only interpolates the port defaults below — there is no .env file. # First-run wiring (LDAP service account, first admin, OAuth client) is @@ -56,7 +57,7 @@ services: volumes: # Operator-edited SSO secrets (sso-secrets.js). Read-WRITE so the bootstrap # can write the generated OAuth client creds into proxy-secrets.js. The - # entrypoint symlinks /config/sso-secrets.js -> /app/conf/secrets.js. + # entrypoint points CONF_SECRETS at /config/sso-secrets.js. - ./config:/config # Persist the LDAP database across container recreation. - ldap-data:/var/lib/ldap @@ -108,7 +109,7 @@ services: volumes: # Operator-edited proxy secrets (proxy-secrets.js). READ-ONLY — the proxy # only reads it; the sso-manager bootstrap writes the OAuth creds. The - # entrypoint symlinks /config/proxy-secrets.js -> /app/conf/secrets.js. + # entrypoint points CONF_SECRETS at /config/proxy-secrets.js. - ./config:/config:ro # Persist Redis (AOF + RDB) so Host records, permissions, DNS creds, local # users, AND the auto-ssl Let's Encrypt certs survive container recreation. diff --git a/docs/architecture.md b/docs/architecture.md index 189bcc9..2bce8e4 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -102,9 +102,9 @@ inputs from the bind-mounted `./config/sso-secrets.js` + `./config/proxy-secrets read-only). If `proxy-secrets.js` already holds a `clientId`+`clientSecret` matching an existing client, they are kept; if the client exists but the file has no usable secret, the secret is rotated and written back. -6. **Build + start the proxy**, wait for `/health`. The proxy entrypoint symlinks - `./config/proxy-secrets.js` to `/app/conf/secrets.js`, so `@simpleworkjs/conf` - (≥1.1.0) reads the OAuth creds + LDAP bind creds from the file. +6. **Build + start the proxy**, wait for `/health`. The proxy entrypoint points + `CONF_SECRETS` at `./config/proxy-secrets.js`, so `@simpleworkjs/conf` + (≥1.2.0) reads the OAuth creds + LDAP bind creds from the file. 7. **Register `` and `` as Host records in the proxy** — `setup.sh` runs a short script inside the proxy container that calls its Host model directly (`Host.create({host, ip, targetPort, ...})`), rather @@ -123,19 +123,20 @@ inputs from the bind-mounted `./config/sso-secrets.js` + `./config/proxy-secrets ### How config reaches the apps (no `.env`) All config and secrets live in `./config/` (gitignored, bind-mounted). Each -entrypoint symlinks its file to `/app/conf/secrets.js` early, before the app -starts: +entrypoint points the `CONF_SECRETS` env var (`@simpleworkjs/conf` >= 1.2.0) +at its file early, before the app starts: ``` -./config/sso-secrets.js -> sso-manager:/app/conf/secrets.js (./config RW) -./config/proxy-secrets.js -> proxy:/app/conf/secrets.js (./config RO) +CONF_SECRETS=/config/sso-secrets.js (sso-manager, ./config RW) +CONF_SECRETS=/config/proxy-secrets.js (proxy, ./config RO) ``` -`@simpleworkjs/conf` loads `conf/base.js → .js → conf/secrets.js → app_* -env`, where **env beats `secrets.js`**. So compose passes **no `app_*` env vars** -(only `NODE_ENV`, `NODE_PORT`) — that makes `secrets.js` authoritative. The SSO -entrypoint reads the few values it needs at startup (LDAP base DN, admin -password, JWT secret, cert CN) from `secrets.js` via an in-container `node` call. +`@simpleworkjs/conf` loads `conf/base.js → .js → secrets file → app_* +env`, where **env beats the secrets file**. So compose passes **no `app_*` env +vars** (only `NODE_ENV`, `NODE_PORT`) — that makes the secrets file +authoritative. The SSO entrypoint reads the few values it needs at startup +(LDAP base DN, admin password, JWT secret, cert CN) from `sso-secrets.js` via +an in-container `node` call. ### Why not `require` the SSO's internal models? diff --git a/docs/standalone.md b/docs/standalone.md index d5b66fd..0ae170f 100644 --- a/docs/standalone.md +++ b/docs/standalone.md @@ -25,18 +25,18 @@ mkdir -p config && cp secrets.js.example config/sso-secrets.js # edit it docker compose up -d --build ``` -The entrypoint symlinks `config/sso-secrets.js` to `nodejs/conf/secrets.js` so +The entrypoint points the `CONF_SECRETS` env var at `config/sso-secrets.js` so `@simpleworkjs/conf` reads it. Set `ldap.bindPassword`, `oauth.jwtSecret`, and the `stack`/`bootstrap` keys (the app ignores the ones it doesn't use). Pass -**no `app_*` env** — env beats `secrets.js`, so `app_*` would silently override -your file. +**no `app_*` env** — env beats the secrets file, so `app_*` would silently +override your file. - Web UI: `http://localhost:3001` - Health: `http://localhost:3001/health` - OIDC discovery: `http://localhost:3001/.well-known/openid-configuration` - LDAPS: `ldaps://:636` -Requires `@simpleworkjs/conf` >= 1.1.0. Full reference: +Requires `@simpleworkjs/conf` >= 1.2.0. Full reference: [SSO Manager deployment docs](https://theta42.github.io/sso-manager-node/deployment.html). ### Bare metal @@ -62,11 +62,11 @@ mkdir -p config && cp secrets.js.example config/proxy-secrets.js # edit it docker compose up -d --build ``` -The entrypoint symlinks `config/proxy-secrets.js` to `nodejs/conf/secrets.js` so -`@simpleworkjs/conf` reads it. Fill in `oidc` (your SSO's endpoints + +The entrypoint points the `CONF_SECRETS` env var at `config/proxy-secrets.js` +so `@simpleworkjs/conf` reads it. Fill in `oidc` (your SSO's endpoints + `clientId`/`clientSecret`/`redirectUri`), `ldap` (bind creds + search base), and -`auth` (admin groups/users). Pass **no `app_*` env** — env beats `secrets.js`, -so `app_*` would silently override your file. +`auth` (admin groups/users). Pass **no `app_*` env** — env beats the secrets +file, so `app_*` would silently override your file. - Proxy (public, auto-SSL): `https:///` - Mgmt UI / API: `http://127.0.0.1:3000/` diff --git a/proxy b/proxy index b9bdf36..f0eadbc 160000 --- a/proxy +++ b/proxy @@ -1 +1 @@ -Subproject commit b9bdf366385a8c3dc758d03e96afb7396752ff93 +Subproject commit f0eadbc2d79b90d72dddbcc6ff97652e3d913b22 diff --git a/setup.sh b/setup.sh index 3ea1355..fd3ce49 100755 --- a/setup.sh +++ b/setup.sh @@ -220,7 +220,7 @@ write_sso_secrets() { cat > "$CONFIG_DIR/sso-secrets.js" < "$CONFIG_DIR/proxy-secrets.js" <