fix: feat: merge chat container into edge — run chat server inside edge container with full permissions (reverts sandbox from #706) (#1083)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
42e9cae6f8
commit
83176c5f28
7 changed files with 48 additions and 142 deletions
|
|
@ -326,7 +326,6 @@ _generate_compose_impl() {
|
|||
_record_service "edge" "base compose template" || return 1
|
||||
_record_service "staging" "base compose template" || return 1
|
||||
_record_service "staging-deploy" "base compose template" || return 1
|
||||
_record_service "chat" "base compose template" || return 1
|
||||
|
||||
# Extract primary woodpecker_repo_id from project TOML files
|
||||
local wp_repo_id
|
||||
|
|
@ -615,6 +614,16 @@ COMPOSEEOF
|
|||
- EDGE_TUNNEL_FQDN_CHAT=${EDGE_TUNNEL_FQDN_CHAT:-}
|
||||
# Shared secret for Caddy ↔ chat forward_auth (#709)
|
||||
- FORWARD_AUTH_SECRET=${FORWARD_AUTH_SECRET:-}
|
||||
# Chat env vars (merged from chat container into edge, #1083)
|
||||
- CHAT_HOST=127.0.0.1
|
||||
- CHAT_PORT=8080
|
||||
- CHAT_OAUTH_CLIENT_ID=${CHAT_OAUTH_CLIENT_ID:-}
|
||||
- CHAT_OAUTH_CLIENT_SECRET=${CHAT_OAUTH_CLIENT_SECRET:-}
|
||||
- DISINTO_CHAT_ALLOWED_USERS=${DISINTO_CHAT_ALLOWED_USERS:-}
|
||||
# Cost caps / rate limiting (#711)
|
||||
- CHAT_MAX_REQUESTS_PER_HOUR=${CHAT_MAX_REQUESTS_PER_HOUR:-60}
|
||||
- CHAT_MAX_REQUESTS_PER_DAY=${CHAT_MAX_REQUESTS_PER_DAY:-500}
|
||||
- CHAT_MAX_TOKENS_PER_DAY=${CHAT_MAX_TOKENS_PER_DAY:-1000000}
|
||||
volumes:
|
||||
- ./docker/Caddyfile:/etc/caddy/Caddyfile
|
||||
- caddy_data:/data
|
||||
|
|
@ -622,6 +631,8 @@ COMPOSEEOF
|
|||
- ./secrets/tunnel_key:/run/secrets/tunnel_key:ro
|
||||
- ${CLAUDE_SHARED_DIR:-/var/lib/disinto/claude-shared}:${CLAUDE_SHARED_DIR:-/var/lib/disinto/claude-shared}
|
||||
- ${CLAUDE_CONFIG_FILE:-${HOME}/.claude.json}:/home/agent/.claude.json:ro
|
||||
# Chat history persistence (merged from chat container, #1083)
|
||||
- ${CHAT_HISTORY_DIR:-./state/chat-history}:/var/lib/chat/history
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-fsS", "http://localhost:2019/config/"]
|
||||
interval: 30s
|
||||
|
|
@ -670,64 +681,12 @@ COMPOSEEOF
|
|||
- disinto-net
|
||||
command: ["echo", "staging slot — replace with project image"]
|
||||
|
||||
# Chat container — Claude chat UI backend (#705)
|
||||
# Internal service only; edge proxy routes to chat:8080
|
||||
# Sandbox hardened per #706 — no docker.sock, read-only rootfs, minimal caps
|
||||
chat:
|
||||
build:
|
||||
context: ./docker/chat
|
||||
dockerfile: Dockerfile
|
||||
container_name: disinto-chat
|
||||
restart: unless-stopped
|
||||
read_only: true
|
||||
tmpfs:
|
||||
- /tmp:size=64m
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
cap_drop:
|
||||
- ALL
|
||||
pids_limit: 128
|
||||
mem_limit: 512m
|
||||
memswap_limit: 512m
|
||||
volumes:
|
||||
# Mount claude binary from host (same as agents)
|
||||
- ${CLAUDE_BIN_DIR}:/usr/local/bin/claude:ro
|
||||
# Throwaway named volume for chat config (isolated from host ~/.claude)
|
||||
- chat-config:/var/chat/config
|
||||
# Chat history persistence: per-user NDJSON files on bind-mounted host volume
|
||||
- ${CHAT_HISTORY_DIR:-./state/chat-history}:/var/lib/chat/history
|
||||
environment:
|
||||
CHAT_HOST: "0.0.0.0"
|
||||
CHAT_PORT: "8080"
|
||||
FORGE_URL: http://forgejo:3000
|
||||
CHAT_OAUTH_CLIENT_ID: ${CHAT_OAUTH_CLIENT_ID:-}
|
||||
CHAT_OAUTH_CLIENT_SECRET: ${CHAT_OAUTH_CLIENT_SECRET:-}
|
||||
EDGE_TUNNEL_FQDN: ${EDGE_TUNNEL_FQDN:-}
|
||||
EDGE_TUNNEL_FQDN_CHAT: ${EDGE_TUNNEL_FQDN_CHAT:-}
|
||||
EDGE_ROUTING_MODE: ${EDGE_ROUTING_MODE:-subpath}
|
||||
DISINTO_CHAT_ALLOWED_USERS: ${DISINTO_CHAT_ALLOWED_USERS:-}
|
||||
# Shared secret for Caddy forward_auth verify endpoint (#709)
|
||||
FORWARD_AUTH_SECRET: ${FORWARD_AUTH_SECRET:-}
|
||||
# Cost caps / rate limiting (#711)
|
||||
CHAT_MAX_REQUESTS_PER_HOUR: ${CHAT_MAX_REQUESTS_PER_HOUR:-60}
|
||||
CHAT_MAX_REQUESTS_PER_DAY: ${CHAT_MAX_REQUESTS_PER_DAY:-500}
|
||||
CHAT_MAX_TOKENS_PER_DAY: ${CHAT_MAX_TOKENS_PER_DAY:-1000000}
|
||||
healthcheck:
|
||||
test: ["CMD", "python3", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8080/health')"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 10s
|
||||
networks:
|
||||
- disinto-net
|
||||
|
||||
volumes:
|
||||
forgejo-data:
|
||||
woodpecker-data:
|
||||
agent-data:
|
||||
project-repos:
|
||||
caddy_data:
|
||||
chat-config:
|
||||
|
||||
networks:
|
||||
disinto-net:
|
||||
|
|
@ -786,7 +745,7 @@ COMPOSEEOF
|
|||
# In build mode, replace image: with build: for locally-built images
|
||||
if [ "$use_build" = true ]; then
|
||||
sed -i '/^ image: ghcr\.io\/disinto\/agents:/{s|image: ghcr\.io/disinto/agents:.*|build:\n context: .\n dockerfile: docker/agents/Dockerfile\n pull_policy: build|}' "$compose_file"
|
||||
sed -i '/^ image: ghcr\.io\/disinto\/edge:/{s|image: ghcr\.io/disinto/edge:.*|build: ./docker/edge\n pull_policy: build|}' "$compose_file"
|
||||
sed -i '/^ image: ghcr\.io\/disinto\/edge:/{s|image: ghcr\.io/disinto/edge:.*|build:\n context: .\n dockerfile: docker/edge/Dockerfile\n pull_policy: build|}' "$compose_file"
|
||||
fi
|
||||
|
||||
echo "Created: ${compose_file}"
|
||||
|
|
@ -864,22 +823,22 @@ _generate_caddyfile_subpath() {
|
|||
reverse_proxy staging:80
|
||||
}
|
||||
|
||||
# Chat service — reverse proxy to disinto-chat backend (#705)
|
||||
# Chat service — reverse proxy to in-process chat server (#705, #1083)
|
||||
# OAuth routes bypass forward_auth — unauthenticated users need these (#709)
|
||||
handle /chat/login {
|
||||
reverse_proxy chat:8080
|
||||
reverse_proxy 127.0.0.1:8080
|
||||
}
|
||||
handle /chat/oauth/callback {
|
||||
reverse_proxy chat:8080
|
||||
reverse_proxy 127.0.0.1:8080
|
||||
}
|
||||
# Defense-in-depth: forward_auth stamps X-Forwarded-User from session (#709)
|
||||
handle /chat/* {
|
||||
forward_auth chat:8080 {
|
||||
forward_auth 127.0.0.1:8080 {
|
||||
uri /chat/auth/verify
|
||||
copy_headers X-Forwarded-User
|
||||
header_up X-Forward-Auth-Secret {$FORWARD_AUTH_SECRET}
|
||||
}
|
||||
reverse_proxy chat:8080
|
||||
reverse_proxy 127.0.0.1:8080
|
||||
}
|
||||
}
|
||||
CADDYFILEEOF
|
||||
|
|
@ -912,18 +871,18 @@ _generate_caddyfile_subdomain() {
|
|||
# Chat — with forward_auth (#709, on its own host)
|
||||
{$EDGE_TUNNEL_FQDN_CHAT} {
|
||||
handle /login {
|
||||
reverse_proxy chat:8080
|
||||
reverse_proxy 127.0.0.1:8080
|
||||
}
|
||||
handle /oauth/callback {
|
||||
reverse_proxy chat:8080
|
||||
reverse_proxy 127.0.0.1:8080
|
||||
}
|
||||
handle /* {
|
||||
forward_auth chat:8080 {
|
||||
forward_auth 127.0.0.1:8080 {
|
||||
uri /auth/verify
|
||||
copy_headers X-Forwarded-User
|
||||
header_up X-Forward-Auth-Secret {$FORWARD_AUTH_SECRET}
|
||||
}
|
||||
reverse_proxy chat:8080
|
||||
reverse_proxy 127.0.0.1:8080
|
||||
}
|
||||
}
|
||||
CADDYFILEEOF
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue