/openvpn-pihole

🕵️ A truly delicious combination of two wonderful pieces of software to setup a pi.hole-backed VPN as quick as possible.

Primary LanguageShellMIT LicenseMIT

Logo

OpenVPN and PiHole wrapped up in a docker-compose setup


CI Status GitHub Sponsors Buy me a Coffee Support on Patreon


This project is a composition out of the official PiHole docker image and a hand-crafted openvpn-image to set up a ready-to-use VPN with PiHole as dns-resolve in less than a minute. Its configuration is kept simple, you can add / remove clients and easily extend it as the configuration is stored in a centralized and easily manageable way. Enjoy!

The main configuration for this is inspired by mr-bolle/docker-openvpn-pihole, pknw1/openvpn-pihole-docker and kylemanna/docker-openvpn.

Table of Contents

Setup

First clone this repository:

git clone https://github.com/simonwep/openvpn-pihole.git
cd openvpn-pihole

Make sure you're using the latest docker and docker-compose. I'm using v3.5 for the docker-compose.yml, so you'll need at least v17.12.0 for the docker-engine (see this table).

If you share your VPN with others it's highly recommended changing the admin password for the PiHole dashboard in the docker-compose.yml file now.

After you've installed all the pre-requisites you can run.

sudo docker compose up -d

After this is done you'll find two new folders inside of this repository - the /openvpn folder will contain all of your certificates as well as an easy-rsa configuration file. /pihole will contain the content of /etc/pihole and /etc/dnsmasq.d.

Until this issue has been resolved I'll be using mounted host directories for the sake of simplicity.

If you want to migrate settings or your query-database you can now copy it into the corresponding folder in /pihole :) The pihole admin dashboard can only be reached through the vpn.

If you're using a VPS make sure to open 1194/udp!

Generating .ovpn files

Before you generate any client certificate you must update the host in client configuration. This file will be used as base-configuration for each .ovpn file! You probably at least want to change the IP address to your public one.

sudo docker exec openvpn bash /opt/app/bin/genclient.sh <name> <password?>

You can find you .ovpn file under /openvpn/clients/<name>.ovpn, make sure to change the remote ip-address / port / protocol.

Generating a list of certificates

This repo contains a script genclients that can be used to generate a list of clients with the current year as suffix:

./genclients <password> <username1> [<username2> ... <usernameN>]

Revoking .ovpn files

sudo docker exec openvpn bash /opt/app/bin/rmclient.sh <name>

Revoked certificates won't kill active connections, you'll have to restart the service if you want the user to immediately disconnect:

sudo docker compose restart openvpn

Renewing certificates

Depending on the configuration of easy-rsa the certificates will expire at some point. By default, that is after two years, to renew it you can simply remove the pki folder that contains the certificate authority. After restarting the service, a new CA will be generated.

docker compose down
rm -rf ./openvpn/pki
docker compose down -d

Keep in mind, that after that you have to re-generate all .ovpn-files.

Configuration

OpenVPN

Configuration files (such as server.conf and client.conf) are stored in openvpn/config. They get copied every time the instance gets spawned so feel free to change / update them any time.

PiHole

We're always using the very latest PiHole version - start the PiHole service at least once to edit configuration files manually.

FAQ & Recipes

Launching multiple openvpn instances with different protocol/port config

First copy the openvpn directory including openvpn/config (copy just the config folder!), then add another service to docker-compose.yml.

Example assuming we want to name our second openvpn instance openvpn-tcp-443:

mkdir openvpn-tcp-443
cp -r openvpn/config openvpn-tcp-443

You can now make changes to our new config files in openvpn-tcp-443/config. Change proto to tcp and port to 443, you'll also need to comment out explicit-exit-notify 1 as this is only compatible with proto udp (update both server.conf and client.conf!).

Now add our new service:

# ... other services
    openvpn-tcp-443:
        container_name: openvpn-tcp-443
        build: ./openvpn-docker
        ports:
            - 443:443/tcp
        volumes:
            - ./openvpn/pki:/etc/openvpn/pki # Keep the PKI
            - ./openvpn-tcp-443/clients:/etc/openvpn/clients
            - ./openvpn-tcp-443/config:/etc/openvpn/config # !! We're using our second configuration
        cap_add:
            - NET_ADMIN
        restart: unless-stopped
# ... other services

Keep in mind that if you want to generate a client-config for that service we've just made you'll have to use the openvpn-tcp-443 container e.g. sudo docker exec openvpn-tcp-443 bash /opt/app/bin/genclient.sh <name>.

Troubleshooting

Port 53 is already in use

ERROR: for pihole Cannot start service pihole: driver failed programming external connectivity on endpoint pihole (...): Error starting userland proxy: listen tcp 0.0.0.0:53: bind: address already in use

You'll need to disable the local dns-server, see this and this askubuntu thread. You can stop, disable and mask the systemd-resolved service using the following commands:

sudo systemctl stop systemd-resolved
sudo systemctl disable systemd-resolved
sudo systemctl mask systemd-resolved

Contributing

Checkout the contribution guidelines :)