fix(settings): route seven editable keys to the service that reads them - #2517
Open
Hoang130203 wants to merge 2 commits into
Open
fix(settings): route seven editable keys to the service that reads them#2517Hoang130203 wants to merge 2 commits into
Hoang130203 wants to merge 2 commits into
Conversation
_match_apply_service() maps a changed .env key to the service that needs recreating. A key it does not recognise falls through to the manual bucket, and the dashboard tells the user to restart the whole stack. Ten documented, editable keys that exactly one compose service reads were falling through: OPEN_WEBUI_LLM_BASE_URL open-webui OPEN_WEBUI_* does not start with OPEN_WEBUI_LLM_API_KEY open-webui the WEBUI_ prefix the rule checks TARGET_API_KEY privacy-shield sibling of TARGET_API_URL, PII_CACHE_SIZE privacy-shield which is routed; sibling of PII_CACHE_TTL privacy-shield PII_CACHE_ENABLED, likewise BRAVE_SEARCH_API_KEY brave-search no rule for this service at all BRAVE_SEARCH_PORT brave-search TS_AUTHKEY tailscale no rule for this service at all TS_HOSTNAME tailscale TS_EXTRA_ARGS tailscale The privacy-shield ones are the clearest sign this is oversight rather than intent: TARGET_API_URL and PII_CACHE_ENABLED are in the set while the keys next to them in .env are not. Effect is downtime, not data loss: changing a Tailscale auth key made the dashboard ask for a full stack restart, taking every service down, when recreating the tailscale container was enough. Adds TestApplyServiceRouting (31 assertions): the ten newly routed keys, fifteen existing routes asserted unchanged, and the keys that must stay unrouted — _MANUAL_RESTART_KEYS and the *_PUBLIC_URL family — so this does not quietly grow into routing things that genuinely need a manual restart.
Correction to the previous commit. Routing a key is only half the job: _compute_env_apply_plan schedules a service only when it is also in _SETTINGS_APPLY_ALLOWED_SERVICES, and neither brave-search nor tailscale was. Those five keys routed and then fell straight back to the manual bucket, so the change did nothing for them. BRAVE_SEARCH_API_KEY services=[] "A manual stack restart is still..." TS_AUTHKEY services=[] "A manual stack restart is still..." brave-search joins the allowed set. It is an ordinary optional HTTP service, the same class as searxng and perplexica, which are already there. The TS_* routing is removed rather than allowed. Recreating the tailscale container can sever the very tailnet connection the operator is using to reach the dashboard, so promoting it from "restart the stack yourself" to "we will restart it for you" is a call for a maintainer, not a drive-by. Tests now assert the end-to-end plan for every routed key rather than _match_apply_service alone, which is what let the gap through, plus that TS_AUTHKEY still lands in the manual bucket on purpose.
23 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
settings._match_apply_service()maps a changed.envkey to the service thatneeds recreating. A key it does not recognise falls through to the manual
bucket, and the dashboard tells the user "A manual stack restart is still
required for: …".
I cross-checked every documented, editable key against the
${VAR}referencesin each service's compose block. Seven keys that exactly one service reads
were falling through:
OPEN_WEBUI_LLM_BASE_URLOPEN_WEBUI_*does not start with theWEBUI_prefix the rule checksOPEN_WEBUI_LLM_API_KEYTARGET_API_KEYTARGET_API_URLis in the set; this one is notPII_CACHE_SIZEPII_CACHE_ENABLEDis in the set; this one is notPII_CACHE_TTLBRAVE_SEARCH_API_KEYBRAVE_SEARCH_PORTThe privacy-shield rows are the clearest evidence this is oversight rather than
intent:
TARGET_API_URLandPII_CACHE_ENABLEDare routed, while the keyssitting next to them in
.envare not.The effect is downtime, not data loss. Changing the open-webui upstream or a
privacy-shield cache setting made the dashboard ask for a full stack restart —
every service down — when recreating one container was enough.
I want to be accurate about what this is not: the change was never silently
dropped. The apply plan does tell you a manual restart is needed, so nothing was
left in an inconsistent state. This is a worse-than-necessary remedy, not a
missing one.
Fix
key.startswith(("WEBUI_", "OPEN_WEBUI_"))instead of"WEBUI_"alone._PRIVACY_SHIELD_APPLY_KEYS._BRAVE_SEARCH_APPLY_KEYS, withbrave-searchadded to_SETTINGS_APPLY_ALLOWED_SERVICES.The correction in the second commit is the interesting part
Routing a key is only half the job —
_compute_env_apply_planschedules aservice only if it is also in
_SETTINGS_APPLY_ALLOWED_SERVICES. My firstpass routed
brave-searchandtailscalekeys without checking that gate, sofive of the ten I originally touched changed nothing at all:
brave-searchnow joins the allowed set — it is an ordinary optional HTTPservice, the same class as
searxngandperplexica, which are already there.The
TS_*routing is removed rather than allowed. Recreating the tailscalecontainer can sever the very tailnet connection the operator is using to reach
the dashboard, so promoting it from "restart the stack yourself" to "we will
restart it for you" is your call, not a drive-by. There is a test asserting
TS_AUTHKEYstill lands in the manual bucket on purpose.The tests now assert the end-to-end apply plan for every routed key, not
just
_match_apply_service— checking only the router is exactly what let thegate slip past me.
AI Assistance
AI assisted with drafting the tests and this description. I built the inventory
by parsing every service's compose block for
${VAR}references and runningeach key through the shipped
_match_apply_service; I caught the allowed-servicesgate by re-running the full apply plan rather than trusting the router alone.
Release Lane
release/2.6.xmainStable hotfix reason:
Changed Surface
(Two key sets, one prefix tuple and one entry in the allowed-services frozenset
in
settings.py, plus tests.)Risk And Validation
git diff --checkrelease/2.6.xCommands/results:
The assertions that pass either way are the deliberate ones: fifteen existing
routes (
WEBUI_PORT,CTX_SIZE,LLAMA_THREADS,SEARXNG_URL,QDRANT_PORT,APE_STRICT_MODE, …) asserted unchanged, plus_MANUAL_RESTART_KEYSand the*_PUBLIC_URLfamily asserted to stay unrouted. Those are there so this doesnot quietly grow into routing things that genuinely need a manual restart.
Operational Change Check
_match_apply_service()runs when the dashboard saves settings, to build theapply plan. The change moves seven keys from "restart the whole stack" to
"recreate one container", and adds one service to the set the dashboard is
permitted to recreate. No key moves the other way, and nothing already routed
changes — the fifteen unchanged-route assertions pin that. No write path or
schema change.
Notes For Reviewers
The inventory found more than I fixed, and the rest needs a decision I should
not make alone.
_match_apply_servicereturns a single service, but somekeys are read by several:
LLM_API_URLis the one worth your attention: it is routed, to llama-server,and returns before the open-webui branch — so changing it recreates llama-server
and leaves open-webui pointing at the old URL, with no manual-restart warning
either. That is the one genuinely silent case I found, and unlike the rest of
this PR it needs
_match_apply_serviceto return a set rather than one service,which changes the apply plan and its summary text. Say the word and I will send
it separately.
BIND_ADDRESSand the port keys are already in_MANUAL_RESTART_KEYS, so theyare handled deliberately.
Tailscale. If you do want
TS_*handled automatically, addingtailscaleto
_SETTINGS_APPLY_ALLOWED_SERVICESand restoring a three-line key set is thewhole change — I just did not want to make that trade on your behalf.
Litellm provider keys (
ANTHROPIC_API_KEY,TOGETHER_API_KEY,MINIMAX_API_KEY) are also unrouted and read only by litellm in compose. I leftthem out because they may be read elsewhere at runtime in cloud mode, and I
could not confirm that from compose alone. Easy to add if you know they are
litellm-only.