Lossless upgrades + config story for the all-in-one proxy image. Redis persistence (Part A): - Replace in-memory `--save "" --appendonly no` with AOF + RDB persisted to /data. Host records, permissions, DNS creds, local users, AND the lua-resty-auto-ssl Let's Encrypt certs now all survive container recreation (persisting Redis persists the cert store — no LE re-issue / rate-limit on rebuild). - Add the `proxy-data` named volume -> /data in docker-compose.yml; fix the stale "in-memory, lost on recreation" comment. Config from ./config/proxy-secrets.js (Part B): - docker-entrypoint.sh: when /config/proxy-secrets.js is mounted, symlink it to /app/conf/secrets.js so @simpleworkjs/conf reads the oidc/ldap/auth config from the file. No app_* env should then be passed (app_* beats secrets.js). Falls back to app_* env when the file is absent (standalone still works). - docker-compose.yml: drop all app_oidc__* / app_ldap__* / app_auth__* env and add `./config:/config:ro`. Keep RESOLVER/REAL_IP_FROM/NODE_ENV/NODE_PORT (OpenResty-runtime / process env, not app_* config). No env_file. - New secrets.js.example (the proxy had none): oidc (enabled, endpoints, clientId/clientSecret, redirectUri, scopes, claims), ldap (url, bindDN, bindPassword, searchBase, userFilter, tlsOptions), auth (adminGroups, adminUsers, groupRoleMap), plus an orchestrator-only `stack` key. Backup/restore docs: - Full "Backups and restore" runbook in DEPLOYMENT.md (what lives where, manual backup, Redis restore with the AOF-vs-RDB note — AOF wins on startup so the AOF must be deleted before an RDB load; restoring Redis restores cert state at snapshot time; migrations note). Update the Setup + Auto-SSL sections. - docs/docker.md: update Quick start + How configuration works + Auto-SSL for the new ./config/ approach (app_* env now advanced/optional). Co-authored-by: Claude <noreply@anthropic.com>
5.5 KiB
layout, title
| layout | title |
|---|---|
| default | Docker |
Docker Deployment
The proxy ships as a single all-in-one Docker image bundling OpenResty + the
Node management app + Redis in one container, mirroring the bare-metal
ops/install.sh
layout. This is the easiest way to run the proxy standalone, or as part of the
unified theta-env stack.
Quick start (standalone)
git clone https://github.com/theta42/proxy.git
cd proxy
mkdir -p config && chmod 700 config
cp secrets.js.example config/proxy-secrets.js # set OIDC/LDAP wiring
$EDITOR config/proxy-secrets.js
docker compose up -d --build
- Proxy (public, auto-SSL):
https://<host>/ - Management UI / API:
http://127.0.0.1:3000/(bound to localhost) - Health:
http://127.0.0.1:3000/health→{"status":"ok"}
How configuration works
The app loads config via @simpleworkjs/conf,
which deep-merges, in order:
conf/base.js(committed defaults)conf/<NODE_ENV>.js(optional)conf/secrets.js(gitignored)app_*environment variables — the highest-precedence layer
The bundled docker-compose.yml mount ./config/proxy-secrets.js at /config,
and docker-entrypoint.sh symlinks it into /app/conf/secrets.js so the app
reads the OIDC + LDAP + auth wiring from the file. No app_* env is passed —
app_* env beats secrets.js, so the file is authoritative only if the matching
app_* env is absent. See secrets.js.example for the shape.
Any env var starting with app_ overrides the merged config; the rest of the
name splits on double-underscore (__) into a nested path. Values are
JSON.parse-coerced when possible, kept as strings otherwise. app_* env is
still supported for advanced/standalone use — add the vars to the compose
environment: block yourself (the bundled compose no longer sets them).
Requires
@simpleworkjs/conf>= 1.1.0. Theapp_*env layer is not honored on 1.0.0. The lock is already on^1.1.0.
Key app_* variables
| Env var | Sets |
|---|---|
app_oidc__issuer |
conf.oidc.issuer (browser-facing SSO URL) |
app_oidc__authorizationEndpoint |
conf.oidc.authorizationEndpoint |
app_oidc__tokenEndpoint |
conf.oidc.tokenEndpoint (server-to-server; can be internal) |
app_oidc__userinfoEndpoint |
conf.oidc.userinfoEndpoint (server-to-server) |
app_oidc__endSessionEndpoint |
conf.oidc.endSessionEndpoint |
app_oidc__clientId / app_oidc__clientSecret |
OIDC client creds |
app_oidc__redirectUri |
conf.oidc.redirectUri (must match the SSO client) |
app_oidc__enabled |
conf.oidc.enabled (boolean) |
app_ldap__url |
conf.ldap.url (ldaps://…:636 or ldap://…:389) |
app_ldap__bindDN / app_ldap__bindPassword |
LDAP service account |
app_ldap__searchBase / app_ldap__userFilter |
user search |
app_ldap__tlsOptions__rejectUnauthorized |
false for self-signed LDAPS |
app_ldap__tlsOptions__ca |
path to a CA cert for strict trust |
app_auth__adminUsers |
local anti-lockout admin (uid) |
app_auth__adminGroups |
SSO/LDAP groups that are global admin (JSON array) |
app_redis__prefix |
conf.redis.prefix (default proxy_) |
See DEPLOYMENT.md
for the complete reference.
OpenResty runtime env
| Variable | Default | Description |
|---|---|---|
RESOLVER |
127.0.0.11 |
DNS for upstream names in Host records (Docker's embedded DNS) |
REAL_IP_FROM |
empty | Trusted CIDR for X-Real-IP. Empty = the proxy is the front (removes the real_ip block). Set to an upstream proxy's CIDR if one sits in front. |
Auto-SSL / Let's Encrypt
lua-resty-auto-ssl stores certs in the bundled Redis. Redis is now AOF+RDB
persisted to the proxy-data volume (not in-memory), so Let's Encrypt certs
survive container recreation — no re-issue / rate-limit on rebuild. Port 80 is
required for HTTP-01 challenges (mapped in the compose). Back up + restore Redis
to back up + restore cert state (see Backups and restore in DEPLOYMENT.md).
Fronting an SSO Manager
The proxy is a natural front for
theta42/sso-manager-node: it
terminates TLS for the SSO's UI and protects it with OIDC login, while also
binding to the SSO's LDAP directly for user lookups. To run both together:
- One Docker network so the proxy reaches the SSO internally at
http://sso-manager:3001(token/userinfo) andldaps://sso-manager:636. - Set the SSO's
app_oauth__issuerto the browser-facing HTTPS URL the proxy serves the SSO at (e.g.https://sso.example.com). - Register the proxy as an OIDC client in the SSO, with
redirectUrimatchinghttps://proxy.example.com/api/auth/oidc/callback. - LDAP: point
app_ldap__urlatldaps://sso-manager:636, create a dedicated service account (cn=ldapclient,ou=people,…), and for the SSO's self-signed LDAPS cert setapp_ldap__tlsOptions__rejectUnauthorized=false(or mount the cert and useapp_ldap__tlsOptions__ca=<path>).
The theta42/theta-env unified repo
automates all four steps with ./setup.sh — see
theta-env docs.
Bare metal
Prefer a systemd install? See the Installation Guide for
the ops/install.sh automated installer on Debian/Ubuntu.