diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c470d1..7524c53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,20 @@ correspond to git tags (`vX.Y.Z`) and `nodejs/package.json`'s `version`. ## [Unreleased] +## [1.2.1] - 2026-07-21 + +### Fixed +- The bootstrap anti-lockout admin account was always created as `proxyadmin2` regardless of `conf.auth.adminUsers`, while `migrations/permission_bootstrap.js` grants the global-admin permission to `conf.auth.adminUsers[0]`. If an operator customized `adminUsers` away from the default, the bootstrapped account and the permissioned account were two different (non-matching) usernames, so the anti-lockout account ended up with no admin access. `models/user_redis.js` now derives the bootstrap username from `conf.auth.adminUsers[0]` (falling back to `proxyadmin2`), matching `permission_bootstrap.js`. +- Corrected a `secrets.js.example` comment that claimed the bootstrap admin's password "defaults to the username itself" — it actually generates a random password printed to the container log on first boot. + +### Changed +- Refreshed all README screenshots (hosts, per-host SSO auth, per-host basic auth) against the current UI, and added a new load-balancing screenshot for the multi-target feature. + +## [1.2.0] - 2026-07-21 + +### Added +- Multi-target load balancing: hosts can now specify additional backend targets (`IP:port`, one per line) alongside the primary target; the proxy distributes requests across all of them round-robin via `lua-resty-balancer`. Fixes #47. + ## [1.1.17] - 2026-07-20 ### Fixed diff --git a/README.md b/README.md index 3cf717c..7472826 100755 --- a/README.md +++ b/README.md @@ -31,6 +31,10 @@ management once basic auth is enabled: [![Per-host basic auth](docs/images/host-auth-basic.png)](docs/images/host-auth-basic.png) +Multiple backend targets per host, load balanced round-robin: + +[![Load balancing](docs/images/load-balancing.png)](docs/images/load-balancing.png) + ## Why this over the alternatives Nginx Proxy Manager, Traefik, and Caddy are all good reverse proxies with diff --git a/docs/images/host-auth-basic.png b/docs/images/host-auth-basic.png index b880082..ffc64d9 100644 Binary files a/docs/images/host-auth-basic.png and b/docs/images/host-auth-basic.png differ diff --git a/docs/images/host-auth-sso.png b/docs/images/host-auth-sso.png index fa05a4f..8503a6a 100644 Binary files a/docs/images/host-auth-sso.png and b/docs/images/host-auth-sso.png differ diff --git a/docs/images/hosts.png b/docs/images/hosts.png index 24b9257..19e8cb1 100644 Binary files a/docs/images/hosts.png and b/docs/images/hosts.png differ diff --git a/docs/images/load-balancing.png b/docs/images/load-balancing.png new file mode 100644 index 0000000..d21f2b9 Binary files /dev/null and b/docs/images/load-balancing.png differ diff --git a/nodejs/models/user_redis.js b/nodejs/models/user_redis.js index 3f5149f..c543197 100644 --- a/nodejs/models/user_redis.js +++ b/nodejs/models/user_redis.js @@ -87,7 +87,11 @@ class User extends Table{ User.register(); (async function(){ - var defaultUser = 'proxyadmin2' + // Matches migrations/permission_bootstrap.js: the anti-lockout account is + // the first entry in conf.auth.adminUsers (default 'proxyadmin2'), NOT a + // hardcoded name -- otherwise an operator who customizes adminUsers ends + // up with a bootstrap account that has no admin permissions. + var defaultUser = (conf.auth && conf.auth.adminUsers && conf.auth.adminUsers[0]) || 'proxyadmin2'; // Optional: an orchestrator (e.g. theta-env's setup.sh) can set // auth.localAdminPass in proxy-secrets.js to a generated password so this // bootstrap account isn't left at a well-known default. Only used on first diff --git a/nodejs/package-lock.json b/nodejs/package-lock.json index 8d46a41..37b8d42 100644 --- a/nodejs/package-lock.json +++ b/nodejs/package-lock.json @@ -1,12 +1,12 @@ { "name": "proxy-api", - "version": "1.1.17", + "version": "1.2.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "proxy-api", - "version": "1.1.17", + "version": "1.2.1", "license": "MIT", "dependencies": { "@fortawesome/fontawesome-free": "^7.3.0", diff --git a/nodejs/package.json b/nodejs/package.json index fd53153..09504a4 100644 --- a/nodejs/package.json +++ b/nodejs/package.json @@ -1,6 +1,6 @@ { "name": "proxy-api", - "version": "1.1.17", + "version": "1.2.1", "author": [ { "name": "William Mantly", diff --git a/secrets.js.example b/secrets.js.example index 0bdc33e..2e49471 100644 --- a/secrets.js.example +++ b/secrets.js.example @@ -67,12 +67,14 @@ module.exports = { adminUsers: ['proxyadmin'], groupRoleMap: {}, // Optional: the local anti-lockout admin's initial password, used - // ONLY the first time that account is created. Leave unset and it - // defaults to the username itself ("proxyadmin2") — fine for a quick - // local test, but change it (or set this) before exposing the proxy - // publicly. Once the account exists, this key is never read again; - // change the password via the app itself (or delete the Redis user - // to force it to be re-bootstrapped with a new value here). + // ONLY the first time that account is created. Leave unset and a + // random password is generated and printed to the container log on + // first boot — fine for a quick local test if you copy it from the + // log right away, but set this (or change the password afterward) + // before exposing the proxy publicly. Once the account exists, this + // key is never read again; change the password via the app itself + // (or delete the Redis user to force it to be re-bootstrapped with a + // new value here). // localAdminPass: 'change-me', },