From 77983dbd42d6dae9822f3d2c85a89c4e43d590ee Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Mon, 22 Jun 2026 16:59:08 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=B3=20feat:=20Bundle=20Admin=20Panel?= =?UTF-8?q?=20in=20Docker=20Compose=20Stacks=20(#13876)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 🐳 feat: Bundle ClickHouse Admin Panel in Docker Compose Stacks * chore: route admin-panel image through Scarf gateway * chore: route admin-panel image through Scarf gateway (deploy-compose) * 📝 docs: Add Admin Panel to README Features * 🏷️ chore: Rename Admin Panel Container to admin-panel * 🔐 fix: Fall Back Admin Panel SESSION_SECRET to CREDS_KEY * 📝 docs: Reference Open-Source code-interpreter Repo in README --- .env.example | 10 ++++++++ README.md | 6 +++++ client/nginx.conf | 59 ++++++++++++++++++++++++++++++++++++++++++++++ deploy-compose.yml | 15 ++++++++++++ docker-compose.yml | 14 +++++++++++ 5 files changed, 104 insertions(+) diff --git a/.env.example b/.env.example index d9a32d076b..3622c660c7 100644 --- a/.env.example +++ b/.env.example @@ -39,6 +39,16 @@ DOMAIN_SERVER=http://localhost:3080 # Example: https://admin.example.com/admin ADMIN_PANEL_URL= +# Session encryption key for the bundled admin panel (min 32 characters). +# The admin panel ships enabled in docker-compose/deploy-compose; the value +# below is a development default. Generate a unique one for production: +# openssl rand -hex 32 +ADMIN_PANEL_SESSION_SECRET=0f7114d0b0b192b59fde7e3b730949b27d49a8717fa32ad3167d94c7684fede3 + +# Host port for the bundled admin panel (default docker-compose only). +# In deploy-compose the panel is served at http://admin.localhost via nginx. +# ADMIN_PANEL_PORT=3000 + NO_INDEX=true # Use the address that is at most n number of hops away from the Express application. # req.socket.remoteAddress is the first hop, and the rest are looked for in the X-Forwarded-For header from right to left. diff --git a/README.md b/README.md index 86deec5b28..54bf286e85 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,7 @@ - Secure, Sandboxed Execution in Python, Node.js (JS/TS), Go, C/C++, Java, PHP, Rust, and Fortran - Seamless File Handling: Upload, process, and download files directly - No Privacy Concerns: Fully isolated and secure execution + - Open-Source & Self-Hostable: powered by [ClickHouse/code-interpreter](https://github.com/ClickHouse/code-interpreter) - 🔦 **Agents & Tools Integration**: - **[LibreChat Agents](https://www.librechat.ai/docs/features/agents)**: @@ -137,6 +138,11 @@ - Multi-User, Secure Authentication with OAuth2, LDAP, & Email Login Support - Built-in Moderation, and Token spend tools +- 🎛️ **[Admin Panel](https://www.librechat.ai/docs/features/admin_panel)**: + - Browser-based UI to manage users, groups, roles, and configuration overrides + - Edit settings and per-role/group permissions live, without redeploying + - Bundled with the Docker Compose stacks for one-command setup + - ⚙️ **Configuration & Deployment**: - Configure Proxy, Reverse Proxy, Docker, & many Deployment options - Use [S3 with CloudFront](https://www.librechat.ai/docs/configuration/cdn/cloudfront) for stable media links, edge delivery, signed cookies, and secured downloads diff --git a/client/nginx.conf b/client/nginx.conf index 906b3af128..3df5d7b92d 100644 --- a/client/nginx.conf +++ b/client/nginx.conf @@ -2,6 +2,12 @@ # generated 2024-01-21, Mozilla Guideline v5.7, nginx 1.24.0, OpenSSL 3.1.4, intermediate configuration # https://ssl-config.mozilla.org/#server=nginx&version=1.24.0&config=intermediate&openssl=3.1.4&guideline=5.7 +# Map the Upgrade header so the admin-panel proxy can pass WebSocket/SSE connections. +map $http_upgrade $connection_upgrade { + default upgrade; + '' close; +} + server { listen 80 default_server; listen [::]:80 default_server; @@ -38,6 +44,31 @@ server { # } } +# Admin panel (ClickHouse) served on the admin.localhost subdomain. +# Uses Docker's embedded DNS (127.0.0.11) with a variable upstream so nginx +# still starts when the admin-panel service is not running. +server { + listen 80; + listen [::]:80; + server_name admin.localhost; + + client_max_body_size 25M; + + resolver 127.0.0.11 valid=30s; + set $admin_panel_upstream http://admin-panel:3000; + + location / { + proxy_pass $admin_panel_upstream; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + } +} + #server { # listen 443 ssl http2; # listen [::]:443 ssl http2; @@ -98,3 +129,31 @@ server { # proxy_set_header Host $host; # } #} + +# SSL variant for the admin panel subdomain (mirror of the admin.localhost block above). +# Over HTTPS you can also set ADMIN_PANEL_SESSION_COOKIE_SECURE=true on the admin-panel service. +#server { +# listen 443 ssl http2; +# listen [::]:443 ssl http2; + +# ssl_certificate /etc/nginx/ssl/nginx.crt; +# ssl_certificate_key /etc/nginx/ssl/nginx.key; + +# server_name admin.localhost; + +# client_max_body_size 25M; + +# resolver 127.0.0.11 valid=30s; +# set $admin_panel_upstream http://admin-panel:3000; + +# location / { +# proxy_pass $admin_panel_upstream; +# proxy_set_header Host $host; +# proxy_set_header X-Real-IP $remote_addr; +# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +# proxy_set_header X-Forwarded-Proto $scheme; +# proxy_http_version 1.1; +# proxy_set_header Upgrade $http_upgrade; +# proxy_set_header Connection $connection_upgrade; +# } +#} diff --git a/deploy-compose.yml b/deploy-compose.yml index e581aed80f..77d6161a7d 100644 --- a/deploy-compose.yml +++ b/deploy-compose.yml @@ -30,6 +30,7 @@ services: - http_proxy=${http_proxy:-} - https_proxy=${https_proxy:-} - no_proxy=${no_proxy:-localhost,127.0.0.1,::1},${NO_PROXY:-},mongodb,chat-mongodb,meilisearch,chat-meilisearch,rag_api,vectordb,host.docker.internal + - ADMIN_PANEL_URL=${ADMIN_PANEL_URL:-http://admin.localhost} volumes: - type: bind source: ./librechat.yaml @@ -39,6 +40,19 @@ services: - ./logs:/app/api/logs - ./skill:/app/skill + admin-panel: + image: registry.librechat.ai/clickhouse/librechat-admin-panel:latest + container_name: admin-panel + depends_on: + - api + restart: always + environment: + - PORT=3000 + - SESSION_SECRET=${ADMIN_PANEL_SESSION_SECRET:-${CREDS_KEY}} + - API_SERVER_URL=http://api:3080 + - VITE_API_BASE_URL=${DOMAIN_CLIENT:-http://localhost} + - SESSION_COOKIE_SECURE=${ADMIN_PANEL_SESSION_COOKIE_SECURE:-false} + client: image: nginx:1.27.0-alpine container_name: LibreChat-NGINX @@ -47,6 +61,7 @@ services: - 443:443 depends_on: - api + - admin-panel restart: always volumes: - ./client/nginx.conf:/etc/nginx/conf.d/default.conf diff --git a/docker-compose.yml b/docker-compose.yml index dd3880a767..1476231df6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -35,6 +35,20 @@ services: - ./uploads:/app/uploads - ./logs:/app/logs - ./skill:/app/skill + admin-panel: + container_name: admin-panel + image: registry.librechat.ai/clickhouse/librechat-admin-panel:latest + ports: + - "${ADMIN_PANEL_PORT:-3000}:3000" + depends_on: + - api + restart: always + environment: + - PORT=3000 + - SESSION_SECRET=${ADMIN_PANEL_SESSION_SECRET:-${CREDS_KEY}} + - API_SERVER_URL=http://api:${PORT:-3080} + - VITE_API_BASE_URL=${DOMAIN_CLIENT:-http://localhost:3080} + - SESSION_COOKIE_SECURE=${ADMIN_PANEL_SESSION_COOKIE_SECURE:-false} mongodb: container_name: chat-mongodb image: mongo:8.0.20