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>
5.8 KiB
layout, title, description
| layout | title | description |
|---|---|---|
| default | Standalone | Running a component individually, without theta-suite's orchestration — an advanced path; the integrated stack is the supported one. |
Running a component individually
The integrated stack is the supported path.
./setup.shwiring all four components together around a shared OpenBao secrets store is what's tested and released. The steps below are for the advanced case where you want to run one component on its own — a separate host, a different network, or without the orchestrator. Running standalone means managing secrets from theconfig/*-secrets.jsfile only (no shared OpenBao) and doing the OIDC/LDAP wiring by hand.
The submodules in this repo are normal clones; you can also clone them directly from GitHub. Each component builds and runs on its own.
SSO Manager alone
The all-in-one image (Dockerfile.openldap) bundles the app + OpenLDAP + Redis:
git clone https://github.com/theta42/sso-manager-node.git
cd sso-manager-node
mkdir -p config && cp secrets.js.example config/sso-secrets.js # edit it
docker compose up -d --build
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 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://<host>:636
Requires @simpleworkjs/conf >= 1.2.0. Full reference:
SSO Manager deployment docs.
Bare metal
sudo ./install.sh -p 'your-ldap-password' -b 'dc=yourdomain,dc=com' -n 'Your Org' -o 3001
sudo systemctl enable --now sso-manager
Idempotent — re-run to update. See the SSO Manager deployment guide.
Proxy alone
The all-in-one image (Dockerfile) bundles OpenResty + the Node app + Redis:
git clone https://github.com/theta42/proxy.git
cd proxy
mkdir -p config && cp secrets.js.example config/proxy-secrets.js # edit it
docker compose up -d --build
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 the secrets
file, so app_* would silently override your file.
- Proxy (public, auto-SSL):
https://<host>/ - Mgmt UI / API:
http://127.0.0.1:3000/ - Health:
http://127.0.0.1:3000/health
Requires @simpleworkjs/conf >= 1.1.0. Full reference:
proxy deployment docs.
The auth.adminUsers anti-lockout account
Both setup.sh and config.example/proxy-secrets.js.example write
auth.adminUsers: ['proxyadmin2'] into proxy-secrets.js. This is a
local, config-driven admin bypass — the proxy grants full admin rights to
any logged-in OIDC user whose username (the preferred_username claim from
the SSO) matches an entry in auth.adminUsers, regardless of their LDAP group
membership (see proxy/nodejs/utils/roles.js, resolveEffective()). It exists
so an operator can't lock themselves out of the proxy mgmt UI if the SSO's
app_sso_admin group is ever misconfigured, deleted, or otherwise broken.
It is not derived from any setup.env value, and it does not create a
user by itself — the name is only a username match. To actually use the
bypass, create a user with uid proxyadmin2 in the SSO (it does not need to
be in app_sso_admin or any other group) and log in through the proxy as that
user.
To change or disable it, edit auth.adminUsers directly in
./config/proxy-secrets.js after the first ./setup.sh run (re-running
setup.sh will not overwrite an existing proxy-secrets.js):
- Rename it to a less guessable username:
adminUsers: ['your-break-glass-uid']. - Add more anti-lockout accounts:
adminUsers: ['proxyadmin2', 'another-admin']. - Disable it entirely:
adminUsers: [](global admin then comes only fromauth.adminGroupsmembership — make sure at least one real admin group is reachable before doing this).
Bare metal
wget -O - https://raw.githubusercontent.com/theta42/proxy/master/ops/install.sh | sudo bash
See the proxy Docker guide / installation guide.
Wiring components together by hand
If you have a specific reason to run the components on separate hosts instead
of through ./setup.sh (and accept that you lose the shared OpenBao secrets
store), the four wiring steps are documented in both projects' deployment
guides:
- One Docker network (or reachable hostnames) so the proxy can reach the SSO internally for token/userinfo + LDAPS.
- Set the SSO's
oauth.issuer(in itssecrets.js) to the browser-facing HTTPS URL the proxy serves the SSO at. - Register the proxy as an OIDC client in the SSO, with
redirectUrimatching the proxy's callback; put the resultingclientId/clientSecretin the proxy'ssecrets.js. - Point the proxy's
ldap.urlat the SSO's LDAPS + create a dedicatedcn=ldapclientservice account; set the same password asbindPassword.
./setup.sh exists to do all of this for you — and to add the OpenBao secrets
store, jump host, and ldap-client on top. Unless you need the components on
separate hosts, prefer the integrated stack.