Files
theta-suite/docs/quickstart.md
T
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

5.0 KiB

layout, title
layout title
default Quickstart

Quickstart Guide

← Back to Home

Prerequisites

  • A Linux host with Docker + Docker Compose (the v2 plugin docker compose or the v1 standalone docker-compose both work).
  • Two hostnames that resolve to the host: one for the SSO UI (your stack.ssoHost), one for the proxy mgmt UI (your stack.proxyHost). On a real network add DNS records; for a local try, add them to /etc/hosts.
  • Port 80 + 443 reachable from the internet if you want Let's Encrypt certs; otherwise the proxy serves a self-signed fallback (browsers warn — expected for LAN use).

1. Clone

git clone --recursive https://github.com/theta42/theta-env.git
cd theta-env

--recursive fetches the two submodules (sso-manager-node, proxy) in one step. If you forgot it:

git submodule update --init --recursive

2. Configure ./config/

./setup.sh        # generates ./config/ with random secrets, then exits

The first ./setup.sh generates ./config/sso-secrets.js + ./config/proxy-secrets.js and exits, telling you to edit. Edit ./config/sso-secrets.js and at minimum set:

Key (in sso-secrets.js) Example Notes
stack.ldapBaseDn dc=lab,dc=local your directory base
stack.ssoHost sso.lab.local hostname the proxy serves the SSO UI at
stack.proxyHost proxy.lab.local hostname the proxy serves its own UI at
bootstrap.adminUid admin your first admin login
bootstrap.adminPass ... first admin password

Random secrets (ldap.bindPassword, oauth.jwtSecret, serviceAccountPass) are generated for you — change them in the file if you like. Optional: bootstrap.adminEmail, smtp.*, stack.ldapCertCn. See config.example/ for the full annotated shape, and each submodule's secrets.js.example.

Migrating from an older .env-based deployment? If .env/proxy.env exist, ./setup.sh migrates them into ./config/ preserving your existing secrets — no need to reconfigure.

3. Run

./setup.sh

What happens:

  1. Snapshots state to ./backups/<timestamp>/ before rebuilding (a no-op on the very first run).
  2. Builds + starts sso-manager, waits for /health.
  3. Runs the bootstrap inside the sso-manager container — creates the LDAP service account, your first admin, and the proxy's OAuth client, and writes the generated client id + secret into ./config/proxy-secrets.js.
  4. Builds + starts proxy, waits for /health.
  5. Prints your first-admin login + the public URLs.

The first run builds two Docker images (a few minutes). Subsequent runs are fast.

4. Point DNS at the host

stack.ssoHost and stack.proxyHost (from ./config/sso-secrets.js) must resolve to the host running the stack. Add DNS records, or for a local try:

echo "127.0.0.1 sso.lab.local proxy.lab.local" | sudo tee -a /etc/hosts

(The proxy needs port 80 reachable for Let's Encrypt; on a LAN without that it serves a self-signed cert — browsers will warn, which is fine for home-lab use.)

5. Log in

Open https://<SSO_HOST> and log in as your bootstrap admin (bootstrap.adminUid / bootstrap.adminPass). From there you can add users, groups, and OAuth clients.

The proxy mgmt UI is at https://<PROXY_HOST> (same admin SSO login protects it). Add the Host records you want to protect with OIDC.

First-run fallbacks (if DNS/TLS isn't ready yet): SSO UI at http://127.0.0.1:3001, proxy UI at http://127.0.0.1:3000.

Re-running

./setup.sh is idempotent — safe to re-run after editing ./config/, after a docker compose down, or after restoring from backup. It snapshots state, then converges the stack to your ./config/ values (LDAP service account + admin passwords are reset to the config; the OAuth client is kept if proxy-secrets.js already holds its creds).

Direct LDAP for legacy apps

Legacy apps bind LDAP directly over LDAPS:

ldapsearch -x -H ldaps://<host>:636 \
  -D "cn=ldapclient,ou=people,dc=lab,dc=local" -W \
  -b "ou=people,dc=lab,dc=local" '(objectClass=posixAccount)' cn mail

Use the cn=ldapclient service account (read-only, the bootstrap created it) or the admin DN. Use LDAPS (636), not plain LDAP.

Backups and restore

./setup.sh auto-snapshots ./config/ + LDAP + both Redis to ./backups/<ts>/ before each rebuild (keeps the last BACKUP_KEEP, default 5). For manual backups and the full restore runbook (full / Redis-only / LDAP-only, with the AOF-vs-RDB note), see the Backups and restore section of the README. Quick LDAP backup:

docker compose exec sso-manager slapcat -f /etc/openldap/slapd.conf \
  -b "<base>" > backup-$(date +%F).ldif

Next steps

  • Add users / groups in the SSO UI.
  • Add Host records in the proxy UI to protect your apps with OIDC.
  • See Architecture for how it all fits together, and Standalone to run either project on its own.

← Back to Home