From 9a4020b7ec850cb6b2464bd1541a841eb6d46063 Mon Sep 17 00:00:00 2001 From: Codex Date: Thu, 8 Oct 2026 20:56:30 -0700 Subject: [PATCH] fix(litellm): restrict UI login to database users --- servers/tools-pve/litellm/.env.example | 2 -- servers/tools-pve/litellm/README.md | 9 ++++++++- servers/tools-pve/litellm/compose.yaml | 2 -- servers/tools-pve/litellm/render_config.py | 1 + servers/tools-pve/litellm/test_config.py | 4 ++++ 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/servers/tools-pve/litellm/.env.example b/servers/tools-pve/litellm/.env.example index c64afa0..f433c47 100644 --- a/servers/tools-pve/litellm/.env.example +++ b/servers/tools-pve/litellm/.env.example @@ -3,8 +3,6 @@ LITELLM_PORT=4000 POSTGRES_PASSWORD= LITELLM_MASTER_KEY= LITELLM_SALT_KEY= -UI_USERNAME=admin -UI_PASSWORD= ZENMUX_SUBSCRIPTION_API_KEY= ZENMUX_PAYG_API_KEY= OPENROUTER_API_KEY= diff --git a/servers/tools-pve/litellm/README.md b/servers/tools-pve/litellm/README.md index 230a97e..f56233a 100644 --- a/servers/tools-pve/litellm/README.md +++ b/servers/tools-pve/litellm/README.md @@ -61,7 +61,14 @@ Google AI Studio 预留独立 key 与模型表;取得有效 key 后查询目 真实 `.env` 权限 `0600`,不提交 Git;模板见 `.env.example`。 ZenMux subscription/PAYG 的 key 需要明确确认用途,不能按外观推断。 数据库密码使用无特殊 URL 字符的随机值,避免 `DATABASE_URL` 编码问题。 -`LITELLM_MASTER_KEY` 以 `sk-` 开头,salt 与 UI 密码独立随机生成。 +`LITELLM_MASTER_KEY` 以 `sk-` 开头,salt 独立随机生成。 +UI 使用数据库管理员 `kai@litellm.local`(只是登录标识,不发送邮件), +设置 `disable_env_credential_login: true`,禁用 UI_PASSWORD 以及 master key 的网页登录。 +临时密码保存在 .145 的 `.secrets/tools-litellm-ui-login.env`(0600); +首次登录必须修改,修改后该文件的临时密码不再有效。数据库保存密码哈希。 +master key 仍能管理 API,用于恢复权限,不再充当网页登录密码。 +不能直接用这份配置初始化空库后期待默认 admin 登录:必须预先通过 +`/user/new` 建立管理员,再 `/user/update` 设置临时密码,随后启用限制。 日常客户端应使用管理界面创建的应用专属 virtual key,不共享 master key。 不要开启输出请求全文的 debug 日志。 diff --git a/servers/tools-pve/litellm/compose.yaml b/servers/tools-pve/litellm/compose.yaml index 80ea461..661b489 100644 --- a/servers/tools-pve/litellm/compose.yaml +++ b/servers/tools-pve/litellm/compose.yaml @@ -34,8 +34,6 @@ services: DATABASE_URL: postgresql://litellm:${POSTGRES_PASSWORD:?required}@postgres:5432/litellm LITELLM_MASTER_KEY: ${LITELLM_MASTER_KEY:?required} LITELLM_SALT_KEY: ${LITELLM_SALT_KEY:?required} - UI_USERNAME: ${UI_USERNAME:-admin} - UI_PASSWORD: ${UI_PASSWORD:?required} ZENMUX_SUBSCRIPTION_API_KEY: ${ZENMUX_SUBSCRIPTION_API_KEY:-} ZENMUX_PAYG_API_KEY: ${ZENMUX_PAYG_API_KEY:-} OPENROUTER_API_KEY: ${OPENROUTER_API_KEY:-} diff --git a/servers/tools-pve/litellm/render_config.py b/servers/tools-pve/litellm/render_config.py index 2d552b5..91d6f6d 100644 --- a/servers/tools-pve/litellm/render_config.py +++ b/servers/tools-pve/litellm/render_config.py @@ -39,6 +39,7 @@ def build_config(catalog, env, exists): 'master_key': 'os.environ/LITELLM_MASTER_KEY', 'database_url': 'os.environ/DATABASE_URL', 'store_model_in_db': False, + 'disable_env_credential_login': True, }, 'litellm_settings': {'drop_params': False, 'set_verbose': False}, # No cross-provider or subscription-to-PAYG fallback without an explicit decision. diff --git a/servers/tools-pve/litellm/test_config.py b/servers/tools-pve/litellm/test_config.py index 12893f8..f3ad550 100644 --- a/servers/tools-pve/litellm/test_config.py +++ b/servers/tools-pve/litellm/test_config.py @@ -14,6 +14,10 @@ class ConfigTests(unittest.TestCase): def test_missing_credentials_exclude_routes(self): self.assertEqual(build_config(self.catalog, {}, lambda _: False)['model_list'], []) + def test_env_ui_login_disabled(self): + settings = build_config(self.catalog, {}, lambda _: False)['general_settings'] + self.assertTrue(settings['disable_env_credential_login']) + def test_subscription_preserves_vendor_prefix(self): routes = build_config(self.catalog, {'ZENMUX_SUBSCRIPTION_API_KEY': 'secret'}, lambda _: False)['model_list'] self.assertEqual(routes[0]['litellm_params']['model'], 'anthropic/anthropic/claude-sonnet-5.5')