revert: tailscale docker sidecar
This commit is contained in:
167
ai/compose.yaml
167
ai/compose.yaml
@@ -96,7 +96,6 @@ services:
|
|||||||
image: ghcr.io/berriai/litellm:main-latest
|
image: ghcr.io/berriai/litellm:main-latest
|
||||||
container_name: ${AI_COMPOSE_PROJECT_NAME}_litellm
|
container_name: ${AI_COMPOSE_PROJECT_NAME}_litellm
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
network_mode: "service:tailscale"
|
|
||||||
environment:
|
environment:
|
||||||
TZ: ${TIMEZONE:-Europe/Berlin}
|
TZ: ${TIMEZONE:-Europe/Berlin}
|
||||||
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY}
|
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY}
|
||||||
@@ -122,9 +121,21 @@ services:
|
|||||||
]
|
]
|
||||||
depends_on:
|
depends_on:
|
||||||
- ai_postgres
|
- ai_postgres
|
||||||
- tailscale
|
|
||||||
healthcheck:
|
healthcheck:
|
||||||
disable: true
|
disable: true
|
||||||
|
networks:
|
||||||
|
- compose_network
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "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.services.${AI_COMPOSE_PROJECT_NAME}-litellm.loadbalancer.server.port=4000"
|
||||||
|
- "traefik.docker.network=${NETWORK_NAME}"
|
||||||
|
- "com.centurylinklabs.watchtower.enable=${WATCHTOWER_LABEL_ENABLE}"
|
||||||
|
|
||||||
# Facefusion - AI face swapping and enhancement
|
# Facefusion - AI face swapping and enhancement
|
||||||
facefusion:
|
facefusion:
|
||||||
@@ -168,130 +179,99 @@ services:
|
|||||||
image: nginx:alpine
|
image: nginx:alpine
|
||||||
container_name: ${AI_COMPOSE_PROJECT_NAME}_comfyui
|
container_name: ${AI_COMPOSE_PROJECT_NAME}_comfyui
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
network_mode: "service:tailscale"
|
|
||||||
environment:
|
environment:
|
||||||
TZ: ${TIMEZONE:-Europe/Berlin}
|
TZ: ${TIMEZONE:-Europe/Berlin}
|
||||||
GPU_SERVICE_HOST: ${GPU_TAILSCALE_HOST}
|
GPU_SERVICE_HOST: ${GPU_TAILSCALE_HOST:-runpod-ai-orchestrator}
|
||||||
GPU_SERVICE_PORT: ${COMFYUI_BACKEND_PORT:-8188}
|
GPU_SERVICE_PORT: ${COMFYUI_BACKEND_PORT:-8188}
|
||||||
volumes:
|
volumes:
|
||||||
- ./nginx.conf.template:/etc/nginx/nginx.conf.template:ro
|
- ./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;'"
|
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;'"
|
||||||
depends_on:
|
|
||||||
- tailscale
|
|
||||||
|
|
||||||
audiocraft:
|
|
||||||
image: nginx:alpine
|
|
||||||
container_name: ${AI_COMPOSE_PROJECT_NAME}_audiocraft
|
|
||||||
restart: unless-stopped
|
|
||||||
network_mode: "service:tailscale"
|
|
||||||
environment:
|
|
||||||
TZ: ${TIMEZONE:-Europe/Berlin}
|
|
||||||
GPU_SERVICE_HOST: ${GPU_TAILSCALE_HOST}
|
|
||||||
GPU_SERVICE_PORT: ${AUDIOCRAFT_BACKEND_PORT:-7860}
|
|
||||||
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;'"
|
|
||||||
depends_on:
|
|
||||||
- tailscale
|
|
||||||
|
|
||||||
upscale:
|
|
||||||
image: nginx:alpine
|
|
||||||
container_name: ${AI_COMPOSE_PROJECT_NAME}_upscale
|
|
||||||
restart: unless-stopped
|
|
||||||
network_mode: "service:tailscale"
|
|
||||||
environment:
|
|
||||||
TZ: ${TIMEZONE:-Europe/Berlin}
|
|
||||||
GPU_SERVICE_HOST: ${GPU_TAILSCALE_HOST}
|
|
||||||
GPU_SERVICE_PORT: ${UPSCALE_BACKEND_PORT:-8080}
|
|
||||||
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;'"
|
|
||||||
depends_on:
|
|
||||||
- tailscale
|
|
||||||
|
|
||||||
# Supervisor UI - Modern web interface for RunPod process management
|
|
||||||
supervisor:
|
|
||||||
image: dev.pivoine.art/valknar/supervisor-ui:latest
|
|
||||||
container_name: ${AI_COMPOSE_PROJECT_NAME}_supervisor_ui
|
|
||||||
restart: unless-stopped
|
|
||||||
network_mode: "service:tailscale"
|
|
||||||
environment:
|
|
||||||
TZ: ${TIMEZONE:-Europe/Berlin}
|
|
||||||
NODE_ENV: production
|
|
||||||
# Connect to RunPod Supervisor via Tailscale
|
|
||||||
SUPERVISOR_HOST: ${GPU_TAILSCALE_HOST}
|
|
||||||
SUPERVISOR_PORT: ${SUPERVISOR_BACKEND_PORT:-9001}
|
|
||||||
# No auth needed - Supervisor has auth disabled (protected by Authelia)
|
|
||||||
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
|
|
||||||
- TS_USERSPACE=true
|
|
||||||
- TS_ACCEPT_DNS=true
|
|
||||||
restart: unless-stopped
|
|
||||||
networks:
|
networks:
|
||||||
- compose_network
|
- compose_network
|
||||||
labels:
|
labels:
|
||||||
- "traefik.enable=true"
|
- "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.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.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.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.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.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.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"
|
- "traefik.http.services.${AI_COMPOSE_PROJECT_NAME}-comfyui.loadbalancer.server.port=80"
|
||||||
# === AudioCraft (port 7860 via nginx on 80) ===
|
- "traefik.docker.network=${NETWORK_NAME}"
|
||||||
|
|
||||||
|
audiocraft:
|
||||||
|
image: nginx:alpine
|
||||||
|
container_name: ${AI_COMPOSE_PROJECT_NAME}_audiocraft
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
TZ: ${TIMEZONE:-Europe/Berlin}
|
||||||
|
GPU_SERVICE_HOST: ${GPU_TAILSCALE_HOST:-runpod-ai-orchestrator}
|
||||||
|
GPU_SERVICE_PORT: ${AUDIOCRAFT_BACKEND_PORT:-7860}
|
||||||
|
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=true"
|
||||||
- "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.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.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.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.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.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.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=80"
|
||||||
- "traefik.http.services.${AI_COMPOSE_PROJECT_NAME}-audiocraft.loadbalancer.server.port=7860"
|
- "traefik.docker.network=${NETWORK_NAME}"
|
||||||
# === Upscale (port 8080 via nginx on 80) ===
|
|
||||||
|
upscale:
|
||||||
|
image: nginx:alpine
|
||||||
|
container_name: ${AI_COMPOSE_PROJECT_NAME}_upscale
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
TZ: ${TIMEZONE:-Europe/Berlin}
|
||||||
|
GPU_SERVICE_HOST: ${GPU_TAILSCALE_HOST:-runpod-ai-orchestrator}
|
||||||
|
GPU_SERVICE_PORT: ${UPSCALE_BACKEND_PORT:-8080}
|
||||||
|
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=true"
|
||||||
- "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.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.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.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.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.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.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=80"
|
||||||
- "traefik.http.services.${AI_COMPOSE_PROJECT_NAME}-upscale.loadbalancer.server.port=8080"
|
- "traefik.docker.network=${NETWORK_NAME}"
|
||||||
# === Supervisor UI (port 3000) ===
|
|
||||||
|
# Supervisor UI - Modern web interface for RunPod process management
|
||||||
|
supervisor:
|
||||||
|
image: dev.pivoine.art/valknar/supervisor-ui:latest
|
||||||
|
container_name: ${AI_COMPOSE_PROJECT_NAME}_supervisor_ui
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
TZ: ${TIMEZONE:-Europe/Berlin}
|
||||||
|
NODE_ENV: production
|
||||||
|
# Connect to RunPod Supervisor via Tailscale (host Tailscale provides DNS)
|
||||||
|
SUPERVISOR_HOST: ${GPU_TAILSCALE_HOST:-runpod-ai-orchestrator}
|
||||||
|
SUPERVISOR_PORT: ${SUPERVISOR_BACKEND_PORT:-9001}
|
||||||
|
# No auth needed - Supervisor has auth disabled (protected by Authelia)
|
||||||
|
networks:
|
||||||
|
- compose_network
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
- "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.rule=Host(`${AI_SUPERVISOR_TRAEFIK_HOST:-supervisor.ai.pivoine.art}`)"
|
||||||
- "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-supervisor-web.entrypoints=web"
|
- "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-supervisor-web.entrypoints=web"
|
||||||
- "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.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.tls.certresolver=resolver"
|
||||||
- "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-supervisor-web-secure.entrypoints=web-secure"
|
- "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-supervisor-web-secure.entrypoints=web-secure"
|
||||||
- "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.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"
|
- "traefik.http.services.${AI_COMPOSE_PROJECT_NAME}-supervisor.loadbalancer.server.port=3000"
|
||||||
# === LiteLLM (port 4000) ===
|
- "traefik.docker.network=${NETWORK_NAME}"
|
||||||
- "traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-litellm-web.rule=Host(`${AI_LITELLM_TRAEFIK_HOST}`)"
|
- "com.centurylinklabs.watchtower.enable=${WATCHTOWER_LABEL_ENABLE}"
|
||||||
- "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:
|
volumes:
|
||||||
ai_postgres_data:
|
ai_postgres_data:
|
||||||
@@ -300,5 +280,8 @@ volumes:
|
|||||||
name: ${AI_COMPOSE_PROJECT_NAME}_webui_data
|
name: ${AI_COMPOSE_PROJECT_NAME}_webui_data
|
||||||
ai_facefusion_data:
|
ai_facefusion_data:
|
||||||
name: ${AI_COMPOSE_PROJECT_NAME}_facefusion_data
|
name: ${AI_COMPOSE_PROJECT_NAME}_facefusion_data
|
||||||
tailscale_state:
|
|
||||||
name: ${AI_COMPOSE_PROJECT_NAME}_tailscale_state
|
networks:
|
||||||
|
compose_network:
|
||||||
|
name: ${NETWORK_NAME}
|
||||||
|
external: true
|
||||||
|
|||||||
54
arty.yml
54
arty.yml
@@ -262,3 +262,57 @@ scripts:
|
|||||||
docker restart sexy_api &&
|
docker restart sexy_api &&
|
||||||
echo "✓ Directus API restarted"
|
echo "✓ Directus API restarted"
|
||||||
net/create: docker network create "$NETWORK_NAME"
|
net/create: docker network create "$NETWORK_NAME"
|
||||||
|
# Setup iptables NAT for Docker containers to reach Tailscale network
|
||||||
|
# Requires Tailscale installed on host: curl -fsSL https://tailscale.com/install.sh | sh
|
||||||
|
tailscale/setup: |
|
||||||
|
echo "Setting up iptables for Docker-to-Tailscale routing..."
|
||||||
|
|
||||||
|
# Enable IP forwarding
|
||||||
|
sudo sysctl -w net.ipv4.ip_forward=1
|
||||||
|
grep -q "net.ipv4.ip_forward=1" /etc/sysctl.conf || echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
|
||||||
|
|
||||||
|
# Get Docker network CIDR
|
||||||
|
DOCKER_CIDR=$(docker network inspect ${NETWORK_NAME} --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}' 2>/dev/null || echo "172.18.0.0/16")
|
||||||
|
echo "Docker network CIDR: $DOCKER_CIDR"
|
||||||
|
|
||||||
|
# Add NAT rule (check if already exists)
|
||||||
|
if ! sudo iptables -t nat -C POSTROUTING -s "$DOCKER_CIDR" -o tailscale0 -j MASQUERADE 2>/dev/null; then
|
||||||
|
sudo iptables -t nat -A POSTROUTING -s "$DOCKER_CIDR" -o tailscale0 -j MASQUERADE
|
||||||
|
echo "✓ iptables NAT rule added"
|
||||||
|
else
|
||||||
|
echo "✓ iptables NAT rule already exists"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Persist rules
|
||||||
|
sudo netfilter-persistent save 2>/dev/null || echo "Install iptables-persistent to persist rules: sudo apt install iptables-persistent"
|
||||||
|
|
||||||
|
echo "✓ Tailscale routing configured"
|
||||||
|
|
||||||
|
# Install and configure Tailscale on host with persistent state
|
||||||
|
tailscale/install: |
|
||||||
|
echo "Installing Tailscale..."
|
||||||
|
|
||||||
|
# Install Tailscale if not present
|
||||||
|
if ! command -v tailscale &> /dev/null; then
|
||||||
|
curl -fsSL https://tailscale.com/install.sh | sh
|
||||||
|
else
|
||||||
|
echo "✓ Tailscale already installed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create state directory for persistence
|
||||||
|
TAILSCALE_STATE="/var/lib/tailscale"
|
||||||
|
sudo mkdir -p "$TAILSCALE_STATE"
|
||||||
|
|
||||||
|
# Start and enable tailscaled service
|
||||||
|
sudo systemctl enable --now tailscaled
|
||||||
|
|
||||||
|
# Connect to Tailscale network
|
||||||
|
echo "Connecting to Tailscale..."
|
||||||
|
sudo tailscale up --authkey="$TAILSCALE_AUTHKEY" --hostname=vps
|
||||||
|
|
||||||
|
# Show status
|
||||||
|
echo ""
|
||||||
|
tailscale status
|
||||||
|
echo ""
|
||||||
|
echo "✓ Tailscale installed and connected"
|
||||||
|
echo " Run 'arty tailscale/setup' to configure iptables routing for Docker"
|
||||||
|
|||||||
Reference in New Issue
Block a user