version: '3.8' services: # ─── Entry point ─────────────────────────────────────────────────────────── haproxy: image: haproxy:2.9-alpine container_name: vpndock-haproxy restart: unless-stopped ports: - "${SOCKS5_PORT:-1080}:1080" # SOCKS5 proxy for browsers/clients - "8404:8404" # HAProxy stats UI volumes: - ./haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro networks: - proxy-net depends_on: - vpn-node # ─── VPN exit nodes ──────────────────────────────────────────────────────── # Scale with: docker compose up -d --scale vpn-node=N (max 10) vpn-node: build: context: ./vpn-node dockerfile: Dockerfile restart: unless-stopped cap_add: - NET_ADMIN devices: - /dev/net/tun:/dev/net/tun environment: - PUREVPN_USER=${PUREVPN_USER} - PUREVPN_PASS=${PUREVPN_PASS} # Comma-separated list of locations each container picks from randomly. # Leave blank to use vpn-node/servers.txt instead. # Example: "United States,United Kingdom,Germany,Netherlands,France" - PUREVPN_LOCATIONS=${PUREVPN_LOCATIONS:-} - SOCKS5_INNER_PORT=1080 # MANUAL_CONNECT=true → container waits; you run purevpn-cli manually via docker exec # MANUAL_CONNECT=false → auto login + connect (default) - MANUAL_CONNECT=${MANUAL_CONNECT:-false} env_file: - .env networks: - proxy-net expose: - "1080" sysctls: - net.ipv4.conf.all.rp_filter=2 - net.ipv6.conf.all.disable_ipv6=1 healthcheck: test: ["CMD-SHELL", "nc -z 127.0.0.1 1080 || exit 1"] interval: 20s timeout: 5s retries: 5 start_period: 45s networks: proxy-net: driver: bridge ipam: config: - subnet: 172.28.0.0/24