# RackNerd VPN hub — OpenVPN (road warriors) + Duo Auth Proxy + Technitium DNS. # # All services use network_mode: host on purpose: # * openvpn's tun0 must live in the host netns so the kernel can route # tun0 <-> wg0 directly (wg0 is host-level wg-quick). # * duo binds only 127.0.0.1; technitium binds wildcard, but the host # firewall default-drops the public interface and the recursion ACL # only allows tunnel/site networks — nothing is usable from outside. # Nothing here publishes ports; the host firewall (host/rules.v4.template) # is the single source of truth for what is reachable from where. # # The ${*_DIR:-./...} variables default to the repo layout for manual use; # the Ansible deploy sets them in .env to the /opt/ layout. # # NOTE: technitium's DNS_SERVER_* env vars only seed config on FIRST start # (empty config dir). After that, change settings in the web console — # or wipe ${TECHNITIUM_DIR}/config to re-seed. name: racknerd-vpnhub services: technitium: # Pin a version (e.g. :13.6.0) for controlled upgrades image: technitium/dns-server:latest container_name: technitium network_mode: host environment: - DNS_SERVER_DOMAIN=vpnhub - DNS_SERVER_ADMIN_PASSWORD=${TECHNITIUM_ADMIN_PASSWORD} - DNS_SERVER_WEB_SERVICE_HTTP_PORT=5380 - DNS_SERVER_RECURSION=UseSpecifiedNetworkACL # NOTE: seeded on first start only — on an existing deploy, add new # networks in the console instead (Settings -> Recursion). - DNS_SERVER_RECURSION_NETWORK_ACL=127.0.0.0/8,172.31.8.0/24,172.31.9.0/24,172.31.255.0/24,192.168.20.0/24,192.168.7.0/24 volumes: - ${TECHNITIUM_DIR:-./technitium}/config:/etc/dns restart: unless-stopped technitium-init: build: ${TECHNITIUM_DIR:-./technitium} container_name: technitium-init network_mode: host env_file: .env depends_on: - technitium restart: "no" duo-authproxy: build: context: ${DUO_DIR:-./duo-authproxy} args: # Pin a version (e.g. "6.5.1") to get deterministic updates — # bumping it busts the Docker layer cache and refetches the tarball. DUO_VERSION: ${DUO_AUTHPROXY_VERSION:-latest} container_name: duo-authproxy network_mode: host # RADIUS listener bound to 127.0.0.1:1812 only env_file: .env volumes: # AD LDAPS issuing-CA chain, exported from your CA (see certs/README.md) - ${DUO_DIR:-./duo-authproxy}/certs:/certs:ro restart: unless-stopped openvpn: build: ${OPENVPN_DIR:-./openvpn} container_name: openvpn network_mode: host # creates tun0 in the host netns cap_add: - NET_ADMIN devices: - /dev/net/tun env_file: .env volumes: - ${OPENVPN_DIR:-./openvpn}/server.conf:/etc/openvpn/server.conf:ro - ${OPENVPN_DIR:-./openvpn}/learn-address.sh:/etc/openvpn/learn-address.sh:ro - ${OPENVPN_DIR:-./openvpn}/pki:/etc/openvpn/pki:ro - openvpn-state:/var/lib/openvpn depends_on: - duo-authproxy - technitium restart: unless-stopped volumes: openvpn-state: