I love RaspberryPi: the card-sized microcomputer can fit almost everywhere, performing exceptionally well with low energy consumption rates and can help you in a variety of tasks, from setting up a simple webserver to improving your home automation systems, not to mention all the possible DIY projects for the electronic enthusiasts.
Having a 3D printer at home, I wanted to access its web interface from the internet, but in a more secure way. I already connected my 3D printer to the Pi, so the missing puzzle piece was setting up a VPN that only I could access from remote.
The first time I followed a guide on setting up an OpenVPN server on the Pi, but it was a pain setting it up; eventually, I had to reinstall Raspbian on the microSD and had to follow the steps of the guide once again to set up the VPN. It was time-consuming and frustrating getting all the needed packages and making sure that everything worked out of the box.
Enter Docker: docker is fairly easy to install on the Raspberry, and it is also pretty lightweight, meaning more containers can be run at the same time and managed by, for example, docker-compose, without the Raspberry heating up too much or stress it to the limit. Let’s see what we need to do in order to transform this little berry beast into our personal home VPN server.
Step 1: Forward the correct port on your home router
For this guide, we need to forward UDP port 1194 of our router to the outer world. This step is different for every router out there, so you might need to tinker a bit with your router to expose the 1194 port. Here, Google is your friend, just search for the model of your router and a guide should, hopefully, come up.
Step 2: Use a DNS service to identify your RaspberryPi
For this step, my tool of choice is using DuckDNS, a free DNS service which can be easily set up in your raspberry in a couple of minutes, thanks to their easy to follow guide. For starters, let’s go to the DuckDNS site and register your account. Then, on the main page, create a domain by filling the “sub domain” textbox with a name of your choice and hit the green “add domain” button.
Now, go to the install tab on the menu and select “pi” in the “operating systems” list as shown below. Finally, select the domain you previously created in the dropdown menu of “first step – choose a domain” and follow the guide that will appear: it will be already configured for the domain of your choice and you only need to copy/paste the commands shown there.
If you like this service, please consider donating through their Patreon page! it is as low as 1$ per month, but I think it’s a great free service and should be supported. Once set up, you are ready to get your hand dirty with docker and build your own VPN server.
Step 3: Install Docker
To install docker on your RaspberryPi running Raspbian OS you must be on version 9 (Stretch) or higher. Unlike Debian, for Raspbian you have to install docker through a convenience script hosted by Docker itself, that you can find in the original guide. Follow the steps in the guide and then test your installation by running the HelloWorld image, a lightweight docker image which is used just to test that the installation is completed successfully by typing:
sudo docker run hello-world
This command will download the image and run the container which will print a console message if it ran successfully. Congrats! You are now ready to create the VPN server!
Step 4: Set up the VPN container
Now that everything is up and running, we are ready for the fun part! First, let’s run the service container (you must change YOUR_DOMAIN at line 3 with the domain name you created in step 2. If you use a different DNS service, change also the rest of the URL):
OVPN_DATA="ovpn-data" sudo docker volume create --name $OVPN_DATA sudo docker run -v $OVPN_DATA:/etc/openvpn --log-driver=none --rm mjenz/rpi-openvpn ovpn_genconfig -u udp://YOUR_DOMAIN.duckdns.org sudo docker run -v $OVPN_DATA:/etc/openvpn --log-driver=none --rm -it mjenz/rpi-openvpn ovpn_initpki sudo docker run -v $OVPN_DATA:/etc/openvpn -d -p 1194:1194/udp --cap-add=NET_ADMIN --restart always mjenz/rpi-openvpn
To sum up this part, it simply creates the container which will be used as the VPN service with the last line. The “–restart always” makes sure that your container is restarted whenever it crashes or docker service is restarted, for example at the startup of Raspbian after a shutdown. Now, it is time to create the certificate for connecting to the VPN:
sudo docker run -v $OVPN_DATA:/etc/openvpn --log-driver=none --rm -it mjenz/rpi-openvpn easyrsa build-client-full CLIENTNAME nopass sudo docker run -v $OVPN_DATA:/etc/openvpn --log-driver=none --rm mjenz/rpi-openvpn ovpn_getclient CLIENTNAME > CLIENTNAME.ovpn
Where CLIENTNAME is a name convenient to you (e.g. I have different certificates for my devices, MacBook, SmartPhone, PC ecc…). This will create a certificate that will not require a password to connect. If you want to enforce the security, you can omit the “nopass” at line 1 of the previous code section and you will be prompted for a password.
If you have done everything right, you will find in the path you are currently at in your raspberry, a file called “CLIENTNAME.ovpn”: save this file and use it in the OVPN client you are using to connect to the VPN.
That’s it, you have created a VPN server with docker, and in a much more convenient way than installing it as you would have done without the help of containers. Plus, if you ever need to remove the VPN, it is as easy as deleting the container.