In this last step, we will not create a startup to offer OpenVPN as a service for merely $50 per day. Instead, we will create a service unit to easily manage our openvpn. The startup thing is left as an exercise for the reader.

Configuration directory

As a reminder, let’s take a look to our current configuration directory:

_$: tree /etc/openvpn
.
├── ca
│   ├── build-ca -> /usr/share/easy-rsa/build-ca
│   ├── build-dh -> /usr/share/easy-rsa/build-dh
│   ├── build-inter -> /usr/share/easy-rsa/build-inter
│   ├── build-key -> /usr/share/easy-rsa/build-key
│   ├── build-key-pass -> /usr/share/easy-rsa/build-key-pass
│   ├── build-key-pkcs12 -> /usr/share/easy-rsa/build-key-pkcs12
│   ├── build-key-server -> /usr/share/easy-rsa/build-key-server
│   ├── build-req -> /usr/share/easy-rsa/build-req
│   ├── build-req-pass -> /usr/share/easy-rsa/build-req-pass
│   ├── clean-all -> /usr/share/easy-rsa/clean-all
│   ├── inherit-inter -> /usr/share/easy-rsa/inherit-inter
│   ├── keys
│   │   ├── 01.pem
│   │   ├── 02.pem
│   │   ├── 03.pem
│   │   ├── ca.crt
│   │   ├── ca.key
│   │   ├── desktop.dcere.com.crt
│   │   ├── desktop.dcere.com.csr
│   │   ├── desktop.dcere.com.key
│   │   ├── dh2048.pem
│   │   ├── index.txt
│   │   ├── index.txt.attr
│   │   ├── index.txt.attr.old
│   │   ├── index.txt.old
│   │   ├── serial
│   │   ├── serial.old
│   │   ├── server.dcere.com.crt
│   │   ├── server.dcere.com.csr
│   │   ├── server.dcere.com.key
│   │   ├── smartphone.dcere.com.crt
│   │   ├── smartphone.dcere.com.csr
│   │   ├── smartphone.dcere.com.key
│   │   └── ta.key
│   ├── list-crl -> /usr/share/easy-rsa/list-crl
│   ├── openssl-0.9.6.cnf
│   ├── openssl-0.9.8.cnf
│   ├── openssl-1.0.0.cnf
│   ├── pkitool -> /usr/share/easy-rsa/pkitool
│   ├── revoke-full -> /usr/share/easy-rsa/revoke-full
│   ├── sign-req -> /usr/share/easy-rsa/sign-req
│   ├── vars
│   └── whichopensslcnf -> /usr/share/easy-rsa/whichopensslcnf
├── certs
│   └── static.key
├── client
├── proxy-certs.conf
├── proxy-p2p.conf
└── server
    ├── ca.crt
    ├── dh2048.pem
    ├── server.dcere.com.crt
    ├── server.dcere.com.key
    └── ta.key

Create the service unit

Let’s start by copying the default service provided for Ubuntu:

_$: cd /lib/systemd/system
_$: cp openvpn@service openvpn@certs.service

With our configuration directory in mind, we will modify it to suit our needs. Take into account that this file is not expected to change very much, so it is fine to have hard-coded arguments.

/lib/systemd/system/openvpn@certs.service:
------------------------------------------
[Unit]
Description=OpenVPN connection with certs
PartOf=openvpn.service
ReloadPropagatedFrom=openvpn.service
Before=systemd-user-sessions.service
Documentation=man:openvpn(8)
Documentation=https://community.openvpn.net/openvpn/wiki/Openvpn23ManPage
Documentation=https://community.openvpn.net/openvpn/wiki/HOWTO

[Service]
PrivateTmp=true
KillMode=mixed
Type=forking
ExecStart=/usr/sbin/openvpn --daemon ovpn-certs --status /run/openvpn/certs.status 10 --cd /etc/openvpn --config /etc/openvpn/proxy-certs.conf --writepid /run/openvpn/certs.pid
PIDFile=/run/openvpn/certs.pid
ExecReload=/bin/kill -HUP $MAINPID
WorkingDirectory=/etc/openvpn
ProtectSystem=yes
CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_READ_SEARCH CAP_AUDIT_WRITE
LimitNPROC=10
DeviceAllow=/dev/null rw
DeviceAllow=/dev/net/tun rw

[Install]
WantedBy=multi-user.target

Enable the service

_$: systemctl enable openvpn@certs.service
Created symlink from /etc/systemd/system/multi-user.target.wants/openvpn@certs.service to /lib/systemd/system/openvpn@certs.service.

_$: systemctl start openvpn@certs.service

_$: systemctl status openvpn@certs.service
● openvpn@certs.service - OpenVPN connection with certs
   Loaded: loaded (/lib/systemd/system/openvpn@certs.service; enabled; vendor p
   Active: active (running) since Tue 2018-01-09 23:13:07 CET; 46s ago
     Docs: man:openvpn(8)
           https://community.openvpn.net/openvpn/wiki/Openvpn23ManPage
           https://community.openvpn.net/openvpn/wiki/HOWTO
  Process: 2216 ExecStart=/usr/sbin/openvpn --daemon ovpn-certs --status /run/o
 Main PID: 2217 (openvpn)
   CGroup: /system.slice/system-openvpn.slice/openvpn@certs.service
           └─2217 /usr/sbin/openvpn --daemon ovpn-certs --status /run/openvpn/c

Jan 09 23:13:07 <server> ovpn-certs[2217]: /sbin/ip link set dev tun0 up mtu 1500
Jan 09 23:13:07 <server> ovpn-certs[2217]: /sbin/ip addr add dev tun0 local 10.200.
Jan 09 23:13:07 <server> ovpn-certs[2217]: UDPv4 link local (bound): [undef]
Jan 09 23:13:07 <server> ovpn-certs[2217]: UDPv4 link remote: [undef]
Jan 09 23:13:07 <server> ovpn-certs[2217]: Initialization Sequence Completed

[...]