Introduction
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:
OVPN_DATA="ovpn-data"
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
Paste contents:
[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
Result:
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 docker ps
:
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
The 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.