From ca0ddb1997f99a0b5aafd58b1ae661542a68f8f3 Mon Sep 17 00:00:00 2001 From: William Mantly Date: Sat, 11 Jul 2026 20:38:11 -0400 Subject: [PATCH] Expose SSO (3001) + proxy mgmt (3000) UIs on the LAN by default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SSO web UI and the proxy management UI were bound to 127.0.0.1, so they were only reachable from the host running the stack — inconvenient during first-run setup from another machine. Make the bind address configurable (SSO_BIND / MGMT_BIND, default 0.0.0.0) so both are LAN-reachable by default, with a one-line flip back to 127.0.0.1 once the proxy fronts them under TLS. Also: friendlier README with an upfront prerequisites section (domain, >=2 DNS records to the public IP, port-forward 80/443) and a note that .env values with spaces should be quoted. Co-Authored-By: Claude --- .env.example | 11 +++++++++-- README.md | 17 +++++++++++------ docker-compose.yml | 15 ++++++++------- 3 files changed, 28 insertions(+), 15 deletions(-) diff --git a/.env.example b/.env.example index 87f139b..fd46c0e 100644 --- a/.env.example +++ b/.env.example @@ -52,8 +52,7 @@ SMTP_PASS= SMTP_FROM= # ── Optional: host port overrides ─────────────────────────────────────────── -# SSO web UI (mapped to host for first-run convenience; the proxy fronts it in -# normal use, so you can leave it unmapped by setting SSO_PORT=0). +# SSO web UI + proxy mgmt UI host ports. SSO_PORT=3001 LDAPS_PORT=636 # Proxy listeners: @@ -62,6 +61,14 @@ HTTPS_PORT=443 HTTPS_ALT_PORT=4443 MGMT_PORT=3000 +# ── Optional: bind address for the SSO UI (3001) + proxy mgmt UI (3000) ─────── +# Default 0.0.0.0 = reachable on the LAN (convenient for first-run / admin from +# another machine). These UIs are login-protected, but exposing them widens the +# attack surface; once the proxy fronts both under TLS you can lock them to the +# host only by setting each to 127.0.0.1. +SSO_BIND=0.0.0.0 +MGMT_BIND=0.0.0.0 + # ── Optional: LDAP TLS cert CN (hostname LDAPS clients verify) ─────────────── # 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 diff --git a/README.md b/README.md index 507a840..cfa80a0 100644 --- a/README.md +++ b/README.md @@ -158,10 +158,11 @@ Optional: `BOOTSTRAP_ADMIN_EMAIL`, `LDAP_SERVICE_PASS` (auto-generated if blank) ## After setup - **SSO Manager UI**: `https://` — log in as your bootstrap admin to - add users, groups, and OAuth clients. (First-run fallback: - `http://127.0.0.1:3001`.) + add users, groups, and OAuth clients. (First-run fallback: `http://:3001`, + reachable on the LAN by default.) - **Proxy mgmt UI**: `https://` — add the Host records you want to - protect with OIDC. (First-run fallback: `http://127.0.0.1:3000`.) + protect with OIDC. (First-run fallback: `http://:3000`, reachable on the + LAN by default.) - **Direct LDAP for legacy apps**: bind to `ldaps://:636` as `cn=admin,` (admin) or `cn=ldapclient,ou=people,` (read-only service account the bootstrap created). Use LDAPS, not plain LDAP. @@ -230,9 +231,13 @@ exactly in the bootstrap) so the SSO can verify them on bind. ## Security notes -1. **Only expose 443 (and optionally 4443) to the internet.** The SSO's web port - (`3001`) is bound to localhost — the proxy fronts it. LDAPS (`636`) is the - only LDAP listener that should cross the network. +1. **Only expose 443 (and optionally 4443) to the internet.** The SSO web port + (`3001`) and the proxy mgmt UI (`3000`) default to `0.0.0.0` for first-run + convenience, so they're reachable on your LAN (they're login-protected, but + it widens the attack surface). The proxy fronts both under TLS in normal + use, so set `SSO_BIND=127.0.0.1` and `MGMT_BIND=127.0.0.1` in `.env` to lock + them to the host once you're up and running. LDAPS (`636`) is the only LDAP + listener that should cross the network. 2. **Persist + protect `.env` and `proxy.env`.** They hold `LDAP_ADMIN_PASS`, `JWT_SECRET`, the LDAP service password, and the OAuth client secret. `setup.sh` writes `proxy.env` mode `0600`; both are in `.gitignore`. diff --git a/docker-compose.yml b/docker-compose.yml index 01bcbb6..d7e4e7c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -23,10 +23,10 @@ services: restart: unless-stopped networks: [theta-net] ports: - # SSO web UI — bind to localhost only (first-run / admin convenience). In - # normal use the proxy fronts it at https://; don't expose 3001 - # to the LAN. Set SSO_PORT=0 in .env to still map (random) or firewall it. - - "127.0.0.1:${SSO_PORT:-3001}:3001" + # 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 in + # .env to lock it to localhost once the proxy fronts it at https://. + - "${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" @@ -75,9 +75,10 @@ services: - "${HTTP_PORT:-80}:80" - "${HTTPS_PORT:-443}:443" - "${HTTPS_ALT_PORT:-4443}:4443" - # Management UI/API — localhost only (the front proxies it under TLS in - # normal use; exposed on localhost for first-run setup / healthcheck). - - "127.0.0.1:${MGMT_PORT:-3000}:3000" + # 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 + # in .env to lock it to localhost once the proxy fronts it under TLS. + - "${MGMT_BIND:-0.0.0.0}:${MGMT_PORT:-3000}:3000" # Written by setup.sh from .env + the bootstrap output (OAuth client creds). # setup.sh creates it before starting the proxy, so it always exists. env_file: