summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/templates/dhcp-relay/config.tmpl17
-rw-r--r--data/templates/dhcpv6-relay/config.tmpl4
-rw-r--r--data/templates/dhcpv6-server/daemon.tmpl8
-rw-r--r--data/templates/openvpn/server.conf.tmpl2
-rw-r--r--debian/vyos-1x.install1
-rw-r--r--interface-definitions/include/interface-hw-id.xml.i12
-rw-r--r--interface-definitions/interfaces-ethernet.xml.in13
-rw-r--r--interface-definitions/interfaces-wireless.xml.in13
-rwxr-xr-xsrc/conf_mode/dhcp_relay.py22
-rwxr-xr-xsrc/conf_mode/dhcp_server.py1
-rwxr-xr-xsrc/conf_mode/dhcpv6_relay.py15
-rwxr-xr-xsrc/conf_mode/dhcpv6_server.py38
-rwxr-xr-xsrc/conf_mode/interfaces-openvpn.py8
-rwxr-xr-xsrc/conf_mode/interfaces-tunnel.py6
-rwxr-xr-xsrc/conf_mode/interfaces-wireless.py2
-rwxr-xr-xsrc/etc/init.d/isc-dhcpv6-relay50
-rwxr-xr-xsrc/etc/init.d/isc-dhcpv6-server113
-rw-r--r--src/systemd/isc-dhcp-relay.service14
-rw-r--r--src/systemd/isc-dhcp-relay6.service14
-rw-r--r--src/systemd/isc-dhcp-server.service3
-rw-r--r--src/systemd/isc-dhcp-server6.service18
21 files changed, 114 insertions, 260 deletions
diff --git a/data/templates/dhcp-relay/config.tmpl b/data/templates/dhcp-relay/config.tmpl
index 7203ae9fb..b223807cf 100644
--- a/data/templates/dhcp-relay/config.tmpl
+++ b/data/templates/dhcp-relay/config.tmpl
@@ -1,17 +1,4 @@
### Autogenerated by dhcp_relay.py ###
-# Defaults for isc-dhcp-relay initscript
-# sourced by /etc/init.d/isc-dhcp-relay
-
-#
-# This is a POSIX shell fragment
-#
-
-# What servers should the DHCP relay forward requests to?
-SERVERS="{{ server | join(' ') }}"
-
-# On what interfaces should the DHCP relay (dhrelay) serve DHCP requests?
-INTERFACES="{{ interface | join(' ') }}"
-
-# Additional options that are passed to the DHCP relay daemon?
-OPTIONS="-4 {{ options | join(' ') }}"
+# Defaults for isc-dhcp-relay6.service
+OPTIONS="{{ options | join(' ') }} -i {{ interface | join(' -i ') }} {{ server | join(' ') }}"
diff --git a/data/templates/dhcpv6-relay/config.tmpl b/data/templates/dhcpv6-relay/config.tmpl
index 28f7a1a58..55035ae6c 100644
--- a/data/templates/dhcpv6-relay/config.tmpl
+++ b/data/templates/dhcpv6-relay/config.tmpl
@@ -1,4 +1,4 @@
### Autogenerated by dhcpv6_relay.py ###
-# Defaults for isc-dhcpv6-relay initscript sourced by /etc/init.d/isc-dhcpv6-relay
-OPTIONS="-6 -l {{ listen_addr | join(' -l ') }} -u {{ upstream_addr | join(' -u ') }} {{ options | join(' ') }}"
+# Defaults for isc-dhcp-relay6.service
+OPTIONS="-l {{ listen_addr | join(' -l ') }} -u {{ upstream_addr | join(' -u ') }} {{ options | join(' ') }}"
diff --git a/data/templates/dhcpv6-server/daemon.tmpl b/data/templates/dhcpv6-server/daemon.tmpl
deleted file mode 100644
index a4967e7c3..000000000
--- a/data/templates/dhcpv6-server/daemon.tmpl
+++ /dev/null
@@ -1,8 +0,0 @@
-### Autogenerated by dhcpv6_server.py ###
-
-# sourced by /etc/init.d/isc-dhcpv6-server
-
-DHCPD_CONF={{ config_file }}
-DHCPD_PID={{ pid_file }}
-OPTIONS="-6 -lf {{ lease_file }}"
-INTERFACES=""
diff --git a/data/templates/openvpn/server.conf.tmpl b/data/templates/openvpn/server.conf.tmpl
index 340ead269..c909f4337 100644
--- a/data/templates/openvpn/server.conf.tmpl
+++ b/data/templates/openvpn/server.conf.tmpl
@@ -85,7 +85,7 @@ max-clients {{ server_max_conn }}
{%- endif %}
{%- if client %}
-client-config-dir /opt/vyatta/etc/openvpn/ccd/{{ intf }}
+client-config-dir /run/openvpn/ccd/{{ intf }}
{%- endif %}
{%- if server_reject_unconfigured %}
diff --git a/debian/vyos-1x.install b/debian/vyos-1x.install
index 5004d111f..dd8eebc0b 100644
--- a/debian/vyos-1x.install
+++ b/debian/vyos-1x.install
@@ -1,5 +1,4 @@
etc/dhcp
-etc/init.d
etc/ppp
etc/rsyslog.d
etc/systemd
diff --git a/interface-definitions/include/interface-hw-id.xml.i b/interface-definitions/include/interface-hw-id.xml.i
new file mode 100644
index 000000000..cefc9f0a0
--- /dev/null
+++ b/interface-definitions/include/interface-hw-id.xml.i
@@ -0,0 +1,12 @@
+<leafNode name="mac">
+ <properties>
+ <help>Associate Ethernet Interface with given Media Access Control (MAC) address</help>
+ <valueHelp>
+ <format>h:h:h:h:h:h</format>
+ <description>Hardware Media Access Control (MAC) address</description>
+ </valueHelp>
+ <constraint>
+ <validator name="mac-address"/>
+ </constraint>
+ </properties>
+</leafNode>
diff --git a/interface-definitions/interfaces-ethernet.xml.in b/interface-definitions/interfaces-ethernet.xml.in
index f8ec26d04..89669f966 100644
--- a/interface-definitions/interfaces-ethernet.xml.in
+++ b/interface-definitions/interfaces-ethernet.xml.in
@@ -56,18 +56,7 @@
<constraintErrorMessage>duplex must be auto, half or full</constraintErrorMessage>
</properties>
</leafNode>
- <leafNode name="hw-id">
- <properties>
- <help>Media Access Control (MAC) address</help>
- <valueHelp>
- <format>h:h:h:h:h:h</format>
- <description>Hardware (MAC) address</description>
- </valueHelp>
- <constraint>
- <validator name="mac-address"/>
- </constraint>
- </properties>
- </leafNode>
+ #include <include/interface-hw-id.xml.i>
<node name="ip">
<children>
#include <include/interface-arp-cache-timeout.xml.i>
diff --git a/interface-definitions/interfaces-wireless.xml.in b/interface-definitions/interfaces-wireless.xml.in
index 194669f77..a5c6315fa 100644
--- a/interface-definitions/interfaces-wireless.xml.in
+++ b/interface-definitions/interfaces-wireless.xml.in
@@ -476,18 +476,7 @@
#include <include/ipv6-dup-addr-detect-transmits.xml.i>
</children>
</node>
- <leafNode name="hw-id">
- <properties>
- <help>Media Access Control (MAC) address</help>
- <valueHelp>
- <format>h:h:h:h:h:h</format>
- <description>Hardware (MAC) address</description>
- </valueHelp>
- <constraint>
- <validator name="mac-address"/>
- </constraint>
- </properties>
- </leafNode>
+ #include <include/interface-hw-id.xml.i>
<leafNode name="isolate-stations">
<properties>
<help>Isolate stations on the AP so they cannot see each other</help>
diff --git a/src/conf_mode/dhcp_relay.py b/src/conf_mode/dhcp_relay.py
index fdc8d2443..ce0e01308 100755
--- a/src/conf_mode/dhcp_relay.py
+++ b/src/conf_mode/dhcp_relay.py
@@ -19,11 +19,11 @@ import os
from sys import exit
from vyos.config import Config
-from vyos import ConfigError
-from vyos.util import call
from vyos.template import render
+from vyos.util import call
+from vyos import ConfigError
-config_file = r'/etc/default/isc-dhcp-relay'
+config_file = r'/run/dhcp-relay/dhcp.conf'
default_config_data = {
'interface': [],
@@ -95,19 +95,25 @@ def verify(relay):
def generate(relay):
# bail out early - looks like removal from running config
- if relay is None:
+ if not relay:
return None
+ # Create configuration directory on demand
+ dirname = os.path.dirname(config_file)
+ if not os.path.isdir(dirname):
+ os.mkdir(dirname)
+
render(config_file, 'dhcp-relay/config.tmpl', relay)
return None
def apply(relay):
- if relay is not None:
- call('sudo systemctl restart isc-dhcp-relay.service')
+ if relay:
+ call('systemctl restart isc-dhcp-relay.service')
else:
# DHCP relay support is removed in the commit
- call('sudo systemctl stop isc-dhcp-relay.service')
- os.unlink(config_file)
+ call('systemctl stop isc-dhcp-relay.service')
+ if os.path.exists(config_file):
+ os.unlink(config_file)
return None
diff --git a/src/conf_mode/dhcp_server.py b/src/conf_mode/dhcp_server.py
index 39f2921cd..da01f16eb 100755
--- a/src/conf_mode/dhcp_server.py
+++ b/src/conf_mode/dhcp_server.py
@@ -594,6 +594,7 @@ def generate(dhcp):
if not dhcp or dhcp['disabled']:
return None
+ # Create configuration directory on demand
dirname = os.path.dirname(config_file)
if not os.path.isdir(dirname):
os.mkdir(dirname)
diff --git a/src/conf_mode/dhcpv6_relay.py b/src/conf_mode/dhcpv6_relay.py
index 6544db055..cb5a4bbfb 100755
--- a/src/conf_mode/dhcpv6_relay.py
+++ b/src/conf_mode/dhcpv6_relay.py
@@ -24,8 +24,7 @@ from vyos import ConfigError
from vyos.util import call
from vyos.template import render
-
-config_file = r'/etc/default/isc-dhcpv6-relay'
+config_file = r'/run/dhcp-relay/dhcpv6.conf'
default_config_data = {
'listen_addr': [],
@@ -85,16 +84,22 @@ def generate(relay):
if relay is None:
return None
+ # Create configuration directory on demand
+ dirname = os.path.dirname(config_file)
+ if not os.path.isdir(dirname):
+ os.mkdir(dirname)
+
render(config_file, 'dhcpv6-relay/config.tmpl', relay)
return None
def apply(relay):
if relay is not None:
- call('sudo systemctl restart isc-dhcpv6-relay.service')
+ call('systemctl restart isc-dhcp-relay6.service')
else:
# DHCPv6 relay support is removed in the commit
- call('sudo systemctl stop isc-dhcpv6-relay.service')
- os.unlink(config_file)
+ call('systemctl stop isc-dhcp-relay6.service')
+ if os.path.exists(config_file):
+ os.unlink(config_file)
return None
diff --git a/src/conf_mode/dhcpv6_server.py b/src/conf_mode/dhcpv6_server.py
index a7807ed9f..94a307826 100755
--- a/src/conf_mode/dhcpv6_server.py
+++ b/src/conf_mode/dhcpv6_server.py
@@ -21,19 +21,14 @@ from sys import exit
from copy import deepcopy
from vyos.config import Config
+from vyos.template import render
+from vyos.util import call
from vyos.validate import is_subnet_connected
from vyos import ConfigError
-from vyos.util import call
-from vyos.template import render
-
-config_file = r'/etc/dhcp/dhcpdv6.conf'
-lease_file = r'/config/dhcpdv6.leases'
-pid_file = r'/var/run/dhcpdv6.pid'
-daemon_config_file = r'/etc/default/isc-dhcpv6-server'
+config_file = r'/run/dhcp-server/dhcpdv6.conf'
default_config_data = {
- 'lease_file': lease_file,
'preference': '',
'disabled': False,
'shared_network': []
@@ -221,10 +216,7 @@ def get_config():
return dhcpv6
def verify(dhcpv6):
- if dhcpv6 is None:
- return None
-
- if dhcpv6['disabled']:
+ if not dhcpv6 or dhcpv6['disabled']:
return None
# If DHCP is enabled we need one share-network
@@ -336,31 +328,25 @@ def verify(dhcpv6):
return None
def generate(dhcpv6):
- if dhcpv6 is None:
+ if not dhcpv6 or dhcpv6['disabled']:
return None
- if dhcpv6['disabled']:
- print('Warning: DHCPv6 server will be deactivated because it is disabled')
- return None
+ # Create configuration directory on demand
+ dirname = os.path.dirname(config_file)
+ if not os.path.isdir(dirname):
+ os.mkdir(dirname)
render(config_file, 'dhcpv6-server/dhcpdv6.conf.tmpl', dhcpv6)
- render(daemon_config_file, 'dhcpv6-server/daemon.tmpl', dhcpv6)
return None
def apply(dhcpv6):
- if (dhcpv6 is None) or dhcpv6['disabled']:
+ if not dhcpv6 or dhcpv6['disabled']:
# DHCP server is removed in the commit
- call('sudo systemctl stop isc-dhcpv6-server.service')
+ call('systemctl stop isc-dhcp-server6.service')
if os.path.exists(config_file):
os.unlink(config_file)
- if os.path.exists(daemon_config_file):
- os.unlink(daemon_config_file)
- else:
- # If our file holding DHCPv6 leases does yet not exist - create it
- if not os.path.exists(lease_file):
- os.mknod(lease_file)
- call('sudo systemctl restart isc-dhcpv6-server.service')
+ call('systemctl restart isc-dhcp-server6.service')
return None
diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py
index 85945ba58..66b96debe 100755
--- a/src/conf_mode/interfaces-openvpn.py
+++ b/src/conf_mode/interfaces-openvpn.py
@@ -666,10 +666,10 @@ def generate(openvpn):
directories = []
directories.append(f'{directory}/status')
directories.append(f'{directory}/ccd/{interface}')
- for directory in directories:
- if not os.path.exists(directory):
- os.makedirs(directory, 0o755)
- chown(directory, user, group)
+ for onedir in directories:
+ if not os.path.exists(onedir):
+ os.makedirs(onedir, 0o755)
+ chown(onedir, user, group)
# Fix file permissons for keys
fix_permissions = []
diff --git a/src/conf_mode/interfaces-tunnel.py b/src/conf_mode/interfaces-tunnel.py
index 19538da72..c51048aeb 100755
--- a/src/conf_mode/interfaces-tunnel.py
+++ b/src/conf_mode/interfaces-tunnel.py
@@ -584,11 +584,17 @@ def apply(conf):
if changes['section'] in 'create' and option in tunnel.options:
# it was setup at creation
continue
+ if not options[option]:
+ # remote can be set to '' and it would generate an invalide command
+ continue
tunnel.set_interface(option, options[option])
# set other interface properties
for option in ('alias', 'mtu', 'link_detect', 'multicast', 'allmulticast',
'vrf', 'ipv6_autoconf', 'ipv6_forwarding', 'ipv6_dad_transmits'):
+ if not options[option]:
+ # should never happen but better safe
+ continue
tunnel.set_interface(option, options[option])
# Configure interface address(es)
diff --git a/src/conf_mode/interfaces-wireless.py b/src/conf_mode/interfaces-wireless.py
index 10aec3dcd..498c24df0 100755
--- a/src/conf_mode/interfaces-wireless.py
+++ b/src/conf_mode/interfaces-wireless.py
@@ -609,7 +609,7 @@ def generate(wifi):
# Delete config files if interface is removed
if wifi['deleted']:
- if os.path.isfile(get_conf_file('hostapd', )):
+ if os.path.isfile(get_conf_file('hostapd', interface)):
os.unlink(get_conf_file('hostapd', interface))
if os.path.isfile(get_conf_file('wpa_supplicant', interface)):
diff --git a/src/etc/init.d/isc-dhcpv6-relay b/src/etc/init.d/isc-dhcpv6-relay
deleted file mode 100755
index e553eafd1..000000000
--- a/src/etc/init.d/isc-dhcpv6-relay
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/bin/sh
-#
-#
-
-### BEGIN INIT INFO
-# Provides: isc-dhcpv6-relay
-# Required-Start: $remote_fs $network
-# Required-Stop: $remote_fs $network
-# Should-Start: $local_fs
-# Should-Stop: $local_fs
-# Default-Start: 2 3 4 5
-# Default-Stop: 0 1 6
-# Short-Description: IPv6 DHCP relay
-# Description: Dynamic Host Configuration Protocol Relay for IPv6
-### END INIT INFO
-
-# It is not safe to start if we don't have a default configuration...
-if [ ! -f /etc/default/isc-dhcpv6-relay ]; then
- echo "/etc/default/isc-dhcpv6-relay does not exist! - Aborting..."
- exit 1
-fi
-
-# Source init functions
-. /lib/lsb/init-functions
-
-# Read init script configuration (interfaces the daemon should listen on
-# and the DHCP server we should forward requests to.)
-[ -f /etc/default/isc-dhcpv6-relay ] && . /etc/default/isc-dhcpv6-relay
-
-DHCRELAYPID=/var/run/dhcv6relay.pid
-
-case "$1" in
- start)
- start-stop-daemon --start --oknodo --quiet --pidfile $DHCRELAYPID \
- --exec /usr/sbin/dhcrelay -- -q $OPTIONS -pf $DHCRELAYPID
- ;;
- stop)
- start-stop-daemon --stop --oknodo --quiet --pidfile $DHCRELAYPID
- ;;
- restart | force-reload)
- $0 stop
- sleep 2
- $0 start
- ;;
- *)
- echo "Usage: /etc/init.d/isc-dhcpv6-relay {start|stop|restart|force-reload}"
- exit 1
-esac
-
-exit 0
diff --git a/src/etc/init.d/isc-dhcpv6-server b/src/etc/init.d/isc-dhcpv6-server
deleted file mode 100755
index f6b27cb4a..000000000
--- a/src/etc/init.d/isc-dhcpv6-server
+++ /dev/null
@@ -1,113 +0,0 @@
-#!/bin/sh
-#
-#
-
-### BEGIN INIT INFO
-# Provides: isc-dhcpv6-server
-# Required-Start: $remote_fs $network $syslog
-# Required-Stop: $remote_fs $network $syslog
-# Should-Start: $local_fs slapd $named
-# Should-Stop: $local_fs slapd
-# Default-Start: 2 3 4 5
-# Default-Stop: 0 1 6
-# Short-Description: IPv6 DHCP server
-# Description: Dynamic Host Configuration Protocol Server for IPv6
-### END INIT INFO
-
-PATH=/sbin:/bin:/usr/sbin:/usr/bin
-
-test -f /usr/sbin/dhcpd || exit 0
-
-DHCPD_DEFAULT="${DHCPD_DEFAULT:-/etc/default/isc-dhcpv6-server}"
-
-# It is not safe to start if we don't have a default configuration...
-if [ ! -f "$DHCPD_DEFAULT" ]; then
- echo "$DHCPD_DEFAULT does not exist! - Aborting..."
- exit 0
-fi
-
-. /lib/lsb/init-functions
-
-# Read init script configuration
-[ -f "$DHCPD_DEFAULT" ] && . "$DHCPD_DEFAULT"
-
-NAME=dhcpdv6
-DESC="ISC DHCP server IPv6"
-# fallback to default config file
-DHCPD_CONF=${DHCPD_CONF:-/etc/dhcp/dhcpdv6.conf}
-# try to read pid file name from config file, with fallback to /var/run/dhcpdv6.pid
-if [ -z "$DHCPD_PID" ]; then
- DHCPD_PID=$(sed -n -e 's/^[ \t]*pid-file-name[ \t]*"(.*)"[ \t]*;.*$/\1/p' < "$DHCPD_CONF" 2>/dev/null | head -n 1)
-fi
-DHCPD_PID="${DHCPD_PID:-/var/run/dhcpdv6.pid}"
-
-test_config()
-{
- if ! /usr/sbin/dhcpd -t $OPTIONS -q -cf "$DHCPD_CONF" > /dev/null 2>&1; then
- echo "dhcpd self-test failed. Please fix $DHCPD_CONF."
- echo "The error was: "
- /usr/sbin/dhcpd -t $OPTIONS -cf "$DHCPD_CONF"
- exit 1
- fi
- touch /var/lib/dhcp/dhcpdv6.leases
-}
-
-# single arg is -v for messages, -q for none
-check_status()
-{
- if [ ! -r "$DHCPD_PID" ]; then
- test "$1" != -v || echo "$NAME is not running."
- return 3
- fi
- if read pid < "$DHCPD_PID" && ps -p "$pid" > /dev/null 2>&1; then
- test "$1" != -v || echo "$NAME is running."
- return 0
- else
- test "$1" != -v || echo "$NAME is not running but $DHCPD_PID exists."
- return 1
- fi
-}
-
-case "$1" in
- start)
- test_config
- log_daemon_msg "Starting $DESC" "$NAME"
- start-stop-daemon --start --oknodo --quiet --pidfile "$DHCPD_PID" \
- --exec /usr/sbin/dhcpd -- \
- -q $OPTIONS -cf "$DHCPD_CONF" -pf "$DHCPD_PID" $INTERFACES
- sleep 2
-
- if check_status -q; then
- log_end_msg 0
- else
- log_failure_msg "check syslog for diagnostics."
- log_end_msg 1
- exit 1
- fi
- ;;
- stop)
- log_daemon_msg "Stopping $DESC" "$NAME"
- start-stop-daemon --stop --oknodo --quiet --pidfile "$DHCPD_PID"
- log_end_msg $?
- rm -f "$DHCPD_PID"
- ;;
- restart | force-reload)
- test_config
- $0 stop
- sleep 2
- $0 start
- if [ "$?" != "0" ]; then
- exit 1
- fi
- ;;
- status)
- echo -n "Status of $DESC: "
- check_status -v
- exit "$?"
- ;;
- *)
- echo "Usage: $0 {start|stop|restart|force-reload|status}"
- exit 1
-esac
-
-exit 0
diff --git a/src/systemd/isc-dhcp-relay.service b/src/systemd/isc-dhcp-relay.service
new file mode 100644
index 000000000..ebf4d234e
--- /dev/null
+++ b/src/systemd/isc-dhcp-relay.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=ISC DHCP IPv4 relay
+Documentation=man:dhcrelay(8)
+Wants=network-online.target
+ConditionPathExists=/run/dhcp-relay/dhcp.conf
+After=vyos-router.service
+
+[Service]
+WorkingDirectory=/run/dhcp-relay
+EnvironmentFile=/run/dhcp-relay/dhcp.conf
+ExecStart=/usr/sbin/dhcrelay -d -4 $OPTIONS
+
+[Install]
+WantedBy=multi-user.target
diff --git a/src/systemd/isc-dhcp-relay6.service b/src/systemd/isc-dhcp-relay6.service
new file mode 100644
index 000000000..a477618b1
--- /dev/null
+++ b/src/systemd/isc-dhcp-relay6.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=ISC DHCP IPv6 relay
+Documentation=man:dhcrelay(8)
+Wants=network-online.target
+ConditionPathExists=/run/dhcp-relay/dhcpv6.conf
+After=vyos-router.service
+
+[Service]
+WorkingDirectory=/run/dhcp-relay
+EnvironmentFile=/run/dhcp-relay/dhcpv6.conf
+ExecStart=/usr/sbin/dhcrelay -d -6 $OPTIONS
+
+[Install]
+WantedBy=multi-user.target
diff --git a/src/systemd/isc-dhcp-server.service b/src/systemd/isc-dhcp-server.service
index 4c3cb9920..d848e3df1 100644
--- a/src/systemd/isc-dhcp-server.service
+++ b/src/systemd/isc-dhcp-server.service
@@ -1,10 +1,9 @@
[Unit]
Description=ISC DHCP IPv4 server
Documentation=man:dhcpd(8)
-After=vyos-router.service
RequiresMountsFor=/run
-After=time-sync.target
ConditionPathExists=/run/dhcp-server/dhcpd.conf
+After=vyos-router.service
[Service]
WorkingDirectory=/run/dhcp-server
diff --git a/src/systemd/isc-dhcp-server6.service b/src/systemd/isc-dhcp-server6.service
new file mode 100644
index 000000000..743f16840
--- /dev/null
+++ b/src/systemd/isc-dhcp-server6.service
@@ -0,0 +1,18 @@
+[Unit]
+Description=ISC DHCP IPv6 server
+Documentation=man:dhcpd(8)
+RequiresMountsFor=/run
+ConditionPathExists=/run/dhcp-server/dhcpd.conf
+After=vyos-router.service
+
+[Service]
+WorkingDirectory=/run/dhcp-server
+# The leases files need to be root:vyattacfg even when dropping privileges
+ExecStart=/bin/sh -ec '\
+ [ -e /config/dhcpdv6.leases ] || touch /config/dhcpdv6.leases; \
+ chown root:vyattacfg /config/dhcpdv6.leases; \
+ chmod 664 /config/dhcpdv6.leases; \
+ exec /usr/sbin/dhcpd -user nobody -group nogroup -f -6 -pf /run/dhcp-server/dhcpdv6.pid -cf /run/dhcp-server/dhcpdv6.conf -lf /config/dhcpdv6.leases'
+
+[Install]
+WantedBy=multi-user.target