Skip to content

🌐 Networking

Network Architecture

Network Plane Type Subnet Role
Zone 1: Trusted Docker Bridge 172.20.0.x Internal communication. Services here talk to Caddy and each other.
Zone 2: Secured VPN Tunnel N/A P2P Isolation. Containers here have NO IP; they piggyback on Gluetun.
Zone 3: Mgmt Tailscale 100.x.x.x Remote Management. Bypasses Caddy/Firewalls for "Emergency Access."

Zone 1: The App Network (dockerapps-net)

This is the backbone bridge network. Unlike standard Docker bridges, we explicitly define the subnet to allow for Static IP Allocation.

  • IPv4 Subnet: 172.20.0.0/24
  • Gateway: 172.20.0.1
  • IPv6: Enabled (Mapped to fd00:dead:beef:2::/64)
  • DNS: Containers inherit the Host's DNS settings (Cloudflare/Google) via daemon.json.
Expand to View: Create Custom Network

Create the dockerapps-net bridge with isolated IPv6 subnets.

docker network create \
--driver=bridge \
--ipv6 \
--subnet=172.20.0.0/24 \
--gateway=172.20.0.1 \
--subnet=fd00:dead:beef:2::/64 \
--gateway=fd00:dead:beef:2::1 \
dockerapps-net


Zone 2: The VPN Bubble (service:gluetun)

This is a specific architectural pattern used for qBittorrent and Transmission.

The "Sidecar" Pattern

These containers do not have a network interface. Instead, they share the network stack of the gluetun container.

  • Outbound: All traffic is forced through the tun0 interface (WireGuard to AirVPN).
  • Inbound: Ports 8080 (qBit) and 9091 (Trans) are mapped on the Gluetun container, not the app containers. Like so:
# Gluetun compose file extract

      ports:
      # --- QBITTORRENT PORTS ---
      - 8080:8080 # qBittorrent Web UI (Host Port: 8080)
      #- 6881:6881       # QBT P2P Port (TCP) commented since using Airvpn Port Forwarding
      #- 6881:6881/udp   # QBT P2P Port (UDP) commented using Airvpn Port Forwarding
      # --- TRANSMISSION PORTS ---
      - 9091:9091 # Trans Web UI (Host Port: 9091)
      #- 6882:6882       # Trans P2P Port (TCP) commented since using Airvpn Port Forwarding
      #- 6882:6882/udp   # Trans P2P Port (UDP) commented since using Airvpn Port Forwarding

Killswitch:

If Gluetun dies, the network stack disappears. The downloaders physically cannot transmit data.

Setting up AirVPN

Selected AirVPN for this stack because it is one of the few providers that supports Port Forwarding and WireGuard simultaneously.

  1. Sign Up: Created an account and purchased a subscription at AirVPN.

  2. Config Generator:

    • Navigated to Client Area > Config Generator.
    • OS: Selected "Linux".
    • Protocol: Selected "WireGuard" (Critical for speed/CPU efficiency).
    • Server Selection: Selected Netherlands (primary for privacy/speed balance) and Singapore (as a low-latency backup).
  3. Key Generation:

    • Generated the configuration.
    • Extracted the Private Key, Preshared Key, and Addresses (IPv4/IPv6) from the generated .conf file or UI.
  4. Port Forwarding (Critical):

    • Navigated to Client Area > Ports.
    • Generated two separate ports:
      • Port A (e.g., xxxxx) for qBittorrent.
      • Port B (e.g., xxxxx) for Transmission.

Example

Note: These specific port numbers must be entered into the .env file and used in the compose file. like so:

  ```bash
  # Gluetun compose file extract

  environment:
  # --- General Settings
  - PUID=${PUID}
  - PGID=${PGID}
  - TZ=${TZ}
  # --- VPN Settings
  - VPN_SERVICE_PROVIDER=airvpn # This one is hardcoded, as it won't change
  - VPN_TYPE=${VPN_TYPE}
  - VPN_IPV6=yes
  # --- WireGuard Settings
  - WIREGUARD_PRIVATE_KEY=${WIREGUARD_PRIVATE_KEY}
  - WIREGUARD_PRESHARED_KEY=${WIREGUARD_PRESHARED_KEY}
  - WIREGUARD_ADDRESSES=${WIREGUARD_ADDRESSES}
  - SERVER_COUNTRIES=${SERVER_COUNTRIES}
  # --- Port Forwarding
  - FIREWALL_VPN_INPUT_PORTS=${AIRVPN_PORT_QBIT},${AIRVPN_PORT_TRANS} #<<- THIS! 

  ```

Zone 3: The Management Plane (Tailscale)

Tailscale runs in network_mode: host on the server.

  • Role: Provides a mesh overlay network.

  • Subnet Routing: Configured as a Subnet Router (192.168.0.0/24), allowing me to access the server's LAN IP from my phone when away from home.

  • Exit Node: Enabled, allowing my phone to tunnel all traffic through the home server when on insecure public Wi-Fi.

Setup and more details at Tailscale Section here


Master Static IP Map

This is the Single Source of Truth for compose.yml static IP assignments.

IP Address Service Stack Port
172.20.0.1 Gateway - -
172.20.0.10 Jellyfin media 8096
172.20.0.11 Gluetun gateway -
- Qbittorrent media 8080
- Transmission media 9091
172.20.0.12 Jellyseerr media 5055
172.20.0.13 Radarr media 7878
172.20.0.14 Sonarr media 8989
172.20.0.15 Bazarr media 6767
172.20.0.16 Gotify ops 8081
172.20.0.17 Arcane mon 3552
172.20.0.19 Profilarr media 6868
172.20.0.20 Prowlarr media 9696
172.20.0.21 FlareSolverr media 8191
172.20.0.22 Jackett media 9117
172.20.0.23 Caddy gateway 80/443
172.20.0.24 CrowdSec gateway -
172.20.0.25 Homepage mon 3000
172.20.0.26 Dozzle mon 9090
172.20.0.27 WUD mon 3001
172.20.0.28 Socket Proxy ops 2375
172.20.0.29 GoAccess ops 7890
172.20.0.31 Beszel mon 8090
172.20.0.33 Kopia ops 51515
172.20.0.37 VoidAuth gateway 3002