Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3943ed02c5 | |||
| 7f43eee36e | |||
| 19ea7e012a | |||
| 94b357e915 | |||
| f5d8cdd09d | |||
| 96b3aec5eb | |||
| 5aff5349a8 | |||
| 3b0f8f1f9a | |||
| 28016376ad |
+7
-1
@@ -76,4 +76,10 @@ MGMT_BIND=0.0.0.0
|
||||
# Defaults to LDAP_DOMAIN. Set to the hostname the proxy connects via
|
||||
# (sso-manager inside the docker net uses the service name, which is in the
|
||||
# cert's SAN, so the default is usually fine).
|
||||
LDAP_CERT_CN=
|
||||
LDAP_CERT_CN=
|
||||
|
||||
# ── Optional: LDAPS hostname shown on the SSO /integrations page ────────────────
|
||||
# Leave blank to derive from the public SSO host (SSO_HOST). Set an internal-only
|
||||
# name like 'ldap.internal.example.com' or 'sso-manager' so direct-LDAP clients
|
||||
# don't need a public 636 port forward. See docs/ldap.md for network layouts.
|
||||
LDAPS_HOST=
|
||||
+36
-1
@@ -10,6 +10,41 @@ for what changed inside the apps it composes.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [1.1.20] - 2026-07-20
|
||||
|
||||
### Bumped
|
||||
- proxy -> [v1.1.17](https://github.com/theta42/proxy/releases/tag/v1.1.17)
|
||||
|
||||
proxy:
|
||||
|
||||
### Fixed
|
||||
- An existing single-label subdomain host (e.g. `sso.nl.wgnode.com`) could not be attached to a wildcard cert added later (e.g. `*.nl.wgnode.com`): `Host.lookUpWildcardParent()` only checked the wildcard-as-child position (the wildcard's own base domain) and missed the far more common wildcard-as-sibling case, so the edit form's "Parent Wildcard" option stayed permanently greyed out. It now checks both positions, and a regression test covers the sibling case.
|
||||
|
||||
## [1.1.19] - 2026-07-18
|
||||
|
||||
### Bumped
|
||||
- sso-manager-node -> [v1.1.17](https://github.com/theta42/sso-manager-node/releases/tag/v1.1.17)
|
||||
|
||||
sso-manager-node:
|
||||
|
||||
### Added
|
||||
- `conf.ldap.ldapsHost` and `conf.ldap.ldapsPort` config options for advertising a separate, internal-only LDAPS hostname on the `/integrations` page. Falls back to the public OAuth issuer host when unset.
|
||||
- Contextual help panel on `/integrations` → LDAP explaining why LDAPS needs a hostname, why port 636 should not be forwarded publicly, and the recommended internal-DNS / Docker-internal alternatives.
|
||||
- Tests for the `/integrations` route's LDAPS URL derivation and `ldapsHost` override.
|
||||
|
||||
### Changed
|
||||
- `nodejs/package.json` / `package-lock.json` version bumped to `1.1.17`.
|
||||
- `routes/index.js` now derives the displayed LDAPS URL from `conf.ldap.ldapsHost`/`ldapsPort` with fallback to the OAuth issuer host.
|
||||
- `docs/configuration.md`, `docs/ldap.md`, `DEPLOYMENT.md`, and `secrets.js.example` document the new `ldapsHost`/`ldapsPort` options and recommended network layouts.
|
||||
|
||||
### theta-env own changes
|
||||
- `setup.env.example` adds optional `CFG_LDAPS_HOST` for the internal LDAPS hostname.
|
||||
- `setup.sh` passes `CFG_LDAPS_HOST` into the generated `./config/sso-secrets.js` as `ldap.ldapsHost`.
|
||||
- `config.example/sso-secrets.js.example` documents `ldap.ldapsHost` / `ldap.ldapsPort`.
|
||||
- `.env.example` adds `LDAPS_HOST` for legacy `.env` migrations.
|
||||
- `docker-compose.yml` comments warn against forwarding 636 to the public internet.
|
||||
- `README.md` explains the `CFG_LDAPS_HOST` recommendation in the port-forwarding section.
|
||||
|
||||
## [1.1.18] - 2026-07-18
|
||||
|
||||
### Bumped
|
||||
@@ -257,7 +292,7 @@ First tagged release. Establishes the `vX.Y.Z` tag convention going forward.
|
||||
- proxy -> [v1.1.0](https://github.com/theta42/proxy/releases/tag/v1.1.0)
|
||||
- sso-manager-node -> [v1.1.0](https://github.com/theta42/sso-manager-node/releases/tag/v1.1.0)
|
||||
|
||||
[Unreleased]: https://github.com/theta42/theta-env/compare/v1.1.18...HEAD
|
||||
[Unreleased]: https://github.com/theta42/theta-env/compare/v1.1.20...HEAD
|
||||
[1.1.17]: https://github.com/theta42/theta-env/compare/v1.1.16...v1.1.17
|
||||
[1.1.16]: https://github.com/theta42/theta-env/compare/v1.1.15...v1.1.16
|
||||
[1.1.15]: https://github.com/theta42/theta-env/compare/v1.1.14...v1.1.15
|
||||
|
||||
@@ -60,6 +60,8 @@ It is **both** an OIDC client of the SSO (for login) **and** a direct LDAP
|
||||
client (for user lookups). Legacy apps can still bind to LDAPS on the SSO
|
||||
directly.
|
||||
|
||||
- **Multi-Site Support (Geo-Location Scaling):** Built-in support for N-Way Multi-Master LDAP replication, allowing you to deploy the stack across multiple physical locations for HA and low latency.
|
||||
|
||||
---
|
||||
|
||||
## Before you begin
|
||||
@@ -120,6 +122,10 @@ Optional extra ports (only if you need them):
|
||||
- **636** (LDAPS) — only if a legacy app on another machine binds to LDAP
|
||||
directly over the network. The proxy itself reaches LDAP over the internal
|
||||
Docker network, so you do **not** need to expose 636 for the stack to work.
|
||||
**Do not forward 636 to the public internet.** If you need LAN clients to bind
|
||||
LDAP, set `CFG_LDAPS_HOST=ldap.internal.example.com` (or `sso-manager` for
|
||||
same-host Docker clients) in `setup.env` and use an internal DNS record / cert
|
||||
SAN. The default shows the public SSO hostname, which implies a public route.
|
||||
|
||||
### 4. Docker + Docker Compose
|
||||
|
||||
|
||||
@@ -17,6 +17,9 @@ module.exports = {
|
||||
bindPassword: 'CHANGE-ME', // slapd root + app bind password
|
||||
userBase: 'ou=people,dc=example,dc=com',
|
||||
groupBase: 'ou=groups,dc=example,dc=com',
|
||||
// ldapsHost: 'ldap.internal.example.com', // optional: internal-only hostname
|
||||
// shown on /integrations for direct LDAPS binds. Empty -> derive from issuer.
|
||||
// ldapsPort: 636,
|
||||
},
|
||||
smtp: { // optional; leave host '' to skip
|
||||
host: '', port: 587, secure: false,
|
||||
|
||||
@@ -46,6 +46,8 @@ services:
|
||||
- "${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.
|
||||
# Prefer an internal-only hostname (set CFG_LDAPS_HOST in setup.env / ldapsHost
|
||||
# in sso-secrets.js) and do NOT forward 636 to the public internet.
|
||||
- "${LDAPS_PORT:-636}:636"
|
||||
# Plain LDAP (389) is NOT mapped — direct-LDAP clients should use LDAPS.
|
||||
environment:
|
||||
@@ -54,6 +56,8 @@ services:
|
||||
# reads that are not part of its conf tree.
|
||||
- NODE_ENV=production
|
||||
- NODE_PORT=3001
|
||||
- LDAP_SERVER_ID=${LDAP_SERVER_ID:-}
|
||||
- LDAP_REPLICATION_HOSTS=${LDAP_REPLICATION_HOSTS:-}
|
||||
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
|
||||
|
||||
@@ -44,6 +44,7 @@ snapshots state before every rebuild.
|
||||
- **LDAPS** for legacy apps that bind directly.
|
||||
- **Self-service API tokens** in both apps' UIs, for scripting/CI without a
|
||||
browser session.
|
||||
- **Multi-Site Support (Geo-Location Scaling)** — built-in support for N-Way Multi-Master LDAP replication across physical locations.
|
||||
|
||||
## Get it
|
||||
|
||||
|
||||
+1
-1
Submodule proxy updated: 289a9587d6...21e295615b
+19
-1
@@ -36,6 +36,12 @@ CFG_DOMAIN=example.com
|
||||
#CFG_ADMIN_UID=admin # initial SSO admin username
|
||||
#CFG_ADMIN_EMAIL=admin@proxy.example.com # defaults to admin@<proxyHost>
|
||||
#CFG_LDAP_CERT_CN= # LDAP TLS cert CN; empty -> defaults to the domain
|
||||
#
|
||||
# Hostname advertised on the SSO /integrations page for direct LDAPS binds.
|
||||
# Leave blank to derive it from the public SSO host (same as oauth.issuer).
|
||||
# Recommended: set an internal-only name like 'ldap.internal.example.com' or
|
||||
# 'sso-manager' so clients don't need a public 636 port forward. See docs.
|
||||
#CFG_LDAPS_HOST=
|
||||
|
||||
# Optional SMTP (outbound email from the SSO app). Leave blank to disable:
|
||||
#CFG_SMTP_HOST=smtp.example.com
|
||||
@@ -52,4 +58,16 @@ CFG_DOMAIN=example.com
|
||||
# password is the exception — see ./config/proxy-secrets.js's auth.localAdminPass
|
||||
# comment for how to actually change it after the account exists). Do NOT set
|
||||
# CFG_LDAP_ADMIN_PASS / CFG_JWT_SECRET / CFG_ADMIN_PASS / CFG_SVC_PASS /
|
||||
# CFG_PROXY_ADMIN_PASS here.
|
||||
# CFG_PROXY_ADMIN_PASS here.
|
||||
|
||||
# ── Geo-Location Scaling (N-Way Multi-Master LDAP) ───────────────────────────
|
||||
# If deploying this stack across multiple physical sites to provide local HA
|
||||
# for directory services, you can enable N-Way Multi-Master OpenLDAP replication.
|
||||
# This requires assigning a unique ID to each site and listing the LDAPS URLs
|
||||
# of all OTHER sites in the cluster.
|
||||
#
|
||||
# Each site MUST have a unique LDAP_SERVER_ID (e.g. 1, 2, 3).
|
||||
# LDAP_REPLICATION_HOSTS is a space-separated list of the other sites' LDAP URLs.
|
||||
# Example for Site 1:
|
||||
#LDAP_SERVER_ID=1
|
||||
#LDAP_REPLICATION_HOSTS="ldaps://sso.site2.com:636 ldaps://sso.site3.com:636"
|
||||
@@ -240,6 +240,8 @@ module.exports = {
|
||||
bindPassword: $(js_str "$CFG_LDAP_ADMIN_PASS"),
|
||||
userBase: $(js_str "ou=people,${dn}"),
|
||||
groupBase: $(js_str "ou=groups,${dn}"),
|
||||
ldapsHost: $(js_str "${CFG_LDAPS_HOST:-}"),
|
||||
ldapsPort: 636,
|
||||
},
|
||||
smtp: {
|
||||
host: $(js_str "${CFG_SMTP_HOST:-}"),
|
||||
@@ -355,6 +357,7 @@ ensure_config() {
|
||||
CFG_ADMIN_UID="${CFG_ADMIN_UID:-}"
|
||||
CFG_ADMIN_EMAIL="${CFG_ADMIN_EMAIL:-}"
|
||||
CFG_LDAP_CERT_CN="${CFG_LDAP_CERT_CN:-}"
|
||||
CFG_LDAPS_HOST="${CFG_LDAPS_HOST:-}"
|
||||
CFG_CLIENT_ID="${CFG_CLIENT_ID:-}"
|
||||
CFG_CLIENT_SECRET="${CFG_CLIENT_SECRET:-}"
|
||||
CFG_LDAP_ADMIN_PASS="${CFG_LDAP_ADMIN_PASS:-}"
|
||||
@@ -383,6 +386,8 @@ ensure_config() {
|
||||
CFG_ADMIN_PASS="${BOOTSTRAP_ADMIN_PASS:-$CFG_ADMIN_PASS}"
|
||||
CFG_SVC_PASS="${LDAP_SERVICE_PASS:-$CFG_SVC_PASS}"
|
||||
CFG_LDAP_CERT_CN="${LDAP_CERT_CN:-$CFG_LDAP_CERT_CN}"
|
||||
# .env has no legacy LDAPS_HOST key; this stays as set in setup.env/env.
|
||||
CFG_LDAPS_HOST="${CFG_LDAPS_HOST:-}"
|
||||
CFG_SMTP_HOST="${SMTP_HOST:-${CFG_SMTP_HOST:-}}"
|
||||
CFG_SMTP_PORT="${SMTP_PORT:-${CFG_SMTP_PORT:-}}"
|
||||
CFG_SMTP_USER="${SMTP_USER:-${CFG_SMTP_USER:-}}"
|
||||
@@ -416,6 +421,7 @@ ensure_config() {
|
||||
CFG_ADMIN_UID="${CFG_ADMIN_UID:-admin}"
|
||||
CFG_ADMIN_EMAIL="${CFG_ADMIN_EMAIL:-admin@$CFG_PROXY_HOST}"
|
||||
CFG_LDAP_CERT_CN="${CFG_LDAP_CERT_CN:-}"
|
||||
CFG_LDAPS_HOST="${CFG_LDAPS_HOST:-}"
|
||||
CFG_CLIENT_ID="${CFG_CLIENT_ID:-}"
|
||||
CFG_CLIENT_SECRET="${CFG_CLIENT_SECRET:-}"
|
||||
# Random secrets (generated fresh unless sourced/migrated above). These do
|
||||
|
||||
+1
-1
Submodule sso-manager-node updated: 5a8030fd7d...6ce36b4a14
Reference in New Issue
Block a user