VPN enabled podman container(s)
So you use for example a p2p bittorrent client and you want to be a good citizen so not just leeching but uploads also. Wouldn’t it be nice if you clould use p2p port forwarding with your favourite VPN provider.
Enter: gluetun
Gluetun works with a platoon of VPN providers both with openvpn and wireguard and even portforwarding is an option.
In this post I will focus on:
- Podman
- Proton VPN
- Deluge bittorrent client
The trick is to use a special docker network, instead of giving deluge a dedicated or shared network you instruct it to use the network of another running container. In this case that is Gluetun configured to use:
- a Proton VPN wireguard config you made through their website. This should provide you with a static anonymous ip address and a static port both available on the internet facing part of things and within the gluetun container.
- P2P should be enabled
- Bear in mind that the deluge container is exposed on the Gluetun network and also since the VPN tunnel is active there is also no need to expose any ports in Gluetun. You should however activate NAT-PMP in deluge:
In the end I made this simple docker-compose.yml to bind it all together, the most important part is this one, network_mode: “service:gluetun”:
---
services:
gluetun:
image: docker.io/qmcgaw/gluetun
container_name: gluetun
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun:/dev/net/tun
environment:
- VPN_SERVICE_PROVIDER=custom
- VPN_TYPE=wireguard
- VPN_ENDPOINT_IP=<vpn config public ip>
- VPN_ENDPOINT_PORT=51820
- VPN_PORT_FORWARDING_PROVIDER=protonvpn
- WIREGUARD_PUBLIC_KEY=<vpn config public key>
- WIREGUARD_PRIVATE_KEY=<vpn config private key>
- WIREGUARD_ADDRESSES=10.2.0.2/32
- FIREWALL_OUTBOUND_SUBNETS=192.168.0.0/16 # Internal network
- VPN_PORT_FORWARDING=on
networks:
- traefik_default
labels:
- traefik.enable=true
- traefik.docker.network=traefik_default
- traefik.http.routers.deluge.rule=Host(`<your subdmomain>`)
- traefik.http.routers.deluge.entrypoints=websecure
- traefik.http.routers.deluge.tls=true
- traefik.http.routers.deluge.tls.certresolver=myresolver
- traefik.http.services.deluge.loadbalancer.server.port=8112
- PODMAN_SYSTEMD_UNIT:gluetun.service
- io.containers.autoupdate=registry
healthcheck:
test: "ping -c 1 10.2.0.1 || exit 1"
timeout: 4s
retries: 3
restart: always
deluge:
image: lscr.io/linuxserver/deluge:latest
container_name: deluge
network_mode: "service:gluetun"
env-file: /root/secrets/deluge
volumes:
- /var/spool/docker-data/deluge:/config:Z
- /data/deluge:/downloads:z
depends_on:
- gluetun
labels:
- PODMAN_SYSTEMD_UNIT:deluge.service
- io.containers.autoupdate=registry
restart: unless-stopped
networks:
traefik_default:
external:
name: traefik_default
A couple of things to notice:
- I use Podman and as such some options are Podman specific.
- I use Traefik as my https loadbalancer and included that in this docker-compose.yml
- Note: the Traefik labels are in the Gluetun section not in the Deluge one!
- Although podman-auto-update should work just fine there is one catch: Gluetun container depends on the Deluge container, so after updating Gluetun bringing up the renewed Gluetun container again will fail if the Deluge container is still active.
- I added a simple healthchaeck to the Gluetun service.
How you would run all of this is up to you but personally I still use:
# podman generate systemd --new <container_name> > /etc/systemd/system/<service_name>.service
I know quadlets are the way to go these days, but this still just works for me ™ 😉
Hope this can serve as a starting point for somebody out there!