Commit Graph

6 Commits

Author SHA1 Message Date
wmantly 455450db1f feat(multi-site): spoke.env.example + CFG_PUBLIC_DOMAIN
A dedicated spoke.env for the join-a-cluster vars (CFG_MASTER_DIRECTORY_URL/
_JOIN_KEY, CFG_SPOKE_NO_INBOUND/_PUBLIC_HOST, CFG_PUBLIC_DOMAIN), split out
of setup.env purely for clarity -- setup.env still has every option and
keeps working as a single file if that's preferred. setup.sh reads both
(setup.env first, spoke.env layered on top so its values win), same
first-run-only rule as setup.env already had.

Also adds CFG_PUBLIC_DOMAIN (documented in MULTI_SITE_SPEC.md §4 but never
actually wired into setup.sh): an inbound spoke/standalone site's own public
web domain, independent of CFG_DOMAIN (the shared LDAP identity namespace,
which must stay identical across every site). Unset behaves exactly as
before -- hostnames derive from CFG_DOMAIN like any standalone install.
2026-08-10 22:22:54 -04:00
wmantly d4154cfec6 Release 1.20.0: bump submodules for cross-app super admin; persist GIT_COMMIT to .env
- Bump jump-host, ldap-client, proxy, sso-manager-node submodules to their
  new tags (cross-app app_super_admin group, jump-host's app_jump_admin,
  ldap-client's SSH host access for super admins).
- setup.sh: new env_upsert helper persists SSO_GIT_COMMIT/PROXY_GIT_COMMIT/
  JUMP_GIT_COMMIT into ./.env (docker compose's auto-loaded env file) so an
  ad-hoc single-service rebuild outside a full setup.sh run still bakes the
  right commit hash instead of "unknown".
2026-07-30 12:07:12 -04:00
wmantly 502aba3da6 Redesign docs site: match the projects' own look, add SEO, mobile-ready
Same treatment as the proxy and sso-manager-node companion PRs. This
repo has no app UI of its own (it's a bash orchestrator), so both the
nav logo and favicon use the shared theta42.svg mark -- matching the
family look shown in its own screenshots (the SSO Manager/proxy
dashboards it stands up).

- New cross-page nav (Home/Quickstart/Architecture/Standalone/
  Changelog) -- replaces index.md's old "More docs" section, now
  redundant with the top nav.
- SEO: jekyll-seo-tag + jekyll-sitemap, per-page meta description,
  OG/Twitter card tags, canonical URLs, JSON-LD, sitemap.xml,
  robots.txt.
- Mobile: Bootstrap's responsive grid + collapsible navbar; the
  screenshot pair in index.md stacks to full-width below 576px.
- Added docs/_site to .gitignore (missing entirely before -- the
  other two repos already had it).

Verified with a real Jekyll build (jekyll/jekyll Docker image) +
Playwright: desktop and mobile (375px) screenshots, mobile nav
toggle, active-link highlighting, zero console/page errors, and
confirmed real SEO output (meta description, OG/Twitter tags,
canonical, JSON-LD, sitemap.xml, robots.txt) via curl against the
served site.
2026-07-16 20:20:42 -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 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 9fb240ff45 theta-env: unified SSO Manager + Proxy stack with one-command setup
Composes theta42/sso-manager-node and theta42/proxy (as git submodules) on a
single Docker network and automates first-run wiring.

- docker-compose.yml: sso-manager (build ./sso-manager-node/Dockerfile.openldap)
  + proxy (build ./proxy/Dockerfile) on theta-net; SSO UI + mgmt port bound to
  localhost, LDAPS published, proxy 80/443/4443 published.
- setup.sh: idempotent one-command bring-up — validates .env, starts SSO, runs
  the bootstrap, writes ./proxy.env, starts the proxy, prints admin login.
- bootstrap/bootstrap.js: runs inside the sso-manager container (self-contained,
  Node built-ins + fetch only) — creates the LDAP service account, first admin
  (+ app_sso_admin/app_sso_oauth_admin membership), registers the proxy as an
  OIDC client via the SSO HTTP API, emits CLIENT_ID/CLIENT_SECRET.
- .env.example: all tunables (LDAP_BASE_DN, LDAP_ADMIN_PASS, JWT_SECRET,
  SSO_HOST, PROXY_HOST, BOOTSTRAP_ADMIN_*, LDAP_SERVICE_PASS, SMTP_*, ports).
- README.md + docs/ (Jekyll site for GitHub Pages): quickstart, architecture,
  standalone usage.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-11 17:04:36 -04:00