Skip to contentSkip to conversation

Use systemd service manager notification

PATCH In review Christian Hesse 4 participants 6 messages Dec 1, 2016 – Dec 2, 2016

lore
Share & tools
lore
#0 lore raw

PATCH v3 1/2 Use systemd service manager notification

From: Christian Hesse <[email protected]...>

Notify systemd service manager when our initialization sequence completed. This helps ordering services as dependencies can rely on vpn being available.

v2: Add curly brackets (and indention) to block the else-part, msg()
call was non-conditional before.

v3: Move systemd header include from init.h to init.c.

---
 distro/systemd/[email protected]... |  1 +
 distro/systemd/[email protected]... |  1 +
 src/openvpn/init.c                     | 14 +++++++++++++-
 3 files changed, 15 insertions(+), 1 deletion(-)
distro/systemd/[email protected]... +1 -0
index 18b84dd..f64a239 100644
@@ -7,6 +7,7 @@ Documentation=https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage
 Documentation=https://community.openvpn.net/openvpn/wiki/HOWTO
 
 [Service]
+Type=notify
 PrivateTmp=true
 RuntimeDirectory=openvpn-client
 RuntimeDirectoryMode=0710
distro/systemd/[email protected]... +1 -0
index a2b7b52..890e6a9 100644
@@ -7,6 +7,7 @@ Documentation=https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage
 Documentation=https://community.openvpn.net/openvpn/wiki/HOWTO
 
 [Service]
+Type=notify
 PrivateTmp=true
 RuntimeDirectory=openvpn-server
 RuntimeDirectoryMode=0710
src/openvpn/init.c +13 -1
index 2ccbab2..f99c934 100644
@@ -30,6 +30,10 @@
 
 #include "syshead.h"
 
+#ifdef ENABLE_SYSTEMD
+#include <systemd/sd-daemon.h>
+#endif
+
 #include "win32.h"
 #include "init.h"
 #include "sig.h"
@@ -1251,11 +1255,19 @@ initialization_sequence_completed (struct context *c, const unsigned int flags)
       show_adapters (M_INFO|M_NOPREFIX);
       msg (M_INFO, "%s With Errors ( see http://openvpn.net/faq.html#dhcpclientserv )", message);
 #else
+#ifdef ENABLE_SYSTEMD
+      sd_notifyf(0, "STATUS=Failed to start up: %s With Errors\nERRNO=1", message);
+#endif /* HAVE_SYSTEMD_SD_DAEMON_H */
       msg (M_INFO, "%s With Errors", message);
 #endif
     }
   else
-    msg (M_INFO, "%s", message);
+    {
+#ifdef ENABLE_SYSTEMD
+      sd_notifyf(0, "READY=1\nSTATUS=%s\nMAINPID=%lu", message, (unsigned long) getpid());
+#endif
+      msg (M_INFO, "%s", message);
+    }
 
   /* Flag that we initialized */
   if ((flags & (ISC_ERRORS|ISC_SERVER)) == 0)
Signature · 1 line
2.10.2
#1 lore raw

PATCH v2 2/2 Refuse to daemonize when running from systemd

From: Christian Hesse <[email protected]...>

We start with systemd Type=notify, so refuse to daemonize. This does not affect starting openvpn from script or command line.

v2: Update commit message about script and command line.

---
 distro/systemd/[email protected]... | 1 -
 distro/systemd/[email protected]... | 1 -
 src/openvpn/init.c                     | 7 +++++++
 3 files changed, 7 insertions(+), 2 deletions(-)
distro/systemd/[email protected]... +0 -1
index f64a239..5618af3 100644
@@ -12,7 +12,6 @@ PrivateTmp=true
 RuntimeDirectory=openvpn-client
 RuntimeDirectoryMode=0710
 WorkingDirectory=/etc/openvpn/client
-ExecStartPre=/bin/sh -c 'grep -q -E ^daemon %i.conf || exit 0 && /usr/bin/echo "OpenVPN configuration cannot contain --daemon when being managed by systemd" ; exit 1'
 ExecStart=/usr/sbin/openvpn --suppress-timestamps --nobind --config %i.conf
 CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_OVERRIDE
 LimitNPROC=10
distro/systemd/[email protected]... +0 -1
index 890e6a9..b9b4dba 100644
@@ -12,7 +12,6 @@ PrivateTmp=true
 RuntimeDirectory=openvpn-server
 RuntimeDirectoryMode=0710
 WorkingDirectory=/etc/openvpn/server
-ExecStartPre=/bin/sh -c 'grep -q -E ^daemon %i.conf || exit 0 && /usr/bin/echo "OpenVPN configuration cannot contain --daemon when being managed by systemd" ; exit 1'
 ExecStart=/usr/sbin/openvpn --status %t/openvpn-server/status-%i.log --status-version 2 --suppress-timestamps --config %i.conf
 CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_OVERRIDE
 LimitNPROC=10
src/openvpn/init.c +7 -0
index f99c934..74f1139 100644
@@ -930,6 +930,13 @@ bool
 possibly_become_daemon (const struct options *options)
 {
   bool ret = false;
+
+#ifdef ENABLE_SYSTEMD
+  /* return without forking if we are running from systemd */
+  if (sd_notify(0, "READY=0") > 0)
+    return ret;
+#endif
+
   if (options->daemon)
     {
       ASSERT (!options->inetd);
Signature · 1 line
2.10.2
#2 lore raw

Re: [Openvpn-devel] [PATCH applied] Refuse to daemonize when running from systemd

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

ACK. A natural continuation of commit c5931897ae8d663e7e.

Your patch has been applied to the master branch

commit 7660bba111f739f9cc7017c392c1434f201b8c44

Author: Christian Hesse
Date:   Thu Dec 1 22:31:04 2016 +0100
     Refuse to daemonize when running from systemd

     Signed-off-by: Christian Hesse <[email protected]...>
     Tested-By: Richard Bonhomme <[email protected]...>
     Acked-by: David Sommerseth <[email protected]...>
     Message-Id: <[email protected]...>
     URL: http://www.mail-archive.com/search?l=mid&[email protected]...
     Signed-off-by: David Sommerseth <[email protected]...>

- --
kind regards,

David Sommerseth

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.22 (GNU/Linux)

iQIcBAEBAgAGBQJYQLJIAAoJEIbPlEyWcf3yMKgQAJapsRNhfkI1+WSaRP2PoVh/ scQQxFEV8HPHOASDtFZQZnaz3ZqkQ0yA+Zyn5w+KRefEIKGJ7/B8AWV5MfmtqPXS d4TTbUXMziK+E4cJpcZukWm/r5eEjIfy6ZhNe+fopq3zMt/JtbJD9nbBjVOe+KiK Kml60oUEP/vDmHKqQYJr69Z+9zgPC9W+etDY6MW6fyoo5O93G+OSenAeG2PJa3IZ JsHOlcaYNIjrUKMZoxeiGKgqaU7aoTqHq/5l83cy7mayI8w3F6tOhYaH02NhVn15 PZ8BDJAG9Dl67/ROll9HO1HaoUegcpAR3lEXWAeRV7TaEn5x9W9HrmDJiWcuWZhj BbvlqMmC0ocQyODul+6NFXWPX9+BmiReDGh+R6g+7H/ZhC01c4kyqBF+xne0DkSY YnEs5ZMkxyY3ItrnUrQGiywayvDIsa0+DNv7jTRnVRy8bfnkKW0grOzDFQvyKqWR K0rwBVOuKNqeRh6vhFSYNjfMIfcvkONMZKPlLjjHHIWzYr8eapxff6Ozw36UVXfI 1AGQ0bSChAjwufD9y6Xy+LDf+GtQI4kWkRjjjnXP/n01fYSLBJSGnLBWC3V+JUV1 JPT4GtD5cPAjxU3alGyrUMw4f18zXoqvlP82Kt+ViMneRwJkffxpOFWG7tD5MKYb 73a0O3IBgkb+SZRjFB4J
=xSqP
-----END PGP SIGNATURE-----

#3 lore raw

Re: [Openvpn-devel] [PATCH v2 2/2] Refuse to daemonize when running from systemd

In reply to Christian Hesse

Gutted ..

I have to step in here NOW and say that this did not work for me.

I applied to the current (as of this email) git master:

* Use systemd service manager notification
* The patch below
* No others.

-----

then

$ autoreconf -ivf
$ ./configure --enable-systemd
$ make
# make uninstall
# make install

I then used the systemd unit from
b/src/distro/systemd/[email protected]...
copied and renamed to my conf file as
/etc/systemd/system/[email protected]...

systemctl'd to the correct unit file:

# ls -l /etc/systemd/system/multi-user.target.wants
total ..
lrwxrwxrwx 1 root root 47 Dec  1 15:56 [email protected]... -> /etc/systemd/system/[email protected]...

changed the unit file as below:

# cat /etc/systemd/system/[email protected]...
[Unit]
Description=OpenVPN service for %I
After=syslog.target network-online.target
Wants=network-online.target
Documentation=man:openvpn(8)
Documentation=https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage
Documentation=https://community.openvpn.net/openvpn/wiki/HOWTO

[Service]
Type=notify
PrivateTmp=true
RuntimeDirectory=openvpn-server
RuntimeDirectoryMode=0710
WorkingDirectory=/etc/openvpn/server

# Not using 2.3.x
#ExecStart=/usr/sbin/openvpn --status %t/openvpn-server/status-%i.log --status-version 2 --suppress-timestamps --config %i.conf # Do not like --supress-timestamps
#ExecStart=/usr/local/sbin/openvpn --status %t/openvpn-server/status-%i.log --status-version 2 --suppress-timestamps --config %i.conf # Using this
ExecStart=/usr/local/sbin/openvpn --status %t/openvpn-server/status-%i.log --status-version 2 --config %i.conf CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_OVERRIDE LimitNPROC=10
DeviceAllow=/dev/null rw
DeviceAllow=/dev/net/tun rw

[Install]
WantedBy=multi-user.target

My east.conf file:

# cat server/east.conf

### TESTS
#
## systemd enhancements: failed as expect
;bad-opt

## daemon: Did *not* fail when run from systemd service daemon vpn-srv-east

                 server 10.25.25.0 255.255.255.248

server-ipv6 12fc:1918::10:25:25:0:0/112

push "setenv-safe PUSH_east arch"

keepalive 10 30
push "comp-lzo no"
comp-lzo no
push "explicit-exit-notify 3"
client-config-dir /etc/openvpn/server/east/ccd
ccd-exclusive

log /etc/openvpn/server/east/temp/east.log
verb 4

management 127.0.0.1 10025
dev tun25s
port 10025
cipher AES-256-CBC
auth RSA-SHA512

# cert/key stuff
...

Then:

# systemctl daemon-reload
# systemctl start [email protected]...

** Openvpn started but should have failed **

Just for the hell of it

# nano b/src/openvpn/init.c

/*
* Should we become a daemon?
* Return true if we did it.
*/
bool
possibly_become_daemon (const struct options *options) {
bool ret = false;

#ifdef ENABLE_SYSTEMD
/* return without forking if we are running from systemd */ if (sd_notify(0, "READY=0") > 0)

    return ret;

#endif

if (options->daemon)

    {
      ASSERT (!options->inetd);
      /* Don't chdir immediately, but the end of the init sequence, if 
needed */
      if (daemon (1, options->log) < 0)
        msg (M_ERR, "daemon() failed or unsupported");
      restore_signal_state ();
      if (options->log)
                                [ line 921/4014 (22%), col 1/3 (33%), 

char 22889/106307 (21%) ]

-----

I have probably done something wrong but could not sleep without letting someone know!

Regards

Quoted 57 lines · Christian Hesse

From: Christian Hesse <[email protected]...>

We start with systemd Type=notify, so refuse to daemonize. This does not affect starting openvpn from script or command line.

v2: Update commit message about script and command line.

---
 distro/systemd/[email protected]... | 1 -
 distro/systemd/[email protected]... | 1 -
 src/openvpn/init.c                     | 7 +++++++
 3 files changed, 7 insertions(+), 2 deletions(-)
distro/systemd/[email protected]... +0 -1
index f64a239..5618af3 100644
@@ -12,7 +12,6 @@ PrivateTmp=true
 RuntimeDirectory=openvpn-client
 RuntimeDirectoryMode=0710
 WorkingDirectory=/etc/openvpn/client
-ExecStartPre=/bin/sh -c 'grep -q -E ^daemon %i.conf || exit 0 && /usr/bin/echo "OpenVPN configuration cannot contain --daemon when being managed by systemd" ; exit 1'
 ExecStart=/usr/sbin/openvpn --suppress-timestamps --nobind --config %i.conf
 CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_OVERRIDE
 LimitNPROC=10
distro/systemd/[email protected]... +0 -1
index 890e6a9..b9b4dba 100644
@@ -12,7 +12,6 @@ PrivateTmp=true
 RuntimeDirectory=openvpn-server
 RuntimeDirectoryMode=0710
 WorkingDirectory=/etc/openvpn/server
-ExecStartPre=/bin/sh -c 'grep -q -E ^daemon %i.conf || exit 0 && /usr/bin/echo "OpenVPN configuration cannot contain --daemon when being managed by systemd" ; exit 1'
 ExecStart=/usr/sbin/openvpn --status %t/openvpn-server/status-%i.log --status-version 2 --suppress-timestamps --config %i.conf
 CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_OVERRIDE
 LimitNPROC=10
src/openvpn/init.c +7 -0
index f99c934..74f1139 100644
@@ -930,6 +930,13 @@ bool
 possibly_become_daemon (const struct options *options)
 {
   bool ret = false;
+
+#ifdef ENABLE_SYSTEMD
+  /* return without forking if we are running from systemd */
+  if (sd_notify(0, "READY=0") > 0)
+    return ret;
+#endif
+
   if (options->daemon)
     {
       ASSERT (!options->inetd);
#4 lore raw

Re: [Openvpn-devel] [PATCH v2 2/2] Refuse to daemonize when running from systemd

On 02/12/16 02:45, debbie10t wrote:
[...snip...]

Quoted 11 lines

My east.conf file:

# cat server/east.conf

### TESTS
#
## systemd enhancements: failed as expect
;bad-opt

## daemon: Did *not* fail when run from systemd service daemon vpn-srv-east

This is just as expected. Having --daemon in the config should not cause any failure. It should just drop trying to daemonize if it is detected that OpenVPN is started via systemd.

Look at init.c:930, possibly_become_daemon()

If sd_notify() returns a value > 0, then OpenVPN is started via systemctl - as sd_notify() have a communication channel with the service manager, and it will not try to daemonize.

If sd_notify() returns 0, it means it don't know how to communicate with the service manager. And < 0, it means something bad happened. In both these cases, openvpn will daemonize as if it was not managed by systemd at all.

So your test showed that this worked just as expected :)

Signature · 4 lines
kind regards,

David Sommerseth
OpenVPN Technologies, Inc
#5 lore raw
In reply to Christian Hesse

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

ACK. Code looks good and does what it promises. This also improved the situation where OpenVPN needs username/passwords from the console. So this is indeed a far better solution.

The patch got also fairly good testing on a relatively short time, across multiple systemd based distributions, client and server profiles, even some configurations with explicit errors.

Your patch has been applied to the master branch

commit c5931897ae8d663e7e6244764fc6379d7b4740f3

Author: Christian Hesse
Date:   Thu Dec 1 22:31:03 2016 +0100
     Use systemd service manager notification

     Signed-off-by: Christian Hesse <[email protected]...>
     Tested-By: Richard Bonhomme <[email protected]...>
     Acked-by: David Sommerseth <[email protected]...>
     Message-Id: <[email protected]...>
     URL: http://www.mail-archive.com/search?l=mid&[email protected]...
     Signed-off-by: David Sommerseth <[email protected]...>

- --
kind regards,

David Sommerseth

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.22 (GNU/Linux)

iQIcBAEBAgAGBQJYQLHEAAoJEIbPlEyWcf3y/gUQAJwqRYi5s0QcMyBhsdY3gRVd kzU+OXiDXZtO/QgMN45rWpdZxAkp2IUxe3tFDEdQjzPsdcCRWL41l9dZcIxAuNEb MHsv33/QUsH90svWGdhVH/nTf2ySR0rS3rLCuBCrwDfdm3mC7kQN7wsjaSRGcUIC AdL5eAbDzrIntDJKXtN+m78lgpZ9zng2w2FHsizJcD2zLsjjSJgJNSO4fIyXs0D8 GZ/W1Ex1d4eMficWHKH6CYmj0dX0c6010X5lVdmT/d25TofahQBPReha0ej3jpAo 5dHtel4nGw+m5ooBa7tOnC5bWp8K7RAr8Vau6+sMhy9LabNZ5BY5Z0cBi/p0ViXx hzlVFBCiVuXtEZhz9yHEp/uNbvnUNBfqzauyFmz7Obyyog3HWx7p5IM8LC7CNZF8 sL3wdSzxp7JFQrKl5vQb1MRAmmQZc/+DClLOxtdxX7bj3nc2wiP6C1iLoe+BvEZA 9tJIyfkh7oxM2Ec0Lt1yC7zMh+rknC5H6MffuvaapG7Xmc5iGekRJzWDZgZPtoJB wreksV4OYUhFRogMMCCKHzfuCuIf3alLOocExNjUFHnAFJwFw+hq0r9YABbWtZ+c FcePeavHusz0afAqyiAmEuQo6dxWN6Nq+lgDWV9SKrulRX0k7DB3/PgE2OfY3UEL WaF1Gx2wZ0ur3SRZIrRA
=Y46U
-----END PGP SIGNATURE-----