-
Notifications
You must be signed in to change notification settings - Fork 0
Gluetun VPN
🇬🇧 English · 🇫🇷 Français
Running Hydra behind a VPN with gluetun is the fiddliest supported setup, so it gets its own page. Two things make it special:
- The forwarded port(s) can rotate. With port forwarding on, gluetun hands Hydra the provider's forwarded port; on some providers it changes on every reconnect. Hydra rebinds its listen port hot (no restart — torrents and live peers stay up), but something has to push the current port to it.
- One inbound port serves one engine. race and hoard are two processes and cannot share one inbound TCP port. So how many engines you can seed inbound behind one tunnel depends on how many ports your provider forwards.
This decides your whole layout, and it's a provider limit (how many ports it lets gluetun forward), not a gluetun one. gluetun does port forwarding for these providers — check your own plan, but as of writing:
| Provider | Ports gluetun forwards | Layout |
|---|---|---|
| AirVPN | up to 5 (you reserve them in the AirVPN panel) | monolith (race + hoard) on one gluetun |
| Perfect Privacy | multiple (3 auto + up to 5 custom) | monolith on one gluetun |
| ProtonVPN | 1, random, rotates (NAT‑PMP)¹ | one engine, or front-only + one agent per gluetun |
| PIA | 1, dynamic | one engine, or split |
| PrivateVPN | 1 per server | one engine, or split |
¹ ProtonVPN's NAT‑PMP can map more, but gluetun currently exposes a single port (multi-port is an open gluetun request).
Rule of thumb: ≥ 2 forwarded ports → run a monolith (race + hoard) behind one gluetun. Only 1 → run one engine behind it, or split into a front-only + one agent per gluetun (below).
-
VPN_PORT_FORWARDING=onenables it. -
VPN_PORT_FORWARDING_UP_COMMANDruns when forwarding is set up (and on each renegotiation). Placeholders:{{PORT}}= the first forwarded port,{{PORTS}}= comma-separated list (e.g.16171,16172). -
FIREWALL_VPN_INPUT_PORTS= ports allowed inbound through gluetun's firewall (set these to your forwarded ports so peers can reach Hydra). -
FIREWALL_OUTBOUND_SUBNETS= LAN subnets Hydra is allowed to reach out to. - The forwarded port is also exposed on gluetun's control server and (pre-v4) the
file
/tmp/gluetun/forwarded_port.
Hydra shares gluetun's network namespace (network_mode: service:gluetun), so
its UI/API (127.0.0.1:8199) and its egress all live in the tunnel. Push the
port with Hydra's HTTP API: POST /api/{race,hoard}/listen-port {"port":N}.
These providers give you fixed forwarded ports: you reserve them in the
provider's panel and they don't change. So there is nothing dynamic to push
— no UP_COMMAND. Just set each engine's listen port statically in
default.toml to your reserved ports, and open them inbound on the firewall.
Say you reserved 16171 (race) and 16172 (hoard) in the AirVPN panel.
./config/default.toml:
[race]
listen_port = 16171
[hoard]
listen_port = 16172services:
gluetun:
image: qmcgaw/gluetun
cap_add: [NET_ADMIN]
ports:
- "8199:8199" # Hydra UI, through the tunnel container
environment:
- VPN_SERVICE_PROVIDER=airvpn
- VPN_TYPE=wireguard
# WireGuard values from AirVPN's Config Generator (Client Area):
- WIREGUARD_PRIVATE_KEY=your-private-key
- WIREGUARD_PRESHARED_KEY=your-preshared-key
- WIREGUARD_ADDRESSES=10.128.0.2/32
- SERVER_COUNTRIES=Netherlands # optional: pick your exit
- FIREWALL_VPN_INPUT_PORTS=16171,16172 # open your reserved ports inbound
- FIREWALL_OUTBOUND_SUBNETS=192.168.1.0/24 # reach a LAN qBit, etc.
hydra:
image: ghcr.io/kheopsian/hydra:latest
network_mode: "service:gluetun"
depends_on: [gluetun]
volumes:
- ./config:/config
- /path/to/data:/dataBoth engines get real inbound, the ports are baked into the config, and nothing has to run on reconnect. This is the simplest layout when your provider gives you enough ports.
You only get one port, so you can't give both engines inbound behind one tunnel. Two options:
-
One engine behind gluetun — same compose as (A) but push the single
{{PORT}}to justhoard(orrace):VPN_PORT_FORWARDING_UP_COMMAND=/bin/sh -c 'wget -qO- --header="X-Api-Key: $${HYDRA_API_KEY}" --header="Content-Type: application/json" --post-data="{\"port\":{{PORT}}}" http://127.0.0.1:8199/api/hoard/listen-port' -
Inbound on both — run a
--front-onlycontroller plus one--agent-onlyengine per gluetun (each its own single port). See Deployment Topologies. An--agent-onlynode has no HTTP API, so push its port with the CLI inside the agent container (hydra set-listen-port /config/<engine>.sock <port>), driven off gluetun's forwarded-port file/control-server (a small watcher) — gluetun'sUP_COMMANDruns in the gluetun container, where thehydrabinary isn't.
-
LAN is unreachable by default. Inside the tunnel
localhostis the VPN namespace, not your host, and the LAN is firewalled. SetFIREWALL_OUTBOUND_SUBNETS=192.168.x.0/24on the gluetun service to let Hydra reach a LAN service (e.g. a qBittorrent for the import wizard); use the LAN IP, notlocalhost. -
Open the forwarded ports inbound with
FIREWALL_VPN_INPUT_PORTS, or peers can't reach you. -
The
listen_portindefault.toml: on fixed-port providers (AirVPN, Perfect Privacy) this IS the real port — set it to your reserved port. Only on dynamic-port providers (Proton, PIA, PrivateVPN) is it a placeholder that the up-command overwrites on every reconnect. -
Expose the UI on the gluetun service (
8199:8199), not on the Hydra service — Hydra has no ports of its own undernetwork_mode: service:gluetun.
The exact
UP_COMMAND(wget vs curl, quoting) varies with the gluetun image and your provider — treat the snippets above as a starting point and check them against a known-good setup.
See also Networking Modes and Deployment Topologies.
Hydra · 🇬🇧
Understand
Install & set up
- Installation & First Run
- Bare-metal Install
- Windows install
- Networking Modes
- Gluetun (VPN)
- Deployment Topologies
Use day-to-day
Reference
Hydra · 🇫🇷
Comprendre
Installer & mettre en place
- Installation & premier démarrage
- Installation bare-metal
- Installation Windows
- Modes réseau
- Gluetun (VPN)
- Topologies de déploiement
Utiliser au quotidien
Référence