Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 30146e9588 | |||
| 481602ae60 | |||
| 26b853e1d6 | |||
| 04a9c557e8 | |||
| d1136a98a6 | |||
| 33f603dcc0 | |||
| f3a5194104 | |||
| d21dfefc37 |
+59
-1
@@ -10,6 +10,60 @@ for what changed inside the apps it composes.
|
|||||||
|
|
||||||
## [Unreleased]
|
## [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
|
||||||
|
- proxy -> [v1.1.13](https://github.com/theta42/proxy/releases/tag/v1.1.13)
|
||||||
|
- sso-manager-node -> [v1.1.13](https://github.com/theta42/sso-manager-node/releases/tag/v1.1.13)
|
||||||
|
|
||||||
|
proxy:
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- The host edit form's "Parent Wildcard" option stayed greyed out even when a valid wildcard actually existed for that host, so an already-created host could never be switched onto one from the edit modal (only brand-new hosts, via the field's `keyup` handler, ever saw it become available). The underlying `/host/lookup/:item` check also had the same self-match issue as the recently-fixed backend bug: it resolved an already-existing host to its own record instead of a sibling wildcard. Added a dedicated `/host/wildcard-parent/:item` endpoint that checks both directions, and the edit form now actually runs the check when it opens.
|
||||||
|
- Fixed an nginx startup warning: `the "listen ... http2" directive is deprecated, use the "http2" directive instead`. Migrated to the standalone `http2 on;` directive (nginx 1.25.1+).
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Four new plain-language docs aimed at less technical readers, replacing the system-design-level Architecture/Installation docs as the target of most card help links: **Hosts & HTTPS**, **DNS Providers**, **Users, Groups & Permissions**, and **API Tokens**. Each links onward to the deeper technical reference for readers who want it; the technical docs link back the other way too. The personal-access-token card (previously missed entirely) now has a help link.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- The in-app docs viewer rendered every `docs/*.md` page with a garbled heading and a stray horizontal rule at the top — Jekyll front matter (meant only for the GitHub Pages build) was never stripped before being handed to the markdown renderer. Also fixed: cross-doc links never resolved in-app, since this viewer serves docs at `/docs/<slug>` with no `.html` suffix — they're now rewritten to the correct in-app URL (by registered slug, falling back to the doc's real filename), the same way image paths already were.
|
||||||
|
|
||||||
|
sso-manager-node:
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Three new plain-language docs aimed at less technical readers, replacing the schema-level LDAP/OAuth/API docs as the target of most card help links: **Accounts, Groups & Managers**, **Connecting Apps (SSO)**, and **API Tokens**. Each links onward to the deeper technical reference for readers who want it; the technical docs link back the other way too. The personal-access-token card (previously missed) now links to its own doc.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- The in-app docs viewer rendered every `docs/*.md` page with a garbled heading and a stray horizontal rule at the top — Jekyll front matter (meant only for the GitHub Pages build) was never stripped before being handed to the markdown renderer. Also fixed: cross-doc links (`ldap.html`, `index.html`, etc.) never resolved in-app, since this viewer serves docs at `/docs/<slug>` with no `.html` suffix — they're now rewritten to the correct in-app URL, the same way image paths already were.
|
||||||
|
- The new concept docs' cross-links (`concepts-accounts.html` etc.) are the correct, working URL on the Jekyll/GitHub Pages build (where the page's URL is its filename stem) but didn't resolve in the in-app docs viewer, which serves docs at a separate short slug (`/docs/accounts`). The in-app renderer now also resolves a doc's real filename as a fallback, so one link written in a doc works on both targets.
|
||||||
|
|
||||||
|
## [1.1.14] - 2026-07-17
|
||||||
|
|
||||||
|
### Bumped
|
||||||
|
- proxy -> [v1.1.11](https://github.com/theta42/proxy/releases/tag/v1.1.11)
|
||||||
|
- sso-manager-node -> [v1.1.11](https://github.com/theta42/sso-manager-node/releases/tag/v1.1.11)
|
||||||
|
|
||||||
|
Both: moved the help (❓) link out of the global header and onto each relevant card individually, so it deep-links straight to the doc that actually covers that card instead of one generic per-page guess.
|
||||||
|
|
||||||
|
## [1.1.13] - 2026-07-17
|
||||||
|
|
||||||
|
### Bumped
|
||||||
|
- proxy -> [v1.1.10](https://github.com/theta42/proxy/releases/tag/v1.1.10)
|
||||||
|
- sso-manager-node -> [v1.1.10](https://github.com/theta42/sso-manager-node/releases/tag/v1.1.10)
|
||||||
|
|
||||||
|
Both: added a help icon (❓) in the top-right header that deep-links to the doc most relevant to the current page, and made the in-app docs viewer (`/docs`) searchable (a simple line-substring search over the local doc set, no new dependency, still works with no internet access).
|
||||||
|
|
||||||
## [1.1.12] - 2026-07-17
|
## [1.1.12] - 2026-07-17
|
||||||
|
|
||||||
### Bumped
|
### Bumped
|
||||||
@@ -152,7 +206,11 @@ 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)
|
- 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)
|
- 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.12...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
|
||||||
[1.1.12]: https://github.com/theta42/theta-env/compare/v1.1.11...v1.1.12
|
[1.1.12]: https://github.com/theta42/theta-env/compare/v1.1.11...v1.1.12
|
||||||
[1.1.11]: https://github.com/theta42/theta-env/compare/v1.1.10...v1.1.11
|
[1.1.11]: https://github.com/theta42/theta-env/compare/v1.1.10...v1.1.11
|
||||||
[1.1.10]: https://github.com/theta42/theta-env/compare/v1.1.9...v1.1.10
|
[1.1.10]: https://github.com/theta42/theta-env/compare/v1.1.9...v1.1.10
|
||||||
|
|||||||
@@ -172,7 +172,8 @@ operator-owned and `setup.env` is ignored.
|
|||||||
### Configuration — `./config/` (no `.env` files)
|
### Configuration — `./config/` (no `.env` files)
|
||||||
|
|
||||||
All config and secrets live in a bind-mounted `./config/` directory (gitignored),
|
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,
|
- **`./config/sso-secrets.js`** — SSO config: `ldap` (base, admin password,
|
||||||
user/group bases), `oauth` (issuer, `jwtSecret`), `smtp`, `name`, plus
|
user/group bases), `oauth` (issuer, `jwtSecret`), `smtp`, `name`, plus
|
||||||
|
|||||||
+8
-7
@@ -13,11 +13,12 @@
|
|||||||
# Config + secrets live in bind-mounted ./config/ (gitignored):
|
# Config + secrets live in bind-mounted ./config/ (gitignored):
|
||||||
# ./config/sso-secrets.js — SSO app + orchestrator config
|
# ./config/sso-secrets.js — SSO app + orchestrator config
|
||||||
# ./config/proxy-secrets.js — proxy OIDC/LDAP/auth config
|
# ./config/proxy-secrets.js — proxy OIDC/LDAP/auth config
|
||||||
# Each app's entrypoint symlinks its file into /app/conf/secrets.js so
|
# Each app's entrypoint points CONF_SECRETS at its file so @simpleworkjs/conf
|
||||||
# @simpleworkjs/conf reads it. No app_* env is passed (app_* env would override
|
# (>= 1.2.0) reads it directly -- no app_* env is passed (app_* env would
|
||||||
# secrets.js). The sso-manager mounts ./config read-write so the bootstrap can
|
# override secrets.js), and no write access to /app/conf is needed. The
|
||||||
# write the generated OAuth client creds back into proxy-secrets.js; the proxy
|
# sso-manager mounts ./config read-write so the bootstrap can write the
|
||||||
# mounts it read-only.
|
# 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.
|
# Compose only interpolates the port defaults below — there is no .env file.
|
||||||
# First-run wiring (LDAP service account, first admin, OAuth client) is
|
# First-run wiring (LDAP service account, first admin, OAuth client) is
|
||||||
@@ -56,7 +57,7 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
# Operator-edited SSO secrets (sso-secrets.js). Read-WRITE so the bootstrap
|
# Operator-edited SSO secrets (sso-secrets.js). Read-WRITE so the bootstrap
|
||||||
# can write the generated OAuth client creds into proxy-secrets.js. The
|
# 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
|
- ./config:/config
|
||||||
# Persist the LDAP database across container recreation.
|
# Persist the LDAP database across container recreation.
|
||||||
- ldap-data:/var/lib/ldap
|
- ldap-data:/var/lib/ldap
|
||||||
@@ -108,7 +109,7 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
# Operator-edited proxy secrets (proxy-secrets.js). READ-ONLY — the proxy
|
# Operator-edited proxy secrets (proxy-secrets.js). READ-ONLY — the proxy
|
||||||
# only reads it; the sso-manager bootstrap writes the OAuth creds. The
|
# 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
|
- ./config:/config:ro
|
||||||
# Persist Redis (AOF + RDB) so Host records, permissions, DNS creds, local
|
# Persist Redis (AOF + RDB) so Host records, permissions, DNS creds, local
|
||||||
# users, AND the auto-ssl Let's Encrypt certs survive container recreation.
|
# users, AND the auto-ssl Let's Encrypt certs survive container recreation.
|
||||||
|
|||||||
+13
-12
@@ -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`
|
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
|
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.
|
has no usable secret, the secret is rotated and written back.
|
||||||
6. **Build + start the proxy**, wait for `/health`. The proxy entrypoint symlinks
|
6. **Build + start the proxy**, wait for `/health`. The proxy entrypoint points
|
||||||
`./config/proxy-secrets.js` to `/app/conf/secrets.js`, so `@simpleworkjs/conf`
|
`CONF_SECRETS` at `./config/proxy-secrets.js`, so `@simpleworkjs/conf`
|
||||||
(≥1.1.0) reads the OAuth creds + LDAP bind creds from the file.
|
(≥1.2.0) reads the OAuth creds + LDAP bind creds from the file.
|
||||||
7. **Register `<SSO_HOST>` and `<PROXY_HOST>` as Host records in the proxy** —
|
7. **Register `<SSO_HOST>` and `<PROXY_HOST>` as Host records in the proxy** —
|
||||||
`setup.sh` runs a short script inside the proxy container that calls its
|
`setup.sh` runs a short script inside the proxy container that calls its
|
||||||
Host model directly (`Host.create({host, ip, targetPort, ...})`), rather
|
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`)
|
### How config reaches the apps (no `.env`)
|
||||||
|
|
||||||
All config and secrets live in `./config/` (gitignored, bind-mounted). Each
|
All config and secrets live in `./config/` (gitignored, bind-mounted). Each
|
||||||
entrypoint symlinks its file to `/app/conf/secrets.js` early, before the app
|
entrypoint points the `CONF_SECRETS` env var (`@simpleworkjs/conf` >= 1.2.0)
|
||||||
starts:
|
at its file early, before the app starts:
|
||||||
|
|
||||||
```
|
```
|
||||||
./config/sso-secrets.js -> sso-manager:/app/conf/secrets.js (./config RW)
|
CONF_SECRETS=/config/sso-secrets.js (sso-manager, ./config RW)
|
||||||
./config/proxy-secrets.js -> proxy:/app/conf/secrets.js (./config RO)
|
CONF_SECRETS=/config/proxy-secrets.js (proxy, ./config RO)
|
||||||
```
|
```
|
||||||
|
|
||||||
`@simpleworkjs/conf` loads `conf/base.js → <env>.js → conf/secrets.js → app_*
|
`@simpleworkjs/conf` loads `conf/base.js → <env>.js → secrets file → app_*
|
||||||
env`, where **env beats `secrets.js`**. So compose passes **no `app_*` env vars**
|
env`, where **env beats the secrets file**. So compose passes **no `app_*` env
|
||||||
(only `NODE_ENV`, `NODE_PORT`) — that makes `secrets.js` authoritative. The SSO
|
vars** (only `NODE_ENV`, `NODE_PORT`) — that makes the secrets file
|
||||||
entrypoint reads the few values it needs at startup (LDAP base DN, admin
|
authoritative. The SSO entrypoint reads the few values it needs at startup
|
||||||
password, JWT secret, cert CN) from `secrets.js` via an in-container `node` call.
|
(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?
|
### Why not `require` the SSO's internal models?
|
||||||
|
|
||||||
|
|||||||
+8
-8
@@ -25,18 +25,18 @@ mkdir -p config && cp secrets.js.example config/sso-secrets.js # edit it
|
|||||||
docker compose up -d --build
|
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
|
`@simpleworkjs/conf` reads it. Set `ldap.bindPassword`, `oauth.jwtSecret`, and
|
||||||
the `stack`/`bootstrap` keys (the app ignores the ones it doesn't use). Pass
|
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
|
**no `app_*` env** — env beats the secrets file, so `app_*` would silently
|
||||||
your file.
|
override your file.
|
||||||
|
|
||||||
- Web UI: `http://localhost:3001`
|
- Web UI: `http://localhost:3001`
|
||||||
- Health: `http://localhost:3001/health`
|
- Health: `http://localhost:3001/health`
|
||||||
- OIDC discovery: `http://localhost:3001/.well-known/openid-configuration`
|
- OIDC discovery: `http://localhost:3001/.well-known/openid-configuration`
|
||||||
- LDAPS: `ldaps://<host>:636`
|
- LDAPS: `ldaps://<host>: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).
|
[SSO Manager deployment docs](https://theta42.github.io/sso-manager-node/deployment.html).
|
||||||
|
|
||||||
### Bare metal
|
### Bare metal
|
||||||
@@ -62,11 +62,11 @@ mkdir -p config && cp secrets.js.example config/proxy-secrets.js # edit it
|
|||||||
docker compose up -d --build
|
docker compose up -d --build
|
||||||
```
|
```
|
||||||
|
|
||||||
The entrypoint symlinks `config/proxy-secrets.js` to `nodejs/conf/secrets.js` so
|
The entrypoint points the `CONF_SECRETS` env var at `config/proxy-secrets.js`
|
||||||
`@simpleworkjs/conf` reads it. Fill in `oidc` (your SSO's endpoints +
|
so `@simpleworkjs/conf` reads it. Fill in `oidc` (your SSO's endpoints +
|
||||||
`clientId`/`clientSecret`/`redirectUri`), `ldap` (bind creds + search base), and
|
`clientId`/`clientSecret`/`redirectUri`), `ldap` (bind creds + search base), and
|
||||||
`auth` (admin groups/users). Pass **no `app_*` env** — env beats `secrets.js`,
|
`auth` (admin groups/users). Pass **no `app_*` env** — env beats the secrets
|
||||||
so `app_*` would silently override your file.
|
file, so `app_*` would silently override your file.
|
||||||
|
|
||||||
- Proxy (public, auto-SSL): `https://<host>/`
|
- Proxy (public, auto-SSL): `https://<host>/`
|
||||||
- Mgmt UI / API: `http://127.0.0.1:3000/`
|
- Mgmt UI / API: `http://127.0.0.1:3000/`
|
||||||
|
|||||||
+1
-1
Submodule proxy updated: 876ea6cfd0...f0eadbc2d7
@@ -220,7 +220,7 @@ write_sso_secrets() {
|
|||||||
cat > "$CONFIG_DIR/sso-secrets.js" <<SSOEOF
|
cat > "$CONFIG_DIR/sso-secrets.js" <<SSOEOF
|
||||||
'use strict';
|
'use strict';
|
||||||
// Generated by setup.sh. Edit freely; re-run ./setup.sh to apply.
|
// Generated by setup.sh. Edit freely; re-run ./setup.sh to apply.
|
||||||
// The SSO app reads this via @simpleworkjs/conf (symlinked to conf/secrets.js).
|
// The SSO app reads this via @simpleworkjs/conf (CONF_SECRETS env var).
|
||||||
// The app ignores the extra stack/bootstrap/serviceAccountPass keys (read by
|
// The app ignores the extra stack/bootstrap/serviceAccountPass keys (read by
|
||||||
// the orchestrator). Back this file up off-host — it holds all SSO secrets.
|
// the orchestrator). Back this file up off-host — it holds all SSO secrets.
|
||||||
|
|
||||||
@@ -271,8 +271,8 @@ write_proxy_secrets() {
|
|||||||
local dn="$CFG_BASE_DN"
|
local dn="$CFG_BASE_DN"
|
||||||
cat > "$CONFIG_DIR/proxy-secrets.js" <<PROXYEOF
|
cat > "$CONFIG_DIR/proxy-secrets.js" <<PROXYEOF
|
||||||
'use strict';
|
'use strict';
|
||||||
// Generated by setup.sh. The proxy reads this via @simpleworkjs/conf (symlinked
|
// Generated by setup.sh. The proxy reads this via @simpleworkjs/conf (CONF_SECRETS
|
||||||
// to conf/secrets.js). clientId/clientSecret are filled in by the bootstrap
|
// env var). clientId/clientSecret are filled in by the bootstrap
|
||||||
// (run by ./setup.sh) — leave them as-is. ldap.bindPassword MUST equal
|
// (run by ./setup.sh) — leave them as-is. ldap.bindPassword MUST equal
|
||||||
// serviceAccountPass in sso-secrets.js (the proxy binds as that account).
|
// serviceAccountPass in sso-secrets.js (the proxy binds as that account).
|
||||||
|
|
||||||
|
|||||||
+1
-1
Submodule sso-manager-node updated: 96adf60cf7...c5a2c0a71d
Reference in New Issue
Block a user