OpenVPN with Docker Containers
Docker is becoming more and more commonplace with custom instance. I recently found myself needing a IDS node container for internal use that would automatically connect to a centralized logging server. The difference from other containers, was the need for an automatically active OpenVPN connection that would start with the instance. At first glance this would seem like a simple process, but the reality is that it requires a bit more effort to create. Let’s look at how to create this container using Alpine Linux, and how to use the power of supervisor to run multiple services.
OpenVPN with Docker
The idea behind the container build was out of need. We needed our Nginx reverse-proxy to pass analytical data to a centralized database server. Because of additional features provided on the host, our company uses a external host for the proxy. So we needed a custom OpenVPN tunnel to securely pass sensitive data to remote logging servers.
Dockerfile Setup
As usual, we add the required packages for OpenVPN as well as supervisor for our process control. Then we replace the configuration files with a custom local copy. We place all of the OpenVPN files into a local folder named vpn. The vpn folder holds the client.conf file, as well as the required keys and certificates needed for OpenVPN. By doing this, we only need one command to copy everything to the /etc/openvpn folder.
ADD vpn/ /etc/openvpn/
If you are looking to setup lots of OpenVPN clients, be sure to check out our OpenVPN Client Management Script.
Since we are wanting to use OpenVPN, we will need access to a tun device for the tunnel. Depending on the host, this device may already be available. In case it doesn’t exist, we create a placeholder during the build process:
RUN mkdir -p /dev/net && \
mknod /dev/net/tun c 10 200 && \
chmod 600 /dev/net/tun
Even if it is, we create it so we can build the container image. When we test our build locally, we can provide the device from our own local system like so:
$ docker run --cap-add=NET_ADMIN --device /dev/net/tun:/dev/net/tun -i -t openvpn-test /bin/sh
Once we can establish a connection with OpenVPN, we need to verify it can go through the tunnel. In order to forward our traffic to the tunnel, we need to enable forwarding through sysctl. We do this by placing the network.conf file, which enabled forwarding, in the sysctl.d folder. To make this automatic, we copy the network.conf file to the container in the Dockerfile. Now that we have this file in place, network forwarding is automatically applied every time the container starts.
/etc/sysctl.d/network.conf
net.ipv4.ip_forward=1
All that’s we have left to do is to set supervisor as our command which starts with the container. Below we see the Dockerfile used for this setup. This file shows multiple services, but keep in mind that snmpd, rsyslog, and nginx are not required for OpenVPN to work. These are present within a real-world docker build, and showcases how a container can run multiple services.
Dockerfile
FROM nginx:alpine
RUN mkdir -p /dev/net && \
mknod /dev/net/tun c 10 200 && \
chmod 600 /dev/net/tun
RUN apk update && \
apk add openvpn rsyslog net-snmp net-snmp-tools iproute2 bash supervisor curl
ADD nginx.conf /etc/nginx/conf.d/default.conf
ADD network.conf /etc/sysctl.d/network.conf
ADD vpn/ /etc/openvpn/
ADD supervisor.conf /app/
ADD rsyslog.conf /etc/rsyslog.conf
ADD snmpd.conf /etc/snmp/snmpd.conf
ENV NGINX_PORT=8080
CMD /usr/bin/supervisord -c /app/supervisor.conf
On the very last line, we are using supervisor as an entry point using CMD, which causes supervisor to become the foreground process to keep the container alive.
Supervisord
Supervisor is a great complement to Docker, giving anyone the ability to run multiple light services within a single container. When you use supervisor, you set a base configuration, then set the configuration for each program you want to run. If a service goes down, supervisor will then restart it so the service is always running.
When working with Docker, we need to make sure none of our programs are running in daemon mode. This means they need to be running in the foreground. If we don’t, we’ll see errors in our deploy, showing the process ran for “< 1 second”, meaning it went right into the background, which supervisor sees as an error. So as we setup our configuration, we set each service to run in the foreground one way or another.
We set supervisor to run in nodaemon mode, as root, and log output to our log folder. Continuing our setup, we add a supervisor HTTP server, and then configure the programs to be run on startup.
We also need to make sure OpenVPN is set to run in the /etc/openvpn folder. This way it has the correct relative path for the configuration and the keys provided. Next we set our logs to output to the stdout and stderr. By doing this, we can see OpenVPN logs within the console logs. Most importantly, set the programs to autorestart. When the service stops, supervisor will immediately start that service again.
[supervisord]
logfile=/var/log/supervisord
logfile_maxbytes=0
loglevel=info
pidfile=/tmp/supervisord.pid
nodaemon=true
user=root
[unix_http_server]
file=/tmp/supervisor.sock
[program:openvpn]
directory=/etc/openvpn
command=/usr/sbin/openvpn --config /etc/openvpn/client.conf
autostart=true
autorestart=true
stdout_logfile=/dev/stdout
stderr_logfile=/dev/stderr
stdout_logfile_maxbytes=0
stderr_logfile_maxbytes=0
[program:nginx]
command=/usr/sbin/nginx -g 'daemon off;'
autorestart=true
startsec=0
stopwaitsec=0
stopasgroup=true
killasgroup=true
stdout_logfile=/dev/stdout
stderr_logfile=/dev/stderr
stdout_logfile_maxbytes=0
stderr_logfile_maxbytes=0
[program:rsyslog]
command=/usr/sbin/rsyslogd -n
autorestart=true
[program:snmpd]
command=/usr/sbin/snmpd -f
autorestart=true
While looking at the commands set for each process, you’ll find each one is using a command flag. These services are explicitly run in the foreground so supervisor can directly monitor the output. If you don’t do this, you will get errors of processes running for “< 1 second”, meaning it went in the background. Since some services do not offer a foreground mode, so you may have to use a debug mode instead. As long as you keep in mind everything needs to be in the foreground, you won’t have issues with supervisor builds.
Comments: 34
books in ancient times was papyrus
Preserved about 300 thousand.
number of surviving European
antiquities. These are the Egyptian papyri
Western Europe also formed
Duke de Montosier
reproduced by hand, in contrast
among them acquired “Moral
and was erased, and on cleaned
One of the most skilled calligraphers
from lat. manus – “hand” and scribo – “I write”) [1]
Middle Ages as in Western
book about the chess of love “, created by
term manuscript (late lat.manuscriptum,
or their samples written
XVII century was Nicholas Jarry [fr].
manuscripts attributed to Robins
55 thousand Greek, 30 thousand Armenian
so expensive material
bride, Julie d’Angenne.
works of art.
elements (case, binding).
By the end of the 15th century, 35
The most common form
Manuscript is a collective name for texts
bride, Julie d’Angenne.
One of the most skilled calligraphers
manuscripts attributed to Robins
written on the parchment was scratched out
and was erased, and on cleaned
way. Handwritten book
way. Handwritten book
inventions of typography
book about the chess of love “, created by