60ba9ba989
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>
127 lines
5.3 KiB
YAML
127 lines
5.3 KiB
YAML
# theta-env — unified SSO Manager + Proxy.
|
|
#
|
|
# Brings up the two all-in-one images on one bridge network so the proxy can
|
|
# reach the SSO internally (http://sso-manager:3001 for token/userinfo,
|
|
# ldaps://sso-manager:636 for LDAP) without exposing the SSO's HTTP port to the
|
|
# internet. The proxy is the public front (80/443); the SSO sits behind it.
|
|
#
|
|
# Each project builds from its git submodule:
|
|
# ./sso-manager-node -> Dockerfile.openldap (app + OpenLDAP + Redis)
|
|
# ./proxy -> Dockerfile (OpenResty + app + Redis)
|
|
# So `git clone --recursive` is required to get the submodules first.
|
|
#
|
|
# Config + secrets live in bind-mounted ./config/ (gitignored):
|
|
# ./config/sso-secrets.js — SSO app + orchestrator config
|
|
# ./config/proxy-secrets.js — proxy OIDC/LDAP/auth config
|
|
# Each app's entrypoint symlinks its file into /app/conf/secrets.js so
|
|
# @simpleworkjs/conf reads it. No app_* env is passed (app_* env would override
|
|
# secrets.js). The sso-manager mounts ./config read-write so the bootstrap can
|
|
# write the generated OAuth client creds back into proxy-secrets.js; the proxy
|
|
# mounts it read-only.
|
|
#
|
|
# Compose only interpolates the port defaults below — there is no .env file.
|
|
# First-run wiring (LDAP service account, first admin, OAuth client) is
|
|
# automated by ./setup.sh, which runs bootstrap/bootstrap.js inside the
|
|
# sso-manager container.
|
|
|
|
services:
|
|
sso-manager:
|
|
build:
|
|
context: ./sso-manager-node
|
|
dockerfile: Dockerfile.openldap
|
|
container_name: sso-manager
|
|
restart: unless-stopped
|
|
networks: [theta-net]
|
|
ports:
|
|
# SSO web UI. Bind address is configurable via SSO_BIND (default 0.0.0.0 so
|
|
# the UI is reachable on the LAN during setup). Set SSO_BIND=127.0.0.1 to
|
|
# lock it to localhost once the proxy fronts it at https://<SSO_HOST>.
|
|
- "${SSO_BIND:-0.0.0.0}:${SSO_PORT:-3001}:3001"
|
|
# LDAPS for EXTERNAL direct-LDAP clients (legacy apps). The proxy itself
|
|
# reaches LDAPS over theta-net (sso-manager:636) without this host mapping.
|
|
- "${LDAPS_PORT:-636}:636"
|
|
# Plain LDAP (389) is NOT mapped — direct-LDAP clients should use LDAPS.
|
|
environment:
|
|
# Config (LDAP, OAuth, SMTP, ...) comes from ./config/sso-secrets.js (see
|
|
# volumes below), not from env. NODE_ENV/NODE_PORT are the only env the app
|
|
# reads that are not part of its conf tree.
|
|
- NODE_ENV=production
|
|
- NODE_PORT=3001
|
|
volumes:
|
|
# Operator-edited SSO secrets (sso-secrets.js). Read-WRITE so the bootstrap
|
|
# can write the generated OAuth client creds into proxy-secrets.js. The
|
|
# entrypoint symlinks /config/sso-secrets.js -> /app/conf/secrets.js.
|
|
- ./config:/config
|
|
# Persist the LDAP database across container recreation.
|
|
- ldap-data:/var/lib/ldap
|
|
# Persist the auto-generated self-signed TLS cert so clients don't have to
|
|
# re-trust it on every rebuild.
|
|
- ldap-certs:/etc/openldap/certs
|
|
# Persist Redis (AOF + RDB) so OAuth clients, tokens, and other Redis state
|
|
# survive container recreation.
|
|
- sso-data:/data
|
|
# Bind-mount the bootstrap script so `docker compose exec sso-manager node
|
|
# /bootstrap/bootstrap.js` can run it (read-only).
|
|
- ./bootstrap:/bootstrap:ro
|
|
healthcheck:
|
|
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3001/health"]
|
|
interval: 30s
|
|
timeout: 5s
|
|
retries: 3
|
|
start_period: 30s
|
|
|
|
proxy:
|
|
build:
|
|
context: ./proxy
|
|
dockerfile: Dockerfile
|
|
container_name: proxy
|
|
restart: unless-stopped
|
|
networks: [theta-net]
|
|
depends_on:
|
|
sso-manager:
|
|
condition: service_healthy
|
|
ports:
|
|
- "${HTTP_PORT:-80}:80"
|
|
- "${HTTPS_PORT:-443}:443"
|
|
- "${HTTPS_ALT_PORT:-4443}:4443"
|
|
# Management UI/API. Bind address is configurable via MGMT_BIND (default
|
|
# 0.0.0.0 so it's reachable on the LAN during setup). Set MGMT_BIND=127.0.0.1
|
|
# to lock it to localhost once the proxy fronts it under TLS.
|
|
- "${MGMT_BIND:-0.0.0.0}:${MGMT_PORT:-3000}:3000"
|
|
environment:
|
|
# oidc/ldap/auth config comes from ./config/proxy-secrets.js (see volumes),
|
|
# not from env. NODE_ENV/NODE_PORT are process env the app reads directly.
|
|
- NODE_ENV=production
|
|
- NODE_PORT=3000
|
|
volumes:
|
|
# Operator-edited proxy secrets (proxy-secrets.js). READ-ONLY — the proxy
|
|
# only reads it; the sso-manager bootstrap writes the OAuth creds. The
|
|
# entrypoint symlinks /config/proxy-secrets.js -> /app/conf/secrets.js.
|
|
- ./config:/config:ro
|
|
# Persist Redis (AOF + RDB) so Host records, permissions, DNS creds, local
|
|
# users, AND the auto-ssl Let's Encrypt certs survive container recreation.
|
|
- proxy-data:/data
|
|
- proxy-cache:/var/cache/nginx/proxy
|
|
- proxy-logs:/var/log/nginx
|
|
# OPTIONAL, for strict LDAPS trust (see README "Security notes"): mount
|
|
# the SSO's self-signed cert into the proxy read-only, then set
|
|
# ldap.tlsOptions.ca=<path-below> in ./config/proxy-secrets.js.
|
|
# - ldap-certs:/etc/ssl/sso-ldap-certs:ro
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-fsS", "http://localhost:3000/health"]
|
|
interval: 30s
|
|
timeout: 5s
|
|
retries: 3
|
|
start_period: 30s
|
|
|
|
networks:
|
|
theta-net:
|
|
driver: bridge
|
|
|
|
volumes:
|
|
ldap-data:
|
|
ldap-certs:
|
|
sso-data:
|
|
proxy-data:
|
|
proxy-cache:
|
|
proxy-logs: |