From c83b77ebdb5d0ecb71ef0192e0f738d158025708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Kr=C3=BCger?= Date: Fri, 28 Nov 2025 08:59:42 +0100 Subject: [PATCH] feat: tailscale sidecar --- ai/compose.yaml | 165 ++++++++++++++++++++--------------------------- net/compose.yaml | 18 ------ 2 files changed, 71 insertions(+), 112 deletions(-) diff --git a/ai/compose.yaml b/ai/compose.yaml index df0e2c7..8065095 100644 --- a/ai/compose.yaml +++ b/ai/compose.yaml @@ -122,28 +122,9 @@ services: ] depends_on: - ai_postgres - # networks: - # - compose_network + - tailscale healthcheck: disable: true - labels: - - "traefik.enable=${AI_TRAEFIK_ENABLED}" - # HTTP to HTTPS redirect - - "traefik.http.middlewares.${AI_COMPOSE_PROJECT_NAME}-litellm-redirect-web-secure.redirectscheme.scheme=https" - - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-litellm-web.middlewares=${AI_COMPOSE_PROJECT_NAME}-litellm-redirect-web-secure" - - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-litellm-web.rule=Host(`${AI_LITELLM_TRAEFIK_HOST}`)" - - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-litellm-web.entrypoints=web" - # HTTPS router - - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-litellm-web-secure.rule=Host(`${AI_LITELLM_TRAEFIK_HOST}`)" - - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-litellm-web-secure.tls.certresolver=resolver" - - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-litellm-web-secure.entrypoints=web-secure" - - "traefik.http.middlewares.${AI_COMPOSE_PROJECT_NAME}-litellm-web-secure-compress.compress=true" - - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-litellm-web-secure.middlewares=${AI_COMPOSE_PROJECT_NAME}-litellm-web-secure-compress,security-headers@file" - # Service - - "traefik.http.services.${AI_COMPOSE_PROJECT_NAME}-litellm-web-secure.loadbalancer.server.port=4000" - - "traefik.docker.network=${NETWORK_NAME}" - # Watchtower - - "com.centurylinklabs.watchtower.enable=${WATCHTOWER_LABEL_ENABLE}" # Facefusion - AI face swapping and enhancement facefusion: @@ -195,26 +176,8 @@ services: volumes: - ./nginx.conf.template:/etc/nginx/nginx.conf.template:ro command: /bin/sh -c "envsubst '$${GPU_SERVICE_HOST},$${GPU_SERVICE_PORT}' < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf && exec nginx -g 'daemon off;'" - # networks: - # - compose_network - labels: - - "traefik.enable=${AI_COMFYUI_TRAEFIK_ENABLED:-true}" - # HTTP to HTTPS redirect - - "traefik.http.middlewares.${AI_COMPOSE_PROJECT_NAME}-comfyui-redirect-web-secure.redirectscheme.scheme=https" - - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-comfyui-web.middlewares=${AI_COMPOSE_PROJECT_NAME}-comfyui-redirect-web-secure" - - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-comfyui-web.rule=Host(`${AI_COMFYUI_TRAEFIK_HOST:-comfy.ai.pivoine.art}`)" - - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-comfyui-web.entrypoints=web" - # HTTPS router with Authelia SSO - - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-comfyui-web-secure.rule=Host(`${AI_COMFYUI_TRAEFIK_HOST:-comfy.ai.pivoine.art}`)" - - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-comfyui-web-secure.tls.certresolver=resolver" - - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-comfyui-web-secure.entrypoints=web-secure" - - "traefik.http.middlewares.${AI_COMPOSE_PROJECT_NAME}-comfyui-web-secure-compress.compress=true" - - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-comfyui-web-secure.middlewares=${AI_COMPOSE_PROJECT_NAME}-comfyui-web-secure-compress,net-authelia,security-headers@file" - # Service - - "traefik.http.services.${AI_COMPOSE_PROJECT_NAME}-comfyui-web-secure.loadbalancer.server.port=80" - - "traefik.docker.network=${NETWORK_NAME}" - # Watchtower - - "com.centurylinklabs.watchtower.enable=${WATCHTOWER_LABEL_ENABLE}" + depends_on: + - tailscale audiocraft: image: nginx:alpine @@ -228,26 +191,8 @@ services: volumes: - ./nginx.conf.template:/etc/nginx/nginx.conf.template:ro command: /bin/sh -c "envsubst '$${GPU_SERVICE_HOST},$${GPU_SERVICE_PORT}' < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf && exec nginx -g 'daemon off;'" - # networks: - # - compose_network - labels: - - "traefik.enable=${AI_AUDIOCRAFT_TRAEFIK_ENABLED:-true}" - # HTTP to HTTPS redirect - - "traefik.http.middlewares.${AI_COMPOSE_PROJECT_NAME}-audiocraft-redirect-web-secure.redirectscheme.scheme=https" - - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-audiocraft-web.middlewares=${AI_COMPOSE_PROJECT_NAME}-audiocraft-redirect-web-secure" - - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-audiocraft-web.rule=Host(`${AI_AUDIOCRAFT_TRAEFIK_HOST:-audiocraft.ai.pivoine.art}`)" - - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-audiocraft-web.entrypoints=web" - # HTTPS router with Authelia SSO - - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-audiocraft-web-secure.rule=Host(`${AI_AUDIOCRAFT_TRAEFIK_HOST:-audiocraft.ai.pivoine.art}`)" - - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-audiocraft-web-secure.tls.certresolver=resolver" - - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-audiocraft-web-secure.entrypoints=web-secure" - - "traefik.http.middlewares.${AI_COMPOSE_PROJECT_NAME}-audiocraft-web-secure-compress.compress=true" - - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-audiocraft-web-secure.middlewares=${AI_COMPOSE_PROJECT_NAME}-audiocraft-web-secure-compress,net-authelia,security-headers@file" - # Service - - "traefik.http.services.${AI_COMPOSE_PROJECT_NAME}-audiocraft-web-secure.loadbalancer.server.port=80" - - "traefik.docker.network=${NETWORK_NAME}" - # Watchtower - - "com.centurylinklabs.watchtower.enable=${WATCHTOWER_LABEL_ENABLE}" + depends_on: + - tailscale upscale: image: nginx:alpine @@ -261,26 +206,8 @@ services: volumes: - ./nginx.conf.template:/etc/nginx/nginx.conf.template:ro command: /bin/sh -c "envsubst '$${GPU_SERVICE_HOST},$${GPU_SERVICE_PORT}' < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf && exec nginx -g 'daemon off;'" - # networks: - # - compose_network - labels: - - "traefik.enable=${AI_UPSCALE_TRAEFIK_ENABLED:-true}" - # HTTP to HTTPS redirect - - "traefik.http.middlewares.${AI_COMPOSE_PROJECT_NAME}-upscale-redirect-web-secure.redirectscheme.scheme=https" - - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-upscale-web.middlewares=${AI_COMPOSE_PROJECT_NAME}-upscale-redirect-web-secure" - - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-upscale-web.rule=Host(`${AI_UPSCALE_TRAEFIK_HOST:-upscale.ai.pivoine.art}`)" - - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-upscale-web.entrypoints=web" - # HTTPS router with Authelia SSO - - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-upscale-web-secure.rule=Host(`${AI_UPSCALE_TRAEFIK_HOST:-upscale.ai.pivoine.art}`)" - - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-upscale-web-secure.tls.certresolver=resolver" - - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-upscale-web-secure.entrypoints=web-secure" - - "traefik.http.middlewares.${AI_COMPOSE_PROJECT_NAME}-upscale-web-secure-compress.compress=true" - - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-upscale-web-secure.middlewares=${AI_COMPOSE_PROJECT_NAME}-upscale-web-secure-compress,net-authelia,security-headers@file" - # Service - - "traefik.http.services.${AI_COMPOSE_PROJECT_NAME}-upscale-web-secure.loadbalancer.server.port=80" - - "traefik.docker.network=${NETWORK_NAME}" - # Watchtower - - "com.centurylinklabs.watchtower.enable=${WATCHTOWER_LABEL_ENABLE}" + depends_on: + - tailscale # Supervisor UI - Modern web interface for RunPod process management supervisor: @@ -295,26 +222,74 @@ services: SUPERVISOR_HOST: ${GPU_TAILSCALE_HOST} SUPERVISOR_PORT: ${SUPERVISOR_BACKEND_PORT:-9001} # No auth needed - Supervisor has auth disabled (protected by Authelia) - # networks: - # - compose_network + depends_on: + - tailscale + + # Tailscale VPN - Provides network access to RunPod GPU services + tailscale: + image: tailscale/tailscale:latest + hostname: vps + container_name: ${AI_COMPOSE_PROJECT_NAME}_tailscale + cap_add: + - NET_ADMIN + - SYS_MODULE + volumes: + - tailscale_state:/var/lib/tailscale + - /dev/net/tun:/dev/net/tun + environment: + - TS_AUTHKEY=${TAILSCALE_AUTHKEY} + - TS_STATE_DIR=/var/lib/tailscale + restart: unless-stopped + networks: + - compose_network labels: - - "traefik.enable=${AI_SUPERVISOR_TRAEFIK_ENABLED:-true}" - # HTTP to HTTPS redirect - - "traefik.http.middlewares.${AI_COMPOSE_PROJECT_NAME}-supervisor-redirect-web-secure.redirectscheme.scheme=https" - - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-supervisor-web.middlewares=${AI_COMPOSE_PROJECT_NAME}-supervisor-redirect-web-secure" + - "traefik.enable=true" + - "traefik.docker.network=${NETWORK_NAME}" + # === ComfyUI (port 80 - nginx proxy) === + - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-comfyui-web.rule=Host(`${AI_COMFYUI_TRAEFIK_HOST:-comfy.ai.pivoine.art}`)" + - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-comfyui-web.entrypoints=web" + - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-comfyui-web-secure.rule=Host(`${AI_COMFYUI_TRAEFIK_HOST:-comfy.ai.pivoine.art}`)" + - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-comfyui-web-secure.tls.certresolver=resolver" + - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-comfyui-web-secure.entrypoints=web-secure" + - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-comfyui-web-secure.middlewares=net-authelia,security-headers@file" + - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-comfyui-web-secure.service=${AI_COMPOSE_PROJECT_NAME}-comfyui" + - "traefik.http.services.${AI_COMPOSE_PROJECT_NAME}-comfyui.loadbalancer.server.port=80" + # === AudioCraft (port 7860 via nginx on 80) === + - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-audiocraft-web.rule=Host(`${AI_AUDIOCRAFT_TRAEFIK_HOST:-audiocraft.ai.pivoine.art}`)" + - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-audiocraft-web.entrypoints=web" + - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-audiocraft-web-secure.rule=Host(`${AI_AUDIOCRAFT_TRAEFIK_HOST:-audiocraft.ai.pivoine.art}`)" + - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-audiocraft-web-secure.tls.certresolver=resolver" + - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-audiocraft-web-secure.entrypoints=web-secure" + - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-audiocraft-web-secure.middlewares=net-authelia,security-headers@file" + - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-audiocraft-web-secure.service=${AI_COMPOSE_PROJECT_NAME}-audiocraft" + - "traefik.http.services.${AI_COMPOSE_PROJECT_NAME}-audiocraft.loadbalancer.server.port=7860" + # === Upscale (port 8080 via nginx on 80) === + - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-upscale-web.rule=Host(`${AI_UPSCALE_TRAEFIK_HOST:-upscale.ai.pivoine.art}`)" + - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-upscale-web.entrypoints=web" + - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-upscale-web-secure.rule=Host(`${AI_UPSCALE_TRAEFIK_HOST:-upscale.ai.pivoine.art}`)" + - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-upscale-web-secure.tls.certresolver=resolver" + - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-upscale-web-secure.entrypoints=web-secure" + - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-upscale-web-secure.middlewares=net-authelia,security-headers@file" + - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-upscale-web-secure.service=${AI_COMPOSE_PROJECT_NAME}-upscale" + - "traefik.http.services.${AI_COMPOSE_PROJECT_NAME}-upscale.loadbalancer.server.port=8080" + # === Supervisor UI (port 3000) === - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-supervisor-web.rule=Host(`${AI_SUPERVISOR_TRAEFIK_HOST:-supervisor.ai.pivoine.art}`)" - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-supervisor-web.entrypoints=web" - # HTTPS router with Authelia SSO - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-supervisor-web-secure.rule=Host(`${AI_SUPERVISOR_TRAEFIK_HOST:-supervisor.ai.pivoine.art}`)" - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-supervisor-web-secure.tls.certresolver=resolver" - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-supervisor-web-secure.entrypoints=web-secure" - - "traefik.http.middlewares.${AI_COMPOSE_PROJECT_NAME}-supervisor-web-secure-compress.compress=true" - - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-supervisor-web-secure.middlewares=${AI_COMPOSE_PROJECT_NAME}-supervisor-web-secure-compress,net-authelia,security-headers@file" - # Service (port 3000 for Next.js app) - - "traefik.http.services.${AI_COMPOSE_PROJECT_NAME}-supervisor-web-secure.loadbalancer.server.port=3000" - - "traefik.docker.network=${NETWORK_NAME}" - # Watchtower - - "com.centurylinklabs.watchtower.enable=${WATCHTOWER_LABEL_ENABLE}" + - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-supervisor-web-secure.middlewares=net-authelia,security-headers@file" + - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-supervisor-web-secure.service=${AI_COMPOSE_PROJECT_NAME}-supervisor" + - "traefik.http.services.${AI_COMPOSE_PROJECT_NAME}-supervisor.loadbalancer.server.port=3000" + # === LiteLLM (port 4000) === + - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-litellm-web.rule=Host(`${AI_LITELLM_TRAEFIK_HOST}`)" + - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-litellm-web.entrypoints=web" + - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-litellm-web-secure.rule=Host(`${AI_LITELLM_TRAEFIK_HOST}`)" + - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-litellm-web-secure.tls.certresolver=resolver" + - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-litellm-web-secure.entrypoints=web-secure" + - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-litellm-web-secure.middlewares=security-headers@file" + - "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-litellm-web-secure.service=${AI_COMPOSE_PROJECT_NAME}-litellm" + - "traefik.http.services.${AI_COMPOSE_PROJECT_NAME}-litellm.loadbalancer.server.port=4000" volumes: ai_postgres_data: @@ -323,3 +298,5 @@ volumes: name: ${AI_COMPOSE_PROJECT_NAME}_webui_data ai_facefusion_data: name: ${AI_COMPOSE_PROJECT_NAME}_facefusion_data + tailscale_state: + name: ${AI_COMPOSE_PROJECT_NAME}_tailscale_state diff --git a/net/compose.yaml b/net/compose.yaml index 390bb1e..ef328fe 100644 --- a/net/compose.yaml +++ b/net/compose.yaml @@ -308,22 +308,6 @@ services: # Watchtower - "com.centurylinklabs.watchtower.enable=${WATCHTOWER_LABEL_ENABLE}" - tailscale: - image: tailscale/tailscale:latest - hostname: vps - cap_add: - - NET_ADMIN - - SYS_MODULE - volumes: - - tailscale_state:/var/lib/tailscale - - /dev/net/tun:/dev/net/tun - environment: - - TS_AUTHKEY=${TAILSCALE_AUTHKEY} - - TS_STATE_DIR=/var/lib/tailscale - restart: unless-stopped - networks: - - compose_network - volumes: letsencrypt_data: name: ${NET_COMPOSE_PROJECT_NAME}_letsencrypt_data @@ -337,8 +321,6 @@ volumes: name: ${NET_COMPOSE_PROJECT_NAME}_mailpit_data authelia_config: name: ${NET_COMPOSE_PROJECT_NAME}_authelia_config - tailscale_state: - name: ${NET_COMPOSE_PROJECT_NAME}_tailscale_state networks: compose_network: