vpn-documentation/ADD_DAEMON_NODE.md -rw-r--r-- 7.7 KiB
9d424f25François Kooman golang from backports on Debian 10 8 days ago

#title: Add Node(s) description: Add additional VPN nodes for handling OpenVPN connections category: advanced

NOTE: if you have only 1 VPN server and do not want to deploy additional servers, check the documentation on how to switch to the daemon on one server here.

NOTE: if you want to deploy a controller with node(s) we recommend you look at this documentation!

NOTE: if you run on Debian, replace yum with apt, /etc/pki/vpn-daemon with /etc/ssl/vpn-daemon and /etc/sysconfig/vpn-daemon with /etc/default/vpn-daemon.

This document describes how to add new VPN servers to your VPN setup. We assume you setup your current VPN server using deploy_${DIST}.sh and have everything on one machine.

Adding more servers will allow you to handle more VPN users concurrently!

When using multiple servers, we'll make a distinction between controller and node(s). The controller runs the portal and API, the node runs the OpenVPN process(es). A typical deploy looks like this:

  • Machine 1 has both controller and node functionality in location X (this is what you end up with when you use deploy_${DIST}.sh);
  • Machine 2 has node functionality in location Y;
  • Machine n has node functionality in location N.

Those machines can be in the same data center, or in physically different locations.


In order to securely add node(s) to your VPN setup we implemented a simple VPN daemon that runs on the node(s). The communication channel between the controller and node is protected by TLS (client certificates) when contacting remote nodes.



First we switch our controller to use the daemon as well to talk to the local OpenVPN processes. This is rather simple:

$ sudo yum -y install vpn-daemon
$ sudo systemctl enable --now vpn-daemon

Modify /etc/vpn-server-api/config.php and add the configuration key useVpnDaemon and set its value to true in the "root", i.e. on the same level as vpnProfiles.

Make sure everything still works, i.e. you can see connected clients when visiting the "Connections" tab in the portal.


As the daemon will use TLS with client certificates when talking to remote daemons, and only when talking to remote daemons, we have to set up a (new) PKI with our own root certificate and generate server & client certificates. These certificates will be valid for 5 years, the default of the CA. The --no-after CA flag means the certificates will expire at the exact same moment as the CA.

$ sudo yum -y install vpn-ca

Generate the CA and certificates:

$ vpn-ca -init
$ vpn-ca -server vpn-daemon -not-after CA
$ vpn-ca -client vpn-daemon-client -not-after CA

Now you have to copy the ca.crt, vpn-daemon-client.crt and vpn-daemon-client.key to /etc/vpn-server-api/vpn-daemon and make sure the web server can read them:

$ sudo mkdir -p /etc/vpn-server-api/vpn-daemon
$ sudo chmod 0710 /etc/vpn-server-api/vpn-daemon
$ chmod 0640 ca.crt vpn-daemon-client.crt vpn-daemon-client.key
$ sudo cp ca.crt vpn-daemon-client.crt vpn-daemon-client.key /etc/vpn-server-api/vpn-daemon
$ sudo chgrp -R apache /etc/vpn-server-api/vpn-daemon

Keep track of the vpn-daemon.crt and vpn-daemon.key files as you'll need them later on the node.


Add a new profile to your server as described here. For every node you need to add an additional profile. You need to take care of setting the following options correctly for the new node:

  • managementIp - set it to the IP address on which you will contact your new node;
  • hostName - set it to the hostname of the VPN node that points to its public IP address;
  • range and range6 - set them to the IP addresses you want that particular node to issue to the clients.

If you want to use "round robin" DNS to balance the load over various nodes you can set the hostName to the same hostname of your other profile. You can also use the hideProfile in the configuration to not show it to users directly.

Next, we want to allow access from the node(s) to the vpn-server-api API component on the controller. Modify /etc/httpd/conf.d/vpn-server-api.conf and add Require ip lines containing the IP address(es) of the node(s). Most likely this will be the public IP address(es) of the node(s). Make sure you restart Apache!

Take note of the secret under apiConsumers => vpn-server-node in /etc/vpn-server-api/config.php, you'll need it on the node later.

Set the configuration option profileList in /etc/vpn-server-node/config.php and list only the VPN profiles that are active on the controller, not the one you want to deploy on the node, e.g.:

'profileList' => ['internet'],


You can use the deploy_${DIST}_node.sh for installing the node. It will only install the relevant software to connect to your controller and handle VPN connections.

The deploy script will ask for your API URL, which is the full HTTPS URL to your VPN controller. Replace the host name with your controller's name, e.g. https://vpn.example.org/vpn-server-api/api.php.

You will need the API secret as well that you took note of before, the script will also ask for that!

If everything was setup correctly, the node script should run without any problems! If it doesn't you can always re-run it.

You can restrict the profiles you deploy on the node. By default, all profiles will be deployed, which is not always what you want.

You can use the configuration option profileList in /etc/vpn-server-node/config.php. It takes an array containing a list of profiles to deploy on this particular node. The default, when the option is missing, is to deploy all profiles on this node. Example:

'profileList' => ['internet-far-away'],
'useVpnDaemon' => true,

Update your firewall to allow access from the controller to the VPN daemon.

To apply the configuration changes:

$ sudo vpn-maint-apply-changes

If the command is not available, install the vpn-maint-scripts package first.


Now to allow the controller to contact the node, we have to setup the daemon.

$ sudo yum -y install vpn-daemon

Enable TLS by removing the comment in /etc/sysconfig/vpn-daemon and set the LISTEN line to the IP address that you configured in the managementIp in the controller, e.g.


Where x.y.z.b is the IP address of the node. This is probably the public IP address of the node.

NOTE we have some problems with automatically starting vpn-daemon on boot when you specify an IP address. The IP won't be assigned to the interface before vpn-daemon tries to start and thus fail to start. The (dirty) solution is to use LISTEN=:41194 so it listens on ALL IPs and interfaces. It is important to firewall this port appropriately. See above where this is done.

Copy the certificates you generated on the controller to the right place on the node:

$ cp ca.crt           /etc/pki/vpn-daemon/
$ cp vpn-daemon.crt   /etc/pki/vpn-daemon/server.crt
$ cp vpn-daemon.key   /etc/pki/vpn-daemon/private/server.key
$ chgrp -R vpn-daemon /etc/pki/vpn-daemon

Start the daemon and enable it on boot:

$ sudo systemctl enable --now vpn-daemon

Make sure vpn-daemon runs:

$ ps aux | grep vpn-daemon
vpn-dae+ 12680  0.0  1.3 211724 13596 ?        Ssl  11:09   0:00 /usr/bin/vpn-daemon -enable-tls -listen

If not, check the log, it probably has something to do with the certificates being unreadable:

$ journalctl -f -t vpn-daemon

Once the daemon runs, everything should work. Try to connect to the new profile using the eduVPN / Let's Connect! app or through the portal.