--- services: headscale-client: image: tailscale/tailscale:latest environment: - DEPLOYMENT_TIME={{ deployment_time }} - TS_AUTHKEY={{ headscale_user_auth_key }} - TS_EXTRA_ARGS=--login-server=https://{{ headscale_host }} --accept-routes --accept-dns --stateful-filtering=false - TS_STATE_DIR=/var/lib/tailscale - TS_USERSPACE=false - TZ={{ timezone }} restart: unless-stopped healthcheck: test: ["CMD-SHELL", "tailscale status"] interval: 1s timeout: 5s retries: 10 hostname: headscale-outbound cap_add: - NET_ADMIN - SYS_ADMIN volumes: - ./data:/var/lib/tailscale - ./headscale/headscale-client.sh:/headscale-client.sh - /dev/net/tun:/dev/net/tun networks: - internal_subnet_router # magic. sysctls: - net.ipv4.ip_forward=1 entrypoint: ["/bin/sh"] command: /headscale-client.sh {{ vpn_proxy_filter_container_name }}: image: nginx:latest entrypoint: ["/bin/sh"] command: /wait-for-bridge.sh pre_stop: - command: /dont-die-until-conn-closed.sh cap_add: - NET_ADMIN # to modify the routing table environment: - DEPLOYMENT_TIME={{ deployment_time }} - VIRTUAL_HOST=*.{{ domain }},{{ domain }} - VIRTUAL_PORT=80 - LETSENCRYPT_HOST=*.{{ domain }},{{ domain }} healthcheck: test: ["CMD", "curl", "http://localhost/health"] interval: 10s timeout: 5s retries: 3 depends_on: - headscale-client volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf - ./nginx/conf.d:/etc/nginx/conf.d - ./nginx/toplevel.conf.d:/etc/nginx/toplevel.conf.d - ./nginx/wait-for-bridge.sh:/wait-for-bridge.sh - ./nginx/dont-die-until-conn-closed.sh:/dont-die-until-conn-closed.sh networks: - proxy - internal_subnet_router networks: internal_subnet_router: driver: bridge proxy: external: true