Commit Graph

36 Commits

Author SHA1 Message Date
wmantly fabb250887 Add site analytics tracking script to docs layout
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-06 23:45:37 -04:00
wmantly 5925940936 Fix Directory topology: containers aren't hosts; bump submodules; docs
bootstrap.js no longer creates host_theta-proxy / host_theta-jump as
synthetic kind:'host' resources. Proxy and jump-host are containers running
on the one real stack host, not machines of their own -- and jump-host
resolves its SSH-reachable-hosts list from exactly kind:'host', so the
mistake wasn't just conceptual, it could offer unreachable SSH targets.
Their services now parent directly onto the stack host, like every other
component. Installs seeded between 2026-08-05 and this release self-heal on
the next ./setup.sh run: existing children are re-parented off the
synthetic hosts and the now-empty synthetic hosts are removed. Validated
live against a running instance carrying the exact bad state.

Bumps submodules to sso-manager-node v1.30.2, proxy v1.35.1,
jump-host v1.19.1.

Also: README's architecture diagram + repo layout were stale (2-service
view predating jump-host/OpenBao, 2 of 5 submodules listed); new
docs/fixtures.md + docs/screenshots.md + bootstrap/seed-demo-users.sh for
consistent, repeatable demo data and screenshot passes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0113gCdnfSCuZr6xvPDxTo3D
2026-08-06 21:38:48 -04:00
wmantly 6479d35fb8 feat: agent enrollment, per-host SSO redirect URIs, seed hierarchy (v1.42.0)
Lint / Shellcheck setup.sh (push) Failing after 10s
Lint / Syntax check bootstrap.js (push) Successful in 14s
Rolls up sso-manager-node v1.29.0, theta-agent v1.4.0, proxy v1.34.0 and
jump-host v1.19.0.

Per-host SSO returned "400 redirect_uri is not registered for this
client". The bootstrap registered only the proxy's own management
callback, but per-host SSO calls back to
https://<protected-host>/__proxy_auth/callback -- a different URL per
proxied host, all against that one OAuth client. Now registers the
wildcard + apex patterns, and backfills them onto existing clients so
upgraded stacks are fixed too.

theta-proxy and theta-jump were seeded as hosts and then left childless
while their services hung off the stack host. Services now parent to the
host that runs them; reparent() corrects existing installs, but only when
the current parent is the one the old code set.

The proxy gets a read-only SSO API token (minted before the OpenBao
snapshot so the running proxy receives it) backing the per-host SSO group
autocomplete, and the sso-broker policy grants secret/agent/* for the
SSO's persistent theta-agent signing key.

BREAKING: theta-agents must be re-enrolled, and ./setup.sh must be re-run
for the new OpenBao grant.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 19:29:29 -04:00
wmantly 84d7c96c17 fix: LDAP enrollment uses localhost (not the public domain); align SSH access groups; roll up ldap-client v1.24.0 (v1.38.0) (#164)
CI/CD / build-theta-agent (push) Successful in 42s
CI/CD / docker-push (push) Failing after 16s
- setup.sh: ldap_host defaults to localhost (the public sso.<domain> can't reach
  the 389/636 LDAP ports through NAT); overridable via CFG_LDAPS_HOST
- ldap.vars access groups + ldap-client sssd filter now reference the SSO group
  model (site_<loc>_hosts_access, site_<loc>_host_<host>_access, god_admin)
- GROUPS.md §5/§8 updated to the corrected naming
- gitlink: ldap-client ebaac18 (v1.24.0)
2026-08-04 23:30:04 -04:00
wmantly 72046a8b29 docs: group naming matches docs/GROUPS.md; roll up sso v1.27.0 (v1.37.0) (#163)
CI/CD / build-theta-agent (push) Successful in 44s
CI/CD / docker-push (push) Failing after 17s
- GROUPS.md: per-resource groups are {site}_{kind}_{name}_{level}; site carries god + site-wide only
- gitlink: sso-manager-node e8d0420 (v1.27.0)
2026-08-04 23:02:14 -04:00
wmantly a77aa8d2df feat: seed god_admin + docker plugin, fix ldap-client enrollment, roll up sso v1.26.0 + theta-agent v1.3.0 (v1.36.0) (#161)
CI/CD / build-theta-agent (push) Successful in 44s
CI/CD / docker-push (push) Failing after 16s
- bootstrap: seed god_admin into the admin's groups; seed a docker-local discovery plugin
- setup.sh: generate ldap-client/ldap.vars from the stack config so LDAP enrollment works
- docs: GROUPS.md site-slug convention (verbatim, kind in resource slug)
- gitlinks: sso-manager-node 8a9de94 (v1.26.0), theta-agent 52379c2 (v1.3.0)
2026-08-04 19:10:32 -04:00
wmantly 292b67c334 docs: group & permission model spec + link (v1.35.17)
Add docs/GROUPS.md — the canonical Group & Permission Model (schema, inheritance
resolver, Directory-only management, multi-site, host-side SSSD mapping, migration)
— link it from the docs index, and note sso v1.25.0 in the changelog.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-04 15:04:30 -04:00
wmantly c27e8c7867 feat: OpenBao token lifecycle + bump sso to v1.23.0 (v1.35.14)
- theta-svc token role (periodic 768h): SSO/PROXY/JUMP_VAULT_TOKEN now minted
  through it; ensure_token renews periodic tokens on every setup.sh re-run and
  detects/revokes/re-mints valid-but-non-periodic tokens from older installs.
- bao-renewer sidecar (docker-compose): renews the three service tokens every
  12h while the stack runs.
- sso-app token role (periodic 768h) + sso-broker policy grants for
  auth/token/create/sso-app and renew/revoke/lookup-accessor.
- docs/secrets.md rewritten around the new lifecycle.
- Bump sso-manager-node gitlink to v1.23.0 (real vault-403 fix + app-token
  lifecycle).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-04 00:21:51 -04:00
wmantly 3b769cf24a chore: release v1.34.3 (updates submodules, docs, bootstrap)
Lint / Shellcheck setup.sh (push) Failing after 9s
Lint / Syntax check bootstrap.js (push) Successful in 13s
2026-08-02 19:08:14 -04:00
wmantly 43b8307e54 docs: note docker compose v1 incompatibility 2026-08-02 13:13:50 -04:00
wmantly 5ee486e808 chore: update submodules for PKI cert and agent C2 releases 2026-08-02 01:54:54 -04:00
wmantly 475ae2c893 docs: remove all standalone deployment documentation 2026-08-02 00:51:25 -04:00
wmantly 8f5ce71bda feat: Add CI/CD workflow, update docs, update submodules 2026-08-02 00:16:27 -04:00
wmantly 403e66556c feat: grant sso-broker OpenBao access to secret/plugins/* (v1.30.1)
Prerequisite for the SSO Manager plugin system (shipped in sso-manager-node
v1.17.0). Adds secret/data/plugins/* (CRUD+list) + secret/metadata/plugins/*
(list/read/delete) to the sso-broker policy HCL so the SSO can store per-instance
plugin secrets in OpenBao instead of sso-secrets.js. ensure_policy is idempotent,
so re-running ./setup.sh grants the existing SSO_VAULT_TOKEN live.

Docs: secrets.md (Plugin secrets section + policy row), architecture.md.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-01 20:33:21 -04:00
wmantly 3287777b9b v1.30.0: rename theta-env -> theta-suite + docs rewrite + sso v1.16.1 (#126)
Rename the project to theta-suite (it is now an integrated suite of four
apps around a shared OpenBao secrets store, not a two-project env).
- theta-env -> theta-suite across the superproject: _config.yml (title +
  baseurl /theta-suite + repo URLs), README, setup.sh (incl. the
  THETA_SUITE_REEXECED self-update sentinel), docker-compose.yml,
  bootstrap.js, lint.yml, config.example/*, docs/robots.txt, all docs,
  this changelog.
- architecture.md rewritten: real 4-service + ldap-client topology, OpenBao
  secrets section, OpenBao-aware config flow; removed "two containers" /
  "three repos" / LDAP-"legacy" framing.
- index.md: integrated-suite framing + secrets/OpenBao + ldap-client.
- standalone.md + README: standalone reframed as advanced opt-in.
- sso-manager-node submodule -> v1.16.1 (401 fix on /conf and /vault).

Co-authored-by: Claude <noreply@anthropic.com>
2026-08-01 18:46:10 -04:00
wmantly 5ef3e3fa8c v1.29.0: jump host is core + fix fresh-install setup.sh abort (#125)
Two fresh-install fixes and promote the SSH jump host from opt-in to core.

setup.sh: fix silent abort after "Minting per-app OpenBao tokens". env_get's
grep|cut pipeline returns non-zero under set -euo pipefail when .env exists
(created by the root VAULT_TOKEN env_upsert) but an app-token key is absent
(the normal first-run state); the unguarded existing assignment from env_get
then tripped set -e and killed the script before minting any token. env_get
now always returns 0 (|| true). Reproduced + verified under the exact condition.

jump host is no longer optional:
- docker-compose.yml: drop profiles jump-host from the jump-host service
  (always started); rename the opt-in test fixture profile jump-host to ldap-test.
- setup.sh: SUBMODULES always includes jump-host; build/start/register/summary
  no longer guarded by JUMP_ENABLED; drop the COMPOSE_PROFILES export.
- bootstrap.js: jump provisioning + directory record run unconditionally.
- setup.env.example/docs: drop optional/CFG_JUMP_HOST_ENABLED wording.

Co-authored-by: Claude <noreply@anthropic.com>
2026-08-01 13:48:28 -04:00
wmantly f7df04c2f0 v1.28.0: OpenBao as the central secrets store for the stack
theta-env orchestration:
- setup.sh: idempotent OpenBao policies (sso-broker, sso-admin, proxy,
  jump-host), sso-broker token role (allowed_policies_glob user-*/app-*,
  24h), mint scoped SSO/PROXY/JUMP_VAULT_TOKEN (orphan, .env reuse),
  seed_app_conf seeds secret/{sso-manager,proxy,jump-host}/conf. Bootstrap
  exec passes root VAULT_ADDR/VAULT_TOKEN for seeding. Root token never
  reaches a service container. shellcheck -S warning clean.
- docker-compose.yml: VAULT_ADDR + VAULT_TOKEN env for sso/proxy/jump;
  proxy/jump depends_on openbao service_started.
- bootstrap/bootstrap.js: baoPut() writes generated OAuth creds to
  secret/proxy/conf + secret/jump-host/conf (OpenBao authoritative).
- docs/secrets.md (new): full secrets architecture. README + nav updated.

Submodule bumps:
- sso-manager-node -> v1.16.0 (OpenBao broker + vault UI + remediation)
- proxy -> v1.13.1 (via v1.13.0: OpenBao boot)
- jump-host -> v1.14.1 (via v1.14.0: OpenBao boot)
- ldap-client unchanged

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-01 12:54:56 -04:00
wmantly 6ef12408df docs: refresh top-level screenshots, add jump-host dashboard
sso-dashboard.png and proxy-hosts.png still showed the pre-unification
nav; refresh with the current shared shell and add a jump-host dashboard
screenshot alongside them.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-26 16:29:51 -04:00
wmantly b25fb56a0d docs: add the optional SSH jump host to the theta-env Pages site
- index: mention the jump host as an optional third component (intro,
  What-you-get, Related projects)
- quickstart: CFG_JUMP_HOST_ENABLED / CFG_JUMP_HOST / JUMP_SSH_PORT
- reframe "legacy LDAP clients" -> "direct LDAP clients" (Linux hosts are
  first-class consumers)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 16:17:14 -04:00
wmantly fea1237c46 Release 1.3.1: bump proxy to v1.2.1, sso-manager-node to v1.1.18
Both bumps are bug-fix releases: proxy fixes a bootstrap admin lockout
bug, sso-manager-node fixes a crash on the new Sites & Replication
page. See CHANGELOG.md for the embedded submodule changelogs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-21 02:16:08 -04:00
wmantly 2baf8acd64 chore: Update proxy submodule and docs for load balancing 2026-07-21 01:00:26 -04:00
wmantly 94b357e915 docs: Add Multi-Site Support to features list 2026-07-21 00:10:26 -04:00
wmantly 481602ae60 Bump proxy and sso-manager-node submodule pins to v1.1.14
- proxy -> v1.1.14
- sso-manager-node -> v1.1.14

Both bump @simpleworkjs/conf to 1.2.0 and jq-repeat to 2.2.0, and use
the new CONF_SECRETS env var instead of symlinking the mounted secrets
file into /app/conf/secrets.js. Updated theta-env's own docs/setup.sh/
docker-compose.yml comments to match -- no change to the config file
format or bind mounts.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-17 23:49:21 -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 e5f3e1714f Add CHANGELOG.md; bump submodules to v1.1.3 (closes #43)
Adds a Keep-a-Changelog-style CHANGELOG.md, linked from README and
docs/index.md, closing the "no changelog or versioning scheme"
issue. Bumps proxy and sso-manager-node to v1.1.3 (both add their
own CHANGELOG.md, served in-app at /docs/changelog).
2026-07-16 16:08:17 -04:00
wmantly c60e745665 docs: link Quickstart/Architecture/Standalone from Home; bump submodules to v1.1.2
docs/index.md (the published site's home page) never linked to
architecture.md, quickstart.md, or standalone.md -- they were only
reachable by direct URL. Added a "More docs" section linking all
three.

Bumps proxy and sso-manager-node to v1.1.2 (air-gap fixes + in-app
/docs on both).
2026-07-16 15:40:25 -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 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 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 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 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 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 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