services: provider-proxy-host: image: node:24-alpine container_name: xiteng-provider-proxy-host restart: unless-stopped network_mode: host command: ["node", "/app/proxy-bridge.mjs"] environment: BRIDGE_MODE: host volumes: - ./proxy-bridge.mjs:/app/proxy-bridge.mjs:ro - ./run:/run/provider-proxy security_opt: - no-new-privileges:true healthcheck: test: ["CMD", "node", "-e", "const s=require('net').connect(7897,'127.0.0.1',()=>{s.end();process.exit(0)});s.setTimeout(2000,()=>process.exit(1));s.on('error',()=>process.exit(1))"] interval: 15s timeout: 3s retries: 3 start_period: 5s provider-proxy-bridge: image: node:24-alpine container_name: xiteng-provider-proxy-bridge restart: unless-stopped command: ["node", "/app/proxy-bridge.mjs"] environment: BRIDGE_MODE: network volumes: - ./proxy-bridge.mjs:/app/proxy-bridge.mjs:ro - ./run:/run/provider-proxy security_opt: - no-new-privileges:true healthcheck: test: ["CMD", "node", "-e", "const s=require('net').connect(17897,'127.0.0.1',()=>{s.end();process.exit(0)});s.setTimeout(2000,()=>process.exit(1));s.on('error',()=>process.exit(1))"] interval: 15s timeout: 3s retries: 3 start_period: 5s networks: - homelab_net chat: build: context: . image: xiteng-chat:local container_name: xiteng-chat restart: unless-stopped environment: KEY_VAULT_URL: http://ai-gateway:8093 KEY_VAULT_TOKEN_FILE: /run/secrets/portal_gateway_hmac CHAT_DATABASE_PATH: /data/chat.db PORTAL_URL: http://xiteng-site:8080 volumes: - ../ai-gateway/secrets/portal_gateway_hmac:/run/secrets/portal_gateway_hmac:ro - ./data:/data security_opt: - no-new-privileges:true healthcheck: test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://127.0.0.1:3000/api/health"] interval: 15s timeout: 5s retries: 3 start_period: 10s networks: - homelab_net labels: - "traefik.enable=true" - "traefik.http.services.xiteng-chat.loadbalancer.server.port=3000" - "traefik.http.middlewares.xiteng-chat-scheme.headers.customrequestheaders.X-Forwarded-Proto=https" - "traefik.http.middlewares.xiteng-chat-auth.forwardauth.address=http://authentik-outpost:9000/outpost.goauthentik.io/auth/traefik" - "traefik.http.middlewares.xiteng-chat-auth.forwardauth.trustForwardHeader=true" - "traefik.http.middlewares.xiteng-chat-auth.forwardauth.authResponseHeaders=X-authentik-username,X-authentik-email,X-authentik-name,X-authentik-uid" - "traefik.http.routers.xiteng-chat.rule=Host(`chat.xiteng.site`)" - "traefik.http.routers.xiteng-chat.entrypoints=websecure" - "traefik.http.routers.xiteng-chat.tls=true" - "traefik.http.routers.xiteng-chat.tls.certresolver=cfresolver" - "traefik.http.routers.xiteng-chat.service=xiteng-chat" - "traefik.http.routers.xiteng-chat.middlewares=xiteng-chat-scheme,xiteng-chat-auth" - "traefik.http.routers.xiteng-chat-http.rule=Host(`chat.xiteng.site`)" - "traefik.http.routers.xiteng-chat-http.entrypoints=web" - "traefik.http.routers.xiteng-chat-http.service=xiteng-chat" - "traefik.http.routers.xiteng-chat-http.middlewares=xiteng-chat-scheme,xiteng-chat-auth" - "xiteng.site.component.chat.enabled=true" - "xiteng.site.component.chat.name=Xiteng Chat" - "xiteng.site.component.chat.description=基于 assistant-ui 与个人 Key Vault 的轻量 AI 对话界面。" - "xiteng.site.component.chat.section=services" - "xiteng.site.component.chat.category=AI" - "xiteng.site.component.chat.url=https://chat.xiteng.site" - "xiteng.site.component.chat.access=sso" - "xiteng.site.component.chat.access-label=需要登录" - "xiteng.site.component.chat.icon=AI" - "xiteng.site.component.chat.icon-url=https://xiteng.site/icons/services/chat.svg" - "xiteng.site.component.chat.accent=blue" - "xiteng.site.component.chat.order=190" - "xiteng.site.component.chat.navigation=new-tab" - "xiteng.site.component.chat.portal-link=embedded" - "xiteng.site.component.chat.monitor.enabled=true" - "xiteng.site.component.chat.monitor.url=http://xiteng-chat:3000/api/health" networks: homelab_net: external: true