docs: document that the domain/base DN is entered once (#37)

The base DN (stack.ldapBaseDn) is the single place the domain is set; the
LDAP DNs (bindDN/userBase/groupBase) and oauth.issuer all derive from it and
must stay consistent. Drifting them apart (leaving bindDN at dc=example,dc=com
while ldapBaseDn is the real domain) makes the SSO bind against a non-existent
root DN and every login fails with Invalid Credentials.

- secrets.js.example: clarifying comment at ldapBaseDn
- DEPLOYMENT.md: "domain entered once as the base DN" note + theta-env
  setup.env cross-link (merged the two duplicate theta-env blockquotes)
- README.md: cross-link to DEPLOYMENT.md from "Server set up"

Docs only; no app/secrets-structure change.

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
2026-07-13 21:56:48 -04:00
committed by GitHub
parent 796e013234
commit 11fb2c0a54
3 changed files with 25 additions and 4 deletions
+15 -3
View File
@@ -62,9 +62,21 @@ admin password, org, domain, cert CN, JWT secret) out of the same file. No
`app_*` env is passed — `app_*` env would override `secrets.js` (env beats the `app_*` env is passed — `app_*` env would override `secrets.js` (env beats the
file in `@simpleworkjs/conf`), so the file is kept authoritative. file in `@simpleworkjs/conf`), so the file is kept authoritative.
> Running the unified `theta-env` stack? Its `setup.sh` generates > **Your domain is entered once, as the LDAP base DN.** Set `stack.ldapBaseDn`
> `./config/sso-secrets.js` (+ `./config/proxy-secrets.js`) for you with random > (e.g. `dc=718it,dc=biz`) and keep the LDAP DNs consistent with it — they all
> secrets and snapshots state before rebuilds — see the theta-env README. > derive from that one value: `ldap.bindDN` = `cn=admin,<dn>`,
> `ldap.userBase` = `ou=people,<dn>`, `ldap.groupBase` = `ou=groups,<dn>`,
> and `stack.ldapDomain` = the dotted form (`718it.biz`). `oauth.issuer` is the
> public SSO URL (`https://<ssoHost>`). Drifting these apart (e.g. leaving
> `ldap.bindDN` at `dc=example,dc=com` while `stack.ldapBaseDn` is your real
> domain) makes the SSO bind against a non-existent root DN and every login
> fails with `Invalid Credentials`.
>
> Running the unified `theta-env` stack? You don't hand-edit these DNs at all
> — its `setup.sh` generates `./config/sso-secrets.js` (+ `./config/proxy-secrets.js`)
> from a single `setup.env` (where the domain is asked once, as the base DN) with
> random secrets, and snapshots state before rebuilds — so the DNs can't drift.
> See the theta-env README.
**Quick test (defaults):** with no `./config/sso-secrets.js` the entrypoint **Quick test (defaults):** with no `./config/sso-secrets.js` the entrypoint
falls back to env-mode with safe defaults (`dc=example,dc=com`, admin password falls back to env-mode with safe defaults (`dc=example,dc=com`, admin password
+6
View File
@@ -9,6 +9,12 @@ The server requires:
* NodeJS 13.x * NodeJS 13.x
* LDAP server * LDAP server
> Setting up the whole stack (Docker) or want the secrets-file layout? See
> [DEPLOYMENT.md](DEPLOYMENT.md) — your domain is entered **once**, as the LDAP
> base DN (`stack.ldapBaseDn`); the LDAP DNs (`bindDN`/`userBase`/`groupBase`)
> and `oauth.issuer` all derive from it and must stay consistent. Running the
> unified `theta-env` stack, `setup.sh` fills those in for you from `setup.env`.
### OpenLDAP configuration ### OpenLDAP configuration
#### Password hashing (required) #### Password hashing (required)
+4 -1
View File
@@ -52,7 +52,10 @@ module.exports = {
// Read by docker-entrypoint.sh (server-side slapd config + validation), the // Read by docker-entrypoint.sh (server-side slapd config + validation), the
// superproject bootstrap script, and setup.sh. Omit for bare-metal use. // superproject bootstrap script, and setup.sh. Omit for bare-metal use.
stack: { stack: {
ldapBaseDn: 'dc=example,dc=com', // slapd suffix (also drives seed OUs) ldapBaseDn: 'dc=example,dc=com', // slapd suffix (also drives seed OUs).
// The base DN also appears in ldap.bindDN/userBase/groupBase above and
// in oauth.issuer — keep them consistent with this value
// (cn=admin,<dn>, ou=people,<dn>, ou=groups,<dn>, https://<ssoHost>).
ldapDomain: 'example.com', // default cert CN + OAuth issuer host ldapDomain: 'example.com', // default cert CN + OAuth issuer host
ldapCertCn: '', // cert CN; empty -> defaults to ldapDomain ldapCertCn: '', // cert CN; empty -> defaults to ldapDomain
ssoHost: 'sso.example.com', // public SSO hostname (OAuth issuer URL) ssoHost: 'sso.example.com', // public SSO hostname (OAuth issuer URL)