411 Commits

Author SHA1 Message Date
wmantly df5e5e1f56 Bump sso-manager-node: 3rd-party LDAP integration docs
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 17:27:20 -04:00
wmantly 1fab34b6ec Merge pull request #36 from theta42/bump-sso-notification-safety
Bump sso-manager-node: notification Compose safety fixes
2026-07-15 17:04:54 -04:00
wmantly cc8e83f42f Bump sso-manager-node: notification Compose safety fixes
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 17:03:46 -04:00
wmantly af68c73629 Merge pull request #35 from theta42/bump-submodules-marketing-pages
Bump proxy and sso-manager-node: marketing landing pages
2026-07-15 16:11:19 -04:00
wmantly 69e02cc121 Bump proxy and sso-manager-node: marketing landing pages
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 16:10:55 -04:00
wmantly ee79b3888b Merge pull request #34 from theta42/marketing-pages
Turn GitHub Pages into a marketing landing page
2026-07-15 16:09:50 -04:00
wmantly fb2d1486c1 Turn GitHub Pages into a marketing landing page; cross-link, drop download buttons
- Rewrite docs/index.md as a short landing page (what it is, screenshots,
  why this over running the two separately, what you get, a minimal
  "get it" snippet) instead of a full config/architecture reference --
  that content still lives in the repo (README, docs/*.md), linked from
  here.
- Cross-link to SSO Manager's and Proxy's own Pages sites.
- Screenshots are now clickable (open full size) on both the Pages site
  and the README.
- Disable show_downloads in docs/_config.yml -- the Cayman theme's
  "Download .zip/.tar.gz" buttons are gone; "View on GitHub" (which links
  back to the repo) is the only header link now.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 16:08:53 -04:00
wmantly f7ae7c5ec7 Merge pull request #33 from theta42/bump-submodules-docs
Bump proxy and sso-manager-node: README/docs screenshots
2026-07-15 15:47:32 -04:00
wmantly a9f9ff00ab Bump proxy and sso-manager-node: README/docs screenshots
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 15:46:01 -04:00
wmantly 6b7488cb0a Merge pull request #32 from theta42/docs-screenshots
Add Documentation link + screenshots to README and docs site
2026-07-15 15:44:58 -04:00
wmantly 7e679928ce Add Documentation link + screenshots to README and docs site
theta-env's GitHub Pages site (docs/, Jekyll) was already configured and
live at https://theta42.github.io/theta-env/ but nothing in the README
linked to it, unlike proxy and sso-manager-node's READMEs -- easy to miss
entirely. Add the same top-of-README Documentation link, plus screenshots
of the composed stack (SSO dashboard + proxy host list from one
./setup.sh run). Also fixes a stale docs/index.md quickstart snippet that
said "set CFG_BASE_DN to your domain" -- CFG_DOMAIN is the actual
required variable (CFG_BASE_DN is an advanced override); everywhere else
in the docs already says CFG_DOMAIN correctly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 15:42:19 -04:00
wmantly 1bf3f63619 Merge pull request #31 from theta42/bump-sso-remove-services-card
Bump sso-manager-node: remove hardcoded Services card
2026-07-15 01:00:37 -04:00
wmantly 192c5a3c6e Bump sso-manager-node: remove hardcoded Services card
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 01:00:12 -04:00
wmantly bc0f7ae6a1 Merge pull request #30 from theta42/bump-submodules-auth-oauth-perf
Bump proxy and sso-manager-node: auth exclusivity, OAuth wildcard redirect_uri, perf fixes
2026-07-15 00:49:33 -04:00
wmantly 32684d5d35 Bump proxy and sso-manager-node: mutually-exclusive host auth, OAuth wildcard redirect_uri, and performance fixes
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 00:48:59 -04:00
wmantly a61ad10262 Merge pull request #29 from theta42/bump-submodules-nav-unification
Bump proxy and sso-manager-node: unified nav bars
2026-07-14 23:51:04 -04:00
wmantly fc9528f4ba Bump proxy and sso-manager-node: unified nav bars
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 23:50:44 -04:00
wmantly 57040bd62a Bump sso-manager-node submodule to pick up the uid/gidNumber fix (#28)
sso-manager-node: 38cc669 -> f45349e (#44) — fixes a crash that broke
every user creation on a theta-env-bootstrapped install
(InvalidSyntaxError on gidNumber), and adds a configurable id floor so
real users start at uidNumber/gidNumber 1500 instead of colliding with
or following the bootstrap admin's reserved 10000.
2026-07-14 23:06:13 -04:00
wmantly 189980d862 Bump proxy + sso-manager-node submodules to latest master (#27)
proxy: 22f382b -> c68fcc9 (#133) — sticky footer fix, Docker commit
hash baked in (incl. submodule GIT_COMMIT build-arg support),
configurable local admin password.
sso-manager-node: f72e888 -> 38cc669 (#43) — Docker commit hash baked
in (incl. submodule GIT_COMMIT build-arg support).

Together with the already-merged theta-env#26, a fresh ./setup.sh run
now generates + prints the proxy's local admin password and bakes
real commit hashes into both images instead of "unknown".
2026-07-14 22:34:25 -04:00
wmantly 9ca3b1a113 Generate the proxy's local admin password, and bake real commit hashes (#26)
Two related fixes found while testing the Docker build:

1. Print the proxy's local anti-lockout admin (proxyadmin2) password
   in the summary. Previously this account was always created with
   username == password == "proxyadmin2" (a hardcoded proxy default —
   see theta42/proxy#133), and setup.sh had no way to know or surface
   whatever password ended up in use. Now generates a random
   CFG_PROXY_ADMIN_PASS the same way it already does for the SSO
   admin, writes it into proxy-secrets.js's auth.localAdminPass (read
   by the proxy once, on first creation of that account), and prints
   it in the final summary. read_config_kv() reads it back from
   proxy-secrets.js so this works correctly on re-runs too (config
   already exists -> ensure_config's early-return path never sets
   CFG_PROXY_ADMIN_PASS in that run's shell, same reasoning as the
   existing SSO_HOST/PROXY_HOST/ADMIN_PASS readback).

2. Pass GIT_COMMIT build-args so the proxy/sso-manager images bake in
   their real commit hash instead of "unknown". Both submodules' .git
   is a pointer file, not a real repo, so the images can never resolve
   their own commit from inside the Docker build context no matter
   what (see theta42/proxy#133 and theta42/sso-manager-node#43) --
   only the host, where the submodule resolves correctly, can compute
   it. setup.sh does that with `git -C <submodule> rev-parse --short
   HEAD` right before each build and exports it for docker-compose.yml
   to pick up.

Verified end to end against a real ./setup.sh run (not just docker
build in isolation):
- Local admin password printed on first run, logs in successfully;
  the DEFAULT ("proxyadmin2"/"proxyadmin2") correctly does NOT.
- Re-running prints the SAME password (confirms the readback path
  works on re-runs, not just first-run).
- `docker exec proxy cat /app/.build_commit` and the equivalent for
  sso-manager both match `git -C <submodule> rev-parse --short HEAD`
  on the host — footer now shows the real hash instead of "unknown".
2026-07-14 22:32:44 -04:00
wmantly ecdd7ee9bd Bump proxy submodule to pick up the SSL fallback fix (#25)
proxy: 8aab9c7 -> 22f382b (#132) — fixes a TLS handshake failure that
broke SSL (including the self-signed fallback cert) for any
connection without an already-known target, e.g. no SNI at all or an
unregistered host. This affects every fresh theta-env install before
DNS/Host records are set up, so it's worth its own bump rather than
waiting to batch with other changes.
2026-07-14 21:34:57 -04:00
wmantly 4f011cbb69 Bump proxy + sso-manager-node submodules to latest master (#24)
proxy: 9d34ff9 -> 8aab9c7 — mobile table-responsive fixes (#131).
sso-manager-node: 3ceeeee -> f72e888 — mobile table-responsive +
group filter bar flex-wrap fixes (#42).
2026-07-14 21:19:39 -04:00
wmantly 5982d44a4a Merge pull request #23 from theta42/chore/bump-submodules-3
Bump proxy + sso-manager-node submodules to latest master
2026-07-14 21:00:02 -04:00
wmantly 8e5b9cd05f Bump proxy + sso-manager-node submodules to latest master
proxy: 1c7ad9a -> 9d34ff9 — target-hostname validation (#126), DuckDNS
domains/subdomains field-collision fix (#127), DuckDNS subdomain
double-suffix fix (#128), DnsProvider.create Domain key mismatch +
rollback fix (#129), footer added (#130).
sso-manager-node: 3d3b15b -> 3ceeeee — footer cleanup (#41).
2026-07-14 20:58:44 -04:00
wmantly 8f9e68bf5e Merge pull request #22 from theta42/feat/setup-self-update
setup.sh: pull theta-env itself before doing anything else
2026-07-14 11:39:38 -04:00
wmantly 79051b96e3 setup.sh: pull theta-env itself before doing anything else
Step 1 (submodule update) only refreshes proxy/sso-manager-node — it
never pulls setup.sh or this repo's own files. So on an existing
deployment, running ./setup.sh alone would build fresh submodule code
but execute a stale copy of the orchestration script itself (missing
whatever fixes landed in it, e.g. the CFG_DOMAIN rename or the
Host-registration step), unless the operator remembered to `git pull`
theta-env manually first.

Add a step 0 that fast-forwards the current branch to its upstream
before anything else runs, then re-execs the script so the rest of
the run uses the freshly-pulled version rather than the copy already
read into memory. Never blocks the run: skips silently if this isn't
a git checkout, is on a detached HEAD, or has no upstream configured
(all normal for e.g. a tarball download); warns and continues on the
current checkout for any other pull failure (offline, local changes
that prevent a fast-forward). Skip entirely with SKIP_SELF_UPDATE=1,
matching the existing SKIP_SUBMODULE_UPDATE convention.

Verified in an isolated scratch clone (not the working repo): pulling
a real commit forward triggers the re-exec and the second invocation
picks up the new HEAD; already-up-to-date and detached-HEAD cases are
both silent no-ops.
2026-07-14 11:38:17 -04:00
wmantly 3cb549f39c Merge pull request #21 from theta42/chore/bump-submodules-2
Bump proxy + sso-manager-node submodules to latest master
2026-07-14 01:29:12 -04:00
wmantly 0f7f7e2080 Bump proxy + sso-manager-node submodules to latest master
proxy: f926d92 -> 1c7ad9a — target-hostname validation fix (#126) and
the DuckDNS `domains`/`subdomains` field-collision fix (#127).
sso-manager-node: 2b11095 -> 3d3b15b — README rewrite (#40).
2026-07-14 01:27:55 -04:00
wmantly c45d030da1 Merge pull request #20 from theta42/fix/bootstrap-proxy-hosts
setup.sh: register SSO + proxy hostnames as Host records in the proxy
2026-07-14 01:07:53 -04:00
wmantly 425d92a137 setup.sh: register SSO + proxy hostnames as Host records in the proxy
The proxy routes every hostname it serves purely off a Host record
(ops/nginx_conf/proxy.conf has no default/self route — targetinfo.lua
does a Redis lookup per request, full stop). Nothing created these for
the SSO's own UI or the proxy's own management UI, so on a fresh
install https://<SSO_HOST> and https://<PROXY_HOST> both 404 despite
setup.sh's summary claiming they're "fronted by the proxy under TLS".

Add a step after the proxy is healthy that runs a short script inside
the proxy container calling its Host model directly (no HTTP API call,
since no authenticated session exists yet at this point in the run):
- <SSO_HOST> -> sso-manager:3001 (the Docker service)
- <PROXY_HOST> -> 127.0.0.1:3000 (the proxy's own management app)

Both created with sso_enabled: false — each app already gates its own
login, and SSO-gating the SSO's own login page would be circular.
Idempotent: skips a host that already exists.
2026-07-14 01:01:37 -04:00
wmantly 4bd2c5a8be Merge pull request #19 from theta42/chore/bump-submodules
Bump proxy + sso-manager-node submodules to latest master
2026-07-14 00:29:04 -04:00
wmantly 6f5878989d setup.sh: take a plain domain (CFG_DOMAIN), derive the LDAP base DN (#18)
Entering the base DN directly (CFG_BASE_DN=dc=foo,dc=bar) is fragile —
a missing comma between labels silently produces a malformed domain
(e.g. "theta42dc=duckdns.org" instead of "theta42.duckdns.org") with
no validation to catch it. Flip the direction: operators now set
CFG_DOMAIN to a plain domain (any number of labels — a DuckDNS domain
like foo.duckdns.org works the same as a normal one), and setup.sh
derives the base DN from it via the new dn_from_domain().

CFG_BASE_DN is still supported as an explicit override (e.g. to
namespace under an OU-style prefix) and is how migrated .env/proxy.env
deployments keep working, since domain_from_dn() still reads the
domain back out of an existing DN either way.
2026-07-14 00:28:39 -04:00
wmantly 1285a86ce6 Bump proxy + sso-manager-node submodules to latest master
proxy: adds DuckDNS as a free DNS provider, public-release doc cleanup,
and the README rewrite (#123, #124, #125).
sso-manager-node: public-release doc cleanup and the README rewrite
(#38, #40).
2026-07-14 00:27:51 -04:00
wmantly b43c3d0d1d docs: fix quickstart drift, add LICENSE, document admin bypass and LDAPS cert mount for public release (#17)
Cleanup pass ahead of the public release announcement:

- docs/index.md: fix the Quick Start block, which described a stale
  "edit config then re-run setup.sh a second time" flow. setup.sh now
  requires setup.env (with CFG_BASE_DN) before it will do anything, and
  builds + bootstraps + starts in a single run. Updated to match
  README.md's correct 4-line sequence.
- Add a standard MIT LICENSE at the repo root (theta42, 2026) so
  docs/index.md's "MIT License — see the repository for details" claim
  is actually true.
- docs/standalone.md: document the hardcoded auth.adminUsers:
  ['proxyadmin2'] local anti-lockout admin bypass written into every
  generated proxy-secrets.js — what it's for, that it requires a
  matching SSO user to actually use, and how to rename/extend/disable
  it.
- README.md + docker-compose.yml: fix the LDAPS strict-trust security
  note, which implied mounting the SSO's cert into the proxy was a
  config-only change. It also requires a docker-compose.yml edit
  (ldap-certs isn't mounted into the proxy service); added commented-out
  boilerplate for that mount and clarified the doc text.
- Also includes the pre-existing "Why use this instead of running the
  two separately?" README paragraph that was already staged as
  in-progress work.
- Verified: no Vagrant references, no emoji, and no hardcoded
  custom-domain URLs anywhere in this repo outside the proxy/ and
  sso-manager-node/ submodules; no docs/CNAME (github.io URL scheme
  confirmed).
- Added --- section dividers to docs/*.md to match README.md's
  formatting convention.

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-13 23:10:55 -04:00
wmantly 20a586de4f feat(setup): enter the domain once via setup.env; stop drifting the secrets (#16)
The first-run flow generated ./config/*.js with example.com/dc=example,dc=com
defaults and then exit 0'd, telling the operator to hand-edit. The domain/base
DN was repeated across ~9 fields in each secrets file; on the deploy host only
the stack block was updated (to dc=718it,dc=biz) while ldap.* DNs stayed at
dc=example,dc=com, so slapd's root DN didn't match the app's bindDN and
bootstrap failed with 401 Invalid Credentials.

Enter the domain once: a new setup.env (gitignored; setup.env.example is the
committed template) holds the essential, non-repeating first-run info — the
domain as an LDAP base DN (CFG_BASE_DN). setup.sh reads it ONLY on first run
(when ./config/*.js don't exist), derives hostnames (sso.<domain> /
proxy.<domain>) and all LDAP DNs from it, generates both secrets files with
the real domain filled in everywhere + random secrets, and proceeds to build
in the same run (no edit-and-re-run step). After first run the secrets files
are operator-owned and setup.env is ignored — the apps and secrets files are
unchanged.

- setup.sh ensure_config: source setup.env -> bind CFG_* to empty (set -u
  safe) -> unchanged .env/proxy.env legacy migration -> derive from base DN
  (no example.com defaults; die with a helpful msg if CFG_BASE_DN blank) ->
  generate + proceed. Header comments updated.
- setup.env.example: committed template; secrets stay out (generated into
  ./config/*.js).
- .gitignore: ignore setup.env (per-deployment).
- README.md + docs/quickstart.md: Quickstart now cp setup.env.example ->
  set CFG_BASE_DN -> ./setup.sh; domain-asked-once note in "Before you begin".
- Bump sso-manager-node gitlink to 11fb2c0 (docs PR #37: base-DN-is-the-one-
  domain-value note in sso-manager README/DEPLOYMENT/secrets.js.example).

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-13 22:05:05 -04:00
wmantly 52cffb9b81 setup.sh: localize snapshot stalls + harden retention (#15) (#15)
After #14 the deploy-host snapshot still stopped right after
'config -> config/' with no further output — neither the LDAP/Redis
'snapshotting...' lines nor the post-snapshot 'Building + starting
sso-manager' line, so the stall was somewhere in the no-container path
(no containers are up yet when ./setup.sh is first run) but invisible
because every skip was silent and there was no marker between the config
copy and the function return.

Instrument + harden backup_before_rebuild() so the next run localizes it:

- ERR trap (scoped to the function): if a command trips set -e and aborts
  the snapshot, print 'snapshot aborted by command: <cmd>' instead of
  dying mute after 'Snapshotting state to ...'.
- Explicit 'skipped' branches: 'LDAP: sso-manager not running — skipped'
  and 'Redis (<svc>): not running — skipped' so a no-container run shows
  which path was taken instead of going quiet.
- 'pruning old backups (keep=N)...' before the retention loop and
  'snapshot complete.' at the end, so a stall is pinned to the retention
  loop (or ruled out of the snapshot entirely).
- Retention: clamp with [[ ]] not (( )) — (( keep < 1 )) returns exit 1
  when false, a classic set -e landmine; guard rm -rf with '|| true';
  skip symlinks and non-dir entries so a stray symlink in ./backups can't
  point rm at an arbitrary tree.

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-13 21:03:26 -04:00
wmantly ab99f532b3 Fix backup snapshot hang + compose project mismatch (#14) (#14)
backup_before_rebuild() stalled on the deploy host after printing
"Snapshotting state to ..." with no LDAP/Redis output, and silently
no-oped on any stack brought up under a different compose project.

Root causes:
- The LDAP slapcat + in-container base-DN read used
  `$COMPOSE exec -T sso-manager`, which exits 1 *silently* (no stderr)
  when the running container belongs to a different compose project than
  the one the superproject resolves (the standalone SSO from the
  sso-manager-node submodule is project "sso-manager-node", not
  "theta-env"). The snapshot then no-ops with no breadcrumb.
- The host-side `node -e 'require(./config/sso-secrets.js)'` base-DN read
  had no timeout, so a malformed secrets.js could block at require() time
  and hang the whole rebuild at that line.
- The Redis RDB copy hardcoded `/data/dump.rdb` and used
  `$COMPOSE cp` — wrong path on the standalone layout (Redis dir is
  /app, not /data) and the same compose-project mismatch as above.

Fix:
- Switch every in-container call to `docker exec <name>` / `docker cp`
  by container name, which works regardless of the owning compose project
  (matches the already-working Redis BGSAVE/SAVE path).
- Wrap the host-side node read in `timeout 5` and slapcat in `timeout 20`
  so no single command can hang the rebuild.
- Ask Redis for its own `CONFIG GET dir` / `dbfilename` and copy from the
  real path, so the RDB is found on both the unified (/data) and standalone
  (/app) layouts.
- Add per-step progress lines (config/LDAP/each Redis service) so any future
  stall is localized to the exact step instead of hanging silently.

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-13 20:57:06 -04:00
wmantly 207f459161 Bump proxy submodule: OpenResty repo distro/component fix for Debian (#13)
proxy: 6158a3a -> 3df7d8c (PR #122)

Follow-up to the Debian 13 install fix: the openresty.org Debian tree only
publishes up to bookworm (no trixie) and uses the "openresty" component, not
"main". install.sh now picks bookworm + component "openresty" on Debian
(codename when published, else bookworm fallback), and keeps codename + "main"
on Ubuntu.

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-13 20:42:11 -04:00
wmantly 895c011118 Bump proxy submodule for Debian 13 (trixie) OpenResty install fix (#12)
proxy: 8dcecbc -> 6158a3a (PR #121)

ops/install.sh now handles Debian 13: extends apt's sequoia SHA-1 acceptance
(the OpenResty repo key is still SHA-1) and picks the /package/debian repo
tree by distro ID instead of hardcoding /package/ubuntu. docs/installation.md
mirrors the manual steps.

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-13 18:14:47 -04:00
wmantly 63e6f6d48c Fix backup snapshot: BGSAVE race + host-side ldapBaseDn read (#11)
Two bugs in backup_before_rebuild() that made every pre-rebuild snapshot
fail once a stack was actually running:

1. Redis "BGSAVE did not finish in 30s" — a race. The code issued BGSAVE and
   only THEN captured `before = LASTSAVE`. On a small dataset BGSAVE finishes
   in well under a second, so `before` was already the post-save value and the
   poll waited 30s for a second advance that never came (both services, every
   run). Fix: capture LASTSAVE before BGSAVE. Also add a synchronous SAVE
   fallback — BGSAVE can fork-fail when the host has vm.overcommit_memory=0
   (this host does: 0), and SAVE can't fork-fail. The brief block is fine
   pre-rebuild. Poll shortened to 10s since a small dataset completes in <1s.

2. "could not read ldapBaseDn from sso-secrets.js" — the base DN was read via
   `docker compose exec sso-manager node -e 'require("/config/sso-secrets.js")'`,
   which fails when the running container predates the ./config bind-mount
   (no /config in the container). Fix: read from the host-side
   ./config/sso-secrets.js first (same require pattern the SSO entrypoint
   uses; works regardless of the running container's mounts), falling back to
   the in-container read.

Verified live: SAVE advances LASTSAVE (reply "OK"); host-side require returns
stack.ldapBaseDn on the example config.

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-13 17:55:24 -04:00
wmantly 500657643d Bump submodules for api-tokens date/authIO fixes (#10)
- sso-manager-node: b91ef27 -> 796e013 (PR #36)
- proxy: a9a48c3 -> 8dcecbc (PR #120)

Fixes: api-tokens page "Created: Invalid date" (created_on comes back as a
string; use moment(ms, "x")), expired badge never showing (isExpired getter
isn't serialized to the client), and a noisy `AuthToken:0 does not exists`
log on unauthenticated socket connects.

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-12 17:42:43 -04:00
wmantly 05a68199f7 Add API tokens (PATs) support + bump submodules (#9)
Both submodules now support self-service personal access tokens (PATs) for
calling the management API without an OIDC browser session. Document the
feature in README.md + docs/ (mint under "API Tokens" in each UI, use as
`Authorization: Bearer sso_…` / `prx_…`, authenticates as the creator with
their permissions, rotate/revoke in the UI, persists in Redis via AOF).

Bump gitlinks to the merged submodule tips:
- sso-manager-node: 6920a9f -> b91ef27 (PR #35)
- proxy: 8e78604 -> a9a48c3 (PR #119)

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-12 17:14:41 -04:00
wmantly b5f24d40fc Persist Redis + config in bind-mounted ./config/ (no .env); add backup/restore (#8)
Part A — lossless upgrades:
- Persist both bundled Redis stores via AOF+RDB on named volumes (sso-data,
  proxy-data) so OAuth clients, Host records, perms, DNS creds, and auto-ssl
  Let's Encrypt certs survive rebuilds.
- setup.sh: backup_before_rebuild() snapshots ./config/ + LDAP (slapcat) +
  both Redis (BGSAVE + compose cp) to ./backups/<ts>/ before each rebuild,
  keeps last BACKUP_KEEP (default 5). First run is a no-op.
- Restore runbook (README + docs): full / Redis-only / LDAP-only, with the
  AOF-vs-RDB note (delete the AOF before restoring an RDB).

Part B — eliminate .env / proxy.env:
- All config + secrets live in bind-mounted ./config/ (gitignored), read by each
  app's @simpleworkjs/conf from a symlinked secrets.js. Compose passes only
  NODE_ENV + NODE_PORT (no app_* env, which would override secrets.js).
- ./config/sso-secrets.js: app secrets + orchestrator-only stack/bootstrap/
  serviceAccountPass keys (app ignores the ones it doesn't use).
- ./config/proxy-secrets.js: oidc (clientId/clientSecret filled in by the
  bootstrap), ldap (bind creds), auth (admin groups/users).
- setup.sh ensure_config(): generates ./config/ with random secrets on first
  run (then exits for editing); one-time migration from .env/proxy.env
  preserving existing secrets (LDAP admin pass, JWT, OAuth client, service
  pass) so a running deployment keeps its directory + tokens + OAuth client.
- bootstrap/bootstrap.js: reads /config/*.js (not process.env), registers the
  proxy as an OIDC client, and writes the SSO-generated client id+secret back
  into ./config/proxy-secrets.js (sso mounts ./config RW, proxy RO).
- config.example/ holds committed annotated templates for manual reference.
- .gitignore: add config/, backups/, *.rdb, *.ldif.

Bump both gitlinks to the merged submodule tips:
- sso-manager-node -> 6920a9f (PR #34)
- proxy -> 8e78604 (PR #118)

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-12 13:16:17 -04:00
wmantly 2d2941e394 Merge pull request #7 from theta42/bump-sso-sudo-lpk-schema
bump sso-manager-node: sudo + openssh-lpk schemas in image
2026-07-11 22:35:13 -04:00
wmantly c72e501fc8 bump sso-manager-node: load sudo + openssh-lpk schemas in image
sso-manager-node d5e951f — ships sudo.schema + openssh-lpk.schema (included
in the all-in-one slapd.conf) so user creation works (addPosixAccount tags
every user with sudoRole + ldapPublicKey). Also fixes the .dockerignore build
error from the previous theta42 schema bump. See theta42/sso-manager-node#33.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-11 22:34:57 -04:00
wmantly c24563fb3e Merge pull request #6 from theta42/bump-sso-theta42-schema
Bump sso-manager-node for the theta42 schema fix
2026-07-11 21:42:02 -04:00
wmantly 25692780e2 Bump sso-manager-node for the theta42 schema fix
sso-manager-node: d1620dd -> 84e5358
  Load the theta42 (dateOfBirth) schema in the all-in-one image
  (theta42/sso-manager-node#32)

Fixes PUT /api/user/<uid> failing with "objectClass: value #0 invalid per
syntax (0x15)" when a dateOfBirth is set, and user creation for the
theta42Person objectClass. Requires a rebuild of the sso-manager image.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-11 21:41:53 -04:00
wmantly 1591ecd2bc Merge pull request #5 from theta42/bump-submodule-logs-docs
Bump submodules for the Logs (Docker) docs
2026-07-11 21:34:45 -04:00
wmantly e1ed517fe1 Bump submodules for the Logs (Docker) docs
Point sso-manager-node and proxy at the commits that add the Logs (Docker)
section to their README/DEPLOYMENT docs:
  proxy:              cca5e48 -> 3f178b0
  sso-manager-node:   fe9b7c1 -> d1620dd

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-11 21:34:33 -04:00
wmantly e9cc042019 Merge pull request #4 from theta42/docs-logs
README: add a Logs section for the Docker stack
2026-07-11 21:06:35 -04:00