thrnz / docker-wireguard-pia

A Docker container for using Wireguard with PIA.
282 stars 54 forks source link

Network settings reset on connected containers when restarting docker-wireguard-pia #44

Open joelstitch opened 2 years ago

joelstitch commented 2 years ago

I am running this container on a Synology NAS, I got it working great on a stack that starts 2 other containers and I have 2 more containers running through it using --net=container. I tested the IP on all of them and they are all successfully going through the VPN. My issue is that whenever I restart the stack running docker-wireguard-pia, the 2 containers using --net=container stop working. In Portainer I have to edit the 2 containers Network settings, On Network it keeps the "container" option but on the Container option it goes blank so I have to choose docker-wireguard-pia and restart the containers. I know I can just add the containers to the stack but the container has a lot of "labels" that I have no idea how to add to the docker compose on the stack.

Here is a screenshot of the labels https://imgur.com/a/5ss78f4

This is the docker command of the stack:

version: '3'
services:
    vpn:
        image: thrnz/docker-wireguard-pia
        container_name: vpn
        volumes:
            # Auth token is stored here
            - pia:/pia
            # If enabled, the forwarded port is dumped to /pia-shared/port.dat for potential use in other containers
            - pia-shared:/pia-shared
        cap_add:
            - NET_ADMIN
            # SYS_MODULE might not be needed with a 5.6+ kernel?
            - SYS_MODULE
        # Mounting the tun device may be necessary for userspace implementations
        #devices:
        #  - /dev/net/tun:/dev/net/tun
        environment:
            # The following env vars are required:
            - LOC=us_chicago
            - USER=MYUSER
            - PASS=PASSWORD
            # The rest are optional:
            - LOCAL_NETWORK=192.168.69.0/24
            #- KEEPALIVE=25
            #- VPNDNS=8.8.8.8,8.8.4.4
            #- PORT_FORWARDING=1
            #- WG_USERSPACE=1
        ports:
            - 9696:9696
            - 6177:6077
            - 8310:7878
            - 8989:8989
        sysctls:
            # wg-quick fails to set this without --privileged, so set it here instead if needed
            - net.ipv4.conf.all.src_valid_mark=1
            # May as well disable ipv6. Should be blocked anyway.
            - net.ipv6.conf.default.disable_ipv6=1
            - net.ipv6.conf.all.disable_ipv6=1
            - net.ipv6.conf.lo.disable_ipv6=1
        # The container has no recovery logic. Use a healthcheck to catch disconnects.
        healthcheck:
            test: ping -c 1 www.google.com || exit 1
            interval: 30s
            timeout: 10s
            retries: 3

    cabernet:
        image: ghcr.io/cabernetwork/cabernet:latest
        container_name: cabernet
        network_mode: service:vpn
        environment:
            - WEBUI_PORT=6077
            - PUID=1026
            - PGID=101
        volumes:
            - /volume1/docker/cabernet:/app
        depends_on:
            - vpn
        restart: always

    prowlarr:
        image: lscr.io/linuxserver/prowlarr:develop
        container_name: prowlarr
        network_mode: service:vpn
        environment:
            - WEBUI_PORT=9696
            - PUID=1026
            - PGID=101
        volumes:
            - /volume1/docker/prowlarr:/config
        depends_on:
            - vpn
        restart: always
volumes:
    pia:
    pia-shared:

The ports 8310 and 8989 are for the 2 containers outside the stack that are using the stack vpn network using --net=container. So, how can I either add Radarr and Sonarr to the stack with all the labels and variables easily or how do I make it so they stay in the vpn network even after restarting the vpn stack?

thrnz commented 2 years ago

I think that's a Docker thing, where when the original container goes down, it's entire network stack also goes down so other containers that may have been sharing its network stack no longer have access to a network. When the container is recreated, the other containers remain networkless and need to be themselves recreated.

I've worked around this in the past by creating a dummy container that does nothing, and then sharing that container's network stack with the other containers, including the vpn container. That way, when the vpn container goes down the network stack remains up. I've not done this before with this specific container though, so I'm not sure how 'graceful' it'll be at being able to reconnect when it comes back up. There might be a chance for data to leak. This way the 'vpn' container can be brought down and restarted without the network stack also going down.

So something like this:

version: '3'
services:
  dummy_network:
    image:  alpine:latest
    command: sleep infinity

  vpn:
    image: thrnz/docker-wireguard-pia
    netowrk_mode: "service:dummy_network"

  some_other_servie:
    image: example/service
    network_mode: "service:dummy_network"

Another way around it that I've also used before is to use healthchecks on effected containers that are able to pick up when the network goes down and then auto triggering a restart using something like this.

I've not actually tested the following exmaple, but the idea is that the network adapters will disappear when the vpn is stopped/restarted, and should be noticed by the healthcheck.

version: '3'
services:
  vpn:
    image: thrnz/docker-wireguard-pia

  some_other_service:
    image: example/service
    network_mode: "service:vpn"
    #Fail healthcheck if adapters have disappeared (ie. no longer attached to the vpn service)
    healthcheck:
      test:  ls /sys/class/net/ | grep -o "eth[0-9*]\|wg[0-9*]" > /dev/null || exit 1
      interval: 10s
    labels:
      - "autoheal=true"

    autoheal:
      restart: always
      image: willfarrell/autoheal
      volumes:
        - /var/run/docker.sock:/var/run/docker.sock

As you said though, adding Sonarr and Radarr to the existing compose file would probably be the easier fix, then you can just bring everything down and up at the same time when needed. From memory, the Linuxserver.io Sonarr and Radarr containers don't need any labels to be manually set to function - all the config is done through ENV vars, though that said I'm not familiar with how Portainer might do things. Modifying your example like this should work:

version: '3'
services:
    vpn:
        image: thrnz/docker-wireguard-pia
        container_name: vpn
        volumes:
            # Auth token is stored here
            - pia:/pia
            # If enabled, the forwarded port is dumped to /pia-shared/port.dat for potential use in other containers
            - pia-shared:/pia-shared
        cap_add:
            - NET_ADMIN
            # SYS_MODULE might not be needed with a 5.6+ kernel?
            - SYS_MODULE
        # Mounting the tun device may be necessary for userspace implementations
        #devices:
        #  - /dev/net/tun:/dev/net/tun
        environment:
            # The following env vars are required:
            - LOC=us_chicago
            - USER=MYUSER
            - PASS=PASSWORD
            # The rest are optional:
            - LOCAL_NETWORK=192.168.69.0/24
            #- KEEPALIVE=25
            #- VPNDNS=8.8.8.8,8.8.4.4
            #- PORT_FORWARDING=1
            #- WG_USERSPACE=1
        ports:
            - 9696:9696
            - 6177:6077
            - 8310:7878
            - 8989:8989
        sysctls:
            # wg-quick fails to set this without --privileged, so set it here instead if needed
            - net.ipv4.conf.all.src_valid_mark=1
            # May as well disable ipv6. Should be blocked anyway.
            - net.ipv6.conf.default.disable_ipv6=1
            - net.ipv6.conf.all.disable_ipv6=1
            - net.ipv6.conf.lo.disable_ipv6=1
        # The container has no recovery logic. Use a healthcheck to catch disconnects.
        healthcheck:
            test: ping -c 1 www.google.com || exit 1
            interval: 30s
            timeout: 10s
            retries: 3

    cabernet:
        image: ghcr.io/cabernetwork/cabernet:latest
        container_name: cabernet
        network_mode: service:vpn
        environment:
            - WEBUI_PORT=6077
            - PUID=1026
            - PGID=101
        volumes:
            - /volume1/docker/cabernet:/app
        depends_on:
            - vpn
        restart: always

    prowlarr:
        image: lscr.io/linuxserver/prowlarr:develop
        container_name: prowlarr
        network_mode: service:vpn
        environment:
            - WEBUI_PORT=9696
            - PUID=1026
            - PGID=101
        volumes:
            - /volume1/docker/prowlarr:/config
        depends_on:
            - vpn
        restart: always

    sonarr:
        image: lscr.io/linuxserver/sonarr:latest
        container_name: sonarr
        network_mode: service:vpn
        environment:
            - WEBUI_PORT=8989
            - PUID=1026
            - PGID=101
        volumes:
            - /path/to/sonarr/config:/config
        depends_on:
            - vpn
        restart: always

    radarr:
        image: lscr.io/linuxserver/radarr:latest
        container_name: radarr
        network_mode: service:vpn
        environment:
            - WEBUI_PORT=7878
            - PUID=1026
            - PGID=101
        volumes:
            - /path/to/radarr/config:/config
        depends_on:
            - vpn
        restart: always

volumes:
    pia:
    pia-shared:
joelstitch commented 2 years ago

I think that's a Docker thing, where when the original container goes down, it's entire network stack also goes down so other containers that may have been sharing its network stack no longer have access to a network. When the container is recreated, the other containers remain networkless and need to be themselves recreated.

I've worked around this in the past by creating a dummy container that does nothing, and then sharing that container's network stack with the other containers, including the vpn container. That way, when the vpn container goes down the network stack remains up. I've not done this before with this specific container though, so I'm not sure how 'graceful' it'll be at being able to reconnect when it comes back up. There might be a chance for data to leak. This way the 'vpn' container can be brought down and restarted without the network stack also going down.

So something like this:

version: '3'
services:
  dummy_network:
    image:  alpine:latest
    command: sleep infinity

  vpn:
    image: thrnz/docker-wireguard-pia
    netowrk_mode: "service:dummy_network"

  some_other_servie:
    image: example/service
    network_mode: "service:dummy_network"

Another way around it that I've also used before is to use healthchecks on effected containers that are able to pick up when the network goes down and then auto triggering a restart using something like this.

I've not actually tested the following exmaple, but the idea is that the network adapters will disappear when the vpn is stopped/restarted, and should be noticed by the healthcheck.

version: '3'
services:
  vpn:
    image: thrnz/docker-wireguard-pia

  some_other_service:
    image: example/service
    network_mode: "service:vpn"
    #Fail healthcheck if adapters have disappeared (ie. no longer attached to the vpn service)
    healthcheck:
      test:  ls /sys/class/net/ | grep -o "eth[0-9*]\|wg[0-9*]" > /dev/null || exit 1
      interval: 10s
    labels:
      - "autoheal=true"

    autoheal:
      restart: always
      image: willfarrell/autoheal
      volumes:
        - /var/run/docker.sock:/var/run/docker.sock

As you said though, adding Sonarr and Radarr to the existing compose file would probably be the easier fix, then you can just bring everything down and up at the same time when needed. From memory, the Linuxserver.io Sonarr and Radarr containers don't need any labels to be manually set to function - all the config is done through ENV vars, though that said I'm not familiar with how Portainer might do things. Modifying your example like this should work:

version: '3'
services:
    vpn:
        image: thrnz/docker-wireguard-pia
        container_name: vpn
        volumes:
            # Auth token is stored here
            - pia:/pia
            # If enabled, the forwarded port is dumped to /pia-shared/port.dat for potential use in other containers
            - pia-shared:/pia-shared
        cap_add:
            - NET_ADMIN
            # SYS_MODULE might not be needed with a 5.6+ kernel?
            - SYS_MODULE
        # Mounting the tun device may be necessary for userspace implementations
        #devices:
        #  - /dev/net/tun:/dev/net/tun
        environment:
            # The following env vars are required:
            - LOC=us_chicago
            - USER=MYUSER
            - PASS=PASSWORD
            # The rest are optional:
            - LOCAL_NETWORK=192.168.69.0/24
            #- KEEPALIVE=25
            #- VPNDNS=8.8.8.8,8.8.4.4
            #- PORT_FORWARDING=1
            #- WG_USERSPACE=1
        ports:
            - 9696:9696
            - 6177:6077
            - 8310:7878
            - 8989:8989
        sysctls:
            # wg-quick fails to set this without --privileged, so set it here instead if needed
            - net.ipv4.conf.all.src_valid_mark=1
            # May as well disable ipv6. Should be blocked anyway.
            - net.ipv6.conf.default.disable_ipv6=1
            - net.ipv6.conf.all.disable_ipv6=1
            - net.ipv6.conf.lo.disable_ipv6=1
        # The container has no recovery logic. Use a healthcheck to catch disconnects.
        healthcheck:
            test: ping -c 1 www.google.com || exit 1
            interval: 30s
            timeout: 10s
            retries: 3

    cabernet:
        image: ghcr.io/cabernetwork/cabernet:latest
        container_name: cabernet
        network_mode: service:vpn
        environment:
            - WEBUI_PORT=6077
            - PUID=1026
            - PGID=101
        volumes:
            - /volume1/docker/cabernet:/app
        depends_on:
            - vpn
        restart: always

    prowlarr:
        image: lscr.io/linuxserver/prowlarr:develop
        container_name: prowlarr
        network_mode: service:vpn
        environment:
            - WEBUI_PORT=9696
            - PUID=1026
            - PGID=101
        volumes:
            - /volume1/docker/prowlarr:/config
        depends_on:
            - vpn
        restart: always

    sonarr:
        image: lscr.io/linuxserver/sonarr:latest
        container_name: sonarr
        network_mode: service:vpn
        environment:
            - WEBUI_PORT=8989
            - PUID=1026
            - PGID=101
        volumes:
            - /path/to/sonarr/config:/config
        depends_on:
            - vpn
        restart: always

    radarr:
        image: lscr.io/linuxserver/radarr:latest
        container_name: radarr
        network_mode: service:vpn
        environment:
            - WEBUI_PORT=7878
            - PUID=1026
            - PGID=101
        volumes:
            - /path/to/radarr/config:/config
        depends_on:
            - vpn
        restart: always

volumes:
    pia:
    pia-shared:

Thanks so much. I got it mostly running smooth now. Now just need to figure out how can I connect to a US Streaming server using TCP. Thats the only way I can use PIA VPN to watch USTVGO

joelstitch commented 2 years ago

That got it working. Thanks for the help!