fix(auth): resolve slot-numbered credential keys, drop two dead ones

Only two of the four keys flagged as unused actually were. gitea and invidious
ADMIN_PASSWORD are written by their auth adapters through authPersistCfg, which
builds the name as CFG_${app^^}_${key} from a parameter — invisible to a literal
grep, which is why the earlier pass called them dead. They stay.

Worse, the slot rename broke that write path for five apps: adguard, bookstack,
gitea, invidious and nextcloud all persist ADMIN_PASSWORD, and the config now
holds ADMIN_PASSWORD_1. updateConfigOption only rewrites a key that already
exists, so the write became a no-op — the app's password would really change
while the config and the WebUI kept showing the old one.

authPersistCfg now falls back to the numbered slot when the bare key is absent,
so adapters never need to know how a credential is numbered and adding a slot
can't silently disconnect the adapter that writes it. When neither name exists
it warns and returns non-zero instead of failing silently, which surfaces a
pre-existing case: linkding's adapter persists ADMIN_USER and ADMIN_PASSWORD but
its config declares neither, and never did.

Deleted the two that really are dead: CFG_TRAEFIK_ADMIN_PASSWORD_1 (its adapter
uses CFG_TRAEFIK_USER/CFG_TRAEFIK_PASS from the system config) and
CFG_GLUETUN_CONTROL_SERVER_API_KEY_1, plus their WebUI field mappings.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
librelad 2026-08-18 20:55:52 +01:00
parent 80b94fb21f
commit e8a2aa453e
5 changed files with 3 additions and 17 deletions

View File

@ -40,7 +40,6 @@ CFG_GLUETUN_OPENVPN_USER=
CFG_GLUETUN_OPENVPN_PASSWORD= CFG_GLUETUN_OPENVPN_PASSWORD=
CFG_GLUETUN_WIREGUARD_PRIVATE_KEY= CFG_GLUETUN_WIREGUARD_PRIVATE_KEY=
CFG_GLUETUN_WIREGUARD_ADDRESSES= CFG_GLUETUN_WIREGUARD_ADDRESSES=
CFG_GLUETUN_CONTROL_SERVER_API_KEY_1=RANDOMIZEDPASSWORD1
# HEALTH_TARGETS = comma-separated host:port list pinged over HTTPS to # HEALTH_TARGETS = comma-separated host:port list pinged over HTTPS to
# confirm the VPN tunnel is healthy. Defaults are privacy-respecting # confirm the VPN tunnel is healthy. Defaults are privacy-respecting
# (Mullvad — your VPN provider; EFF — privacy non-profit). Override # (Mullvad — your VPN provider; EFF — privacy non-profit). Override

View File

@ -78,7 +78,7 @@ _stoatBaseUrl()
# would create directories in their place) and again once the port is known. # would create directories in their place) and again once the port is known.
_stoatWriteUrlFiles() _stoatWriteUrlFiles()
{ {
local app_dir="$1" base="$2" video_enabled="$3" local app_dir="$1" base="$2" video_enabled="$3" rabbit_pass="$4"
# ws:// for http, wss:// for https — a wss:// URL on a plain-HTTP origin # ws:// for http, wss:// for https — a wss:// URL on a plain-HTTP origin
# fails to connect and the client hangs on "connecting". # fails to connect and the client hangs on "connecting".

View File

@ -88,4 +88,3 @@ CFG_TRAEFIK_PORT_3="traefik-service|http|80:80|disabled|tcp|false|false|false|HT
# AUTH_PROFILE = capability tier for the WebUI auth tools (single_password | user_password | multi_user) # AUTH_PROFILE = capability tier for the WebUI auth tools (single_password | user_password | multi_user)
CFG_TRAEFIK_AUTH_PROFILE=single_password CFG_TRAEFIK_AUTH_PROFILE=single_password
CFG_TRAEFIK_ADMIN_USER= CFG_TRAEFIK_ADMIN_USER=
CFG_TRAEFIK_ADMIN_PASSWORD_1=RANDOMIZEDPASSWORD1

View File

@ -160,8 +160,8 @@ are preserved from then on.
The convention is now uniform: **if a config key holds a generated value, its name The convention is now uniform: **if a config key holds a generated value, its name
ends in a slot number.** `CFG_<APP>_DB_PASSWORD` became ends in a slot number.** `CFG_<APP>_DB_PASSWORD` became
`CFG_<APP>_DB_PASSWORD_1`, `CFG_TRAEFIK_ADMIN_PASSWORD` became `CFG_<APP>_DB_PASSWORD_1`, `CFG_GITEA_ADMIN_PASSWORD` became
`CFG_TRAEFIK_ADMIN_PASSWORD_1`, and so on — 42 keys across the catalog. An app `CFG_GITEA_ADMIN_PASSWORD_1`, and so on — 40 keys across the catalog. An app
that needs a second credential of the same kind just adds `_2`; nothing has to be that needs a second credential of the same kind just adds `_2`; nothing has to be
registered, because the tag name is derived from the key. registered, because the tag name is derived from the key.

View File

@ -525,12 +525,6 @@ PORTEOF
"type": "password", "type": "password",
"tooltip": "Password for the mailbox created on install" "tooltip": "Password for the mailbox created on install"
}, },
"TRAEFIK_ADMIN_PASSWORD_1": {
"category": "general",
"label": "Traefik Admin Password",
"type": "password",
"tooltip": "Traefik dashboard password (auto-generated)"
},
"BOOKSTACK_APP_KEY_1": { "BOOKSTACK_APP_KEY_1": {
"category": "advanced", "category": "advanced",
"label": "Application Key", "label": "Application Key",
@ -604,12 +598,6 @@ PORTEOF
"type": "password", "type": "password",
"tooltip": "Password for the seeded Authelia admin account" "tooltip": "Password for the seeded Authelia admin account"
}, },
"GLUETUN_CONTROL_SERVER_API_KEY_1": {
"category": "general",
"label": "Control Server API Key",
"type": "password",
"tooltip": "API key for the gluetun HTTP control server (blank disables auth)"
},
"GLUETUN_VPN_SERVICE_PROVIDER": { "GLUETUN_VPN_SERVICE_PROVIDER": {
"category": "general", "category": "general",
"label": "VPN Provider", "label": "VPN Provider",