Files
wmantly a78db906e8 Fix SMTP From-address fallback rejection; catalog card icon order; doc corrections
Mail sending fell back to a hardcoded noreply@theta42.com From address when
smtp.from wasn't set, which authenticated relays reject with "Sender is not
same as SMTP authenticate username" since no relay authorized this account
to send as that address. Falls back to smtp.user first now.

Also: catalog card titles now read name-then-icon instead of icon-then-name,
and a handful of docs corrections found in an accuracy pass (configuration.md
missing the OpenBao/live-config layer, plugins.md undercounting plugin types,
vault.md describing OpenBao dev-mode/root-token access that doesn't reflect
the real production setup, orphaned discovery.md/vault.md pages linked in,
README's required-groups list missing app_sso_directory_admin).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0113gCdnfSCuZr6xvPDxTo3D
2026-08-06 21:13:38 -04:00

4.9 KiB

layout, title, description
layout title description
default Configuration SSO Manager's config layers — conf/base.js defaults, secrets.js overrides, and app_* environment variables.

Configuration

← Back to Home

The app loads configuration via @simpleworkjs/conf, which deep-merges, in order (later wins):

  1. conf/base.js — committed, generic defaults (dc=example,dc=com, localhost, SSO Manager).
  2. conf/<NODE_ENV>.js — optional, environment-specific.
  3. conf/secrets.js — gitignored; secrets + per-deployment values.
  4. app_* environment variables — the highest-precedence layer among these four.

Any env var whose name starts 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 (numbers, booleans, null, JSON) and kept as raw strings otherwise.

A fifth, higher-precedence layer: OpenBao + the Configuration UI

In a theta-suite deployment, @simpleworkjs/bao-conf's init() deep-merges secret/sso-manager/conf (from OpenBao) over the four layers above at boot — this is the layer setup.sh/theta-suite actually manages, and it wins over everything else here. On top of that, the admin Configuration page in the UI writes straight to secret/sso-manager/conf (via routes/api_conf.js) and applies the change to the live conf object immediately (applyToLiveConf) — no restart, and it bypasses conf/secrets.js entirely. If a value isn't behaving the way conf/secrets.js says it should, check the Configuration UI / OpenBao before assuming a file edit didn't take — it's almost certainly OpenBao (or a live UI edit) winning the merge.

Examples

Env var Sets Type
app_ldap__url=ldap://host:389 conf.ldap.url string
app_ldap__bindPassword=secret conf.ldap.bindPassword string
app_ldap__userBase=ou=people,dc=… conf.ldap.userBase string
app_ldap__uidGidMin=1500 conf.ldap.uidGidMin number (new-user id floor)
app_ldap__uidGidReservedFloor=9000 conf.ldap.uidGidReservedFloor number (ids at/above this are ignored when allocating)
app_ldap__ldapsHost=ldap.internal.example.com conf.ldap.ldapsHost string (hostname shown on /integrations for LDAPS binds; empty = derive from oauth.issuer)
app_ldap__ldapsPort=636 conf.ldap.ldapsPort number (port shown on /integrations)
app_oauth__jwtSecret=... conf.oauth.jwtSecret string
app_oauth__issuer=https://sso.example.com conf.oauth.issuer string
app_oauth__token_lifetime__access_token=3600 conf.oauth.token_lifetime.access_token number
app_smtp__secure=false conf.smtp.secure boolean
app_smtp__host=smtp.example.com conf.smtp.host string
app_name=My SSO conf.name string
app_redis__host=redis.local conf.redis.host string (external Redis)

The app_* env layer requires conf >= 1.1.0

The app_* environment-variable override layer was added in @simpleworkjs/conf 1.1.0. On 1.0.0 the app ignores all app_* vars and only reads base.js / <NODE_ENV>.js / secrets.js. The Docker image will not honor app_* env on 1.0.0. Refresh the lock from the nodejs/ directory:

cd nodejs && npm install @simpleworkjs/conf@^1.1.0

Inspecting the merged config

From the nodejs/ directory:

node -e "console.log(require('@simpleworkjs/conf').ldap)"
node -e "console.log(require('@simpleworkjs/conf').oauth)"
node -e "console.log(require('@simpleworkjs/conf'))"   # everything

Or, inside the running container:

docker compose exec sso-manager node -e "console.log(require('@simpleworkjs/conf').ldap)"

app_* env vars override secrets.js, which overrides base.js — if a value isn't what you expect, check those layers in that order.

Migrating an existing instance to the generic defaults

The committed nodejs/conf/base.js ships generic defaults (dc=example,dc=com, localhost, SSO Manager). Previously it carried Theta42-specific values (LDAP bind DN/bases, SMTP host/user/sender, OAuth issuer). If you run an existing instance off this repo:

  • Move per-deployment, non-secret values (bind DN, user/group bases, SMTP host/user/sender, OAuth issuer, org name) from base.js into your gitignored conf/secrets.js, or set them as app_* env vars.
  • Secret values (LDAP bind password, SMTP password, JWT secret) already belong in secrets.js.

Troubleshooting app_* env vars

app_* vars seem to do nothing

You're on @simpleworkjs/conf 1.0.0. Bump to 1.1.0+ (above).

LDAP operations 401 / "Invalid Credentials"

Check the merged LDAP config the app actually sees:

cd nodejs && node -e "console.log(require('@simpleworkjs/conf').ldap)"

Confirm url / bindDN / bindPassword / userBase match your directory.

← Back to Home