This tutorial will guide you into getting a docker container running on your Ubuntu/Debian host.
I originally followed this tutorial but with the introduction of systemd it is slightly out of date, so I have outlined exactly what to do in here.
I have also added instructions on how to add UPnP support which I needed as I have a permanent VPN connection at home via my RaspberryPi - guide here.
Initial Server Setup
If you’re on most VPS providers, you’re probably starting out with root. This is bad for a number of reasons.
Please follow these instructions, and at a minimum create your own user with sudo and disable root login.
Step 1 - Install and Configure Docker
Add the upstream Docker repository as the Ubuntu one can’t really keep up with the pace of change.
curl -L https://get.docker.com/gpg | sudo apt-key add -
echo deb http://get.docker.io/ubuntu docker main | sudo tee /etc/apt/sources.list.d/docker.list
Update packages and install Docker:
sudo apt-get update && sudo apt-get install -y lxc-docker
Add your user that you created earlier to the docker group.
sudo usermod -aG docker demo
Log out and log back in, running the id command should show the docker group present:
uid=1001(test0) gid=1001(test0) groups=1001(test0),27(sudo),999(docker)
Step 2 - Set Up the EasyRSA PKI Certificate Store
This step is usually a headache for those familiar with OpenVPN or any services utilizing PKI. Luckily, Docker and the scripts in the Docker image simplify this step by generating configuration files and all the necessary certificate files for us.
Create a volume container. This tutorial will use the
$OVPN_DATA environmental variable to make it copy-paste friendly. Set this to anything you like. The default ovpn-data value is recommended for single OpenVPN Docker container servers. Setting the variable in the shell leverages string substitution to save the user from manually replacing it for each step in the tutorial:
Create an empty docker volume with a busybox image:
docker run --name $OVPN_DATA -v /etc/openvpn busybox
We’ll now init the
OVPN_DATA container that will hold all of our config and certificates.
Make sure you replace vpn.app.com with your intended FQDN, or use the IP if you are sure you won’t need to change it in the future. If you do need to change it, you would need to update every client file.
docker run --volumes-from $OVPN_DATA --rm kylemanna/openvpn ovpn_genconfig -u udp://vpn.app.com:1194
Generate PKI authority. Make sure you pick a good password and REMEMBER it!
docker run --volumes-from $OVPN_DATA --rm -it kylemanna/openvpn ovpn_initpki
“Note, the security of the
$OVPN_DATA container is important. It contains all the private keys to impersonate the server and all the client certificates. Keep this in mind and control access as appropriate. The default OpenVPN scripts use a passphrase for the CA key to increase security and prevent issuing bogus certificates.“
Step 3 - Run OpenVPN Container
To autostart your OpenVPN Docker container, you’ll need to create a
docker-openvpn.service file for systemd.
sudo vim /lib/systemd/system/docker-openvpn.service
[Unit] Description=Dockerized OpenVPN Service After=docker.service BindsTo=docker.service Conflicts=shutdown.target reboot.target halt.target [Service] TimeoutStartSec=0 TimeoutStopSec=30 Restart=always RestartSec=10 ExecStart=/usr/bin/docker run --volumes-from ovpn-data --rm -p 1194:1194/udp --cap-add=NET_ADMIN kylemanna/openvpn ExecStop=/usr/bin/docker stop kylemanna/openvpn NotifyAccess=all [Install] WantedBy=multi-user.target
Enable the service on boot
sudo systemctl enable docker-openvpn.service
Start the systemd service:
sudo systemctl start docker-openvpn.service
Check the status:
sudo systemctl status docker-openvpn.service
sean@vpn2:~$ sudo systemctl status docker-openvpn.service ● docker-openvpn.service - Dockerized OpenVPN Service Loaded: loaded (/lib/systemd/system/docker-openvpn.service; disabled; vendor preset: enabled) Active: active (running) since Tue 2016-07-26 11:02:43 BST; 1 weeks 1 days ago Main PID: 4448 (docker) Tasks: 6 Memory: 6.3M CPU: 1min 5.150s CGroup: /system.slice/docker-openvpn.service └─4448 /usr/bin/docker run --volumes-from ovpn-data --rm -p 1194:1194/udp --cap-add=NET_ADMIN kylemanna/openv
You can also verify it is running via
sean@vpn2:~$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d1f61e8bd561 kylemanna/openvpn "ovpn_run" 8 days ago Up 8 days 0.0.0.0:1194->1194/udp big_snyder
Step 4 - Generate Client Cerificates and Config
Make sure you replace
clientname in the following commands with your actual client name. For example, I used
vpn2-xyz just to prefix the config files so I knew which server I was connecting to in Tunnelblick.
Create certificates with helpful scripts:
docker run --volumes-from $OVPN_DATA --rm -it kylemanna/openvpn easyrsa build-client-full CLIENTNAME nopass
Generate client config which is just one file to download via scp:
docker run --volumes-from $OVPN_DATA --rm kylemanna/openvpn ovpn_getclient CLIENTNAME > CLIENTNAME.ovpn
CLIENTNAME.ovpn is self-contained and contains the certificates too, so download it now to your client and you will be ready to go!
Step 5 - UPnP Support
I noticed this was lacking when trying to stream a show on the Plex mobile app. I was unable to get a direct connection because my home now had a permanent VPN connection as discussed.