From 4905226d3cf1a8649152516b1cea5ba226a9714c Mon Sep 17 00:00:00 2001 From: Tomas Krizek Date: Thu, 25 Jan 2018 18:17:09 +0100 Subject: [PATCH] systemd: enable multiple processes with socket activation In order to be able to spawn multiple processes with socket activation, systemd template (see systemd.unit(5)) is used. This allows the user to create any amount of instances by simply providing a unique name for each of them. The most sensible instance identifiers are natural numbers, but any convention could be used. The default recommended service name becomes kresd@1.service, replacing the older kresd.service. Sockets are renamed in a similar way. Users are able to take advantage of bash expansion to spawn/control multiple processes, e.g. "systemctl start kresd@{1..16}.service" The socket-activated service can now be launched directly with "systemctl start kresd@1.service", which will request the associated sockets without the need for any extra priviledges or capabilities. Stopping the kresd service now also stops the associated sockets. Stopping any individual socket is an isolated opration now (stopping kresd@1.socket no longer stop kresd-tls@1.socket and kresd-control@1.socket). Users and packagers are also encouraged to use drop-in files for extra configuration or modifications to ensure compatibility with their distribution. --- daemon/README.rst | 2 + doc/kresd.8.in | 4 +- doc/kresd.systemd.8 | 148 ++++++++++++++++++ systemd/90-kresd.preset | 2 +- systemd/README.md | 47 +++--- systemd/drop-in/listen-tls.conf | 7 + systemd/drop-in/listen-udp-tcp.conf | 8 + systemd/drop-in/manual-activation.conf | 7 + systemd/drop-in/systemd-compat.conf | 6 + ...d-control.socket => kresd-control@.socket} | 7 +- systemd/kresd-control@1.socket | 1 + .../{kresd-tls.socket => kresd-tls@.socket} | 10 +- systemd/kresd-tls@1.socket | 1 + systemd/{kresd.service => kresd@.service} | 6 +- systemd/{kresd.socket => kresd@.socket} | 10 +- systemd/kresd@1.socket | 1 + 16 files changed, 224 insertions(+), 43 deletions(-) create mode 100644 doc/kresd.systemd.8 create mode 100644 systemd/drop-in/listen-tls.conf create mode 100644 systemd/drop-in/listen-udp-tcp.conf create mode 100644 systemd/drop-in/manual-activation.conf create mode 100644 systemd/drop-in/systemd-compat.conf rename systemd/{kresd-control.socket => kresd-control@.socket} (61%) create mode 120000 systemd/kresd-control@1.socket rename systemd/{kresd-tls.socket => kresd-tls@.socket} (57%) create mode 120000 systemd/kresd-tls@1.socket rename systemd/{kresd.service => kresd@.service} (63%) rename systemd/{kresd.socket => kresd@.socket} (80%) create mode 120000 systemd/kresd@1.socket diff --git a/daemon/README.rst b/daemon/README.rst index 902e8ac3c..649f1d686 100644 --- a/daemon/README.rst +++ b/daemon/README.rst @@ -1012,6 +1012,8 @@ The watchdog process must notify kresd about active file descriptors, and kresd The daemon also supports `systemd socket activation`_, it is automatically detected and requires no configuration on users's side. +See ``kresd.systemd(8)`` for details. + Enabling DNSSEC =============== diff --git a/doc/kresd.8.in b/doc/kresd.8.in index eb42bbdd0..fb4784ee4 100644 --- a/doc/kresd.8.in +++ b/doc/kresd.8.in @@ -88,7 +88,7 @@ online documentation. .PP .nf .RS 6n -# Create a basic forwarder configuration +# Create a basic forwarder configuration $ cat << EOF > config modules = { 'policy' } policy.add(policy.all(policy.FORWARD('192.168.1.1'))) @@ -164,7 +164,7 @@ Show short commandline option help. .B \-V Show the version. .SH "SEE ALSO" -\fIdaemon/README.md\fR, +\fIkresd.systemd(8)\fR, \fIhttps://knot-resolver.readthedocs.io\fR .SH "AUTHORS" .B kresd diff --git a/doc/kresd.systemd.8 b/doc/kresd.systemd.8 new file mode 100644 index 000000000..0eca9805e --- /dev/null +++ b/doc/kresd.systemd.8 @@ -0,0 +1,148 @@ +.TH "kresd.systemd" "8" "2018-01-30" "CZ.NIC" "Knot DNS Resolver Systemd Units" +.\" +.\" kresd.systemd.8 -- man page for systemd units for kresd +.\" +.\" Copyright (c) 2018, CZ.NIC. All rights reserved. +.\" +.\" See COPYING for the license. +.\" +.\" +.SH "NAME" +kresd.systemd +\- managing Knot DNS Resolver through systemd. + +.SH "SYNOPSIS" +.nf +kresd@.service +kresd@.socket +kresd-tls@.socket +kresd-control@.socket +.fi + +.SH "DESCRIPTION" +.P +This manual page describes how to manage \fBkresd\fR using \fBsystemd\fR +units. Depending on your distribution, this can be either be done with +socket-based activation or without it. The following assumes socket-based activation. +For differences see \fINOTES\fR below. + +\fBkresd\fR daemon can be executed in multiple independent processes, which can be +managed with \fBsystemd\fR via systemd templates (see \fBsystemd.unit\fR(5)). +Each \fBsystemd\fR service instance of \fBkresd\fR (\fIkresd@.service\fR) represents a +single, independent kresd process. + +Each instance of \fIkresd@.service\fR has three systemd sockets (see +\fBsystemd.socket(5)\fR) associated with it: + +.nf +.RS +\fIkresd@.socket\fR - UDP/TCP network socket (default: localhost:53) +\fIkresd-tls@.socket\fR - network socket for DNS-over-TLS (default: localhost:853) +\fIkresd-control@.socket\fR - UNIX socket with control terminal +.RE +.fi + +.B Configuring network interfaces + +When using socket-based activation, the daemon doesn't require root privileges +nor any capabilities, because the sockets are created by \fBsystemd\fR and +passed to \fBkresd\fR. This means \fBkresd\fR can't bind to ports below 1024 when +configured in \fI/etc/knot-resolver/kresd.conf\fR. + +To configure \fBkresd\fR to listen on public interfaces, drop-in files (see +\fBsystemd.unit\fR(5)) should be used. These can be created with: + +.nf +.RS 4n +.B systemctl edit kresd@.socket +.B systemctl edit kresd-tls@.socket +.RE +.fi + +For example, to configure \fBkresd\fR to listen on 192.0.2.115 on ports 53 and +853, the drop-in files would look like: + +.nf +.RS 4n +# /etc/systemd/system/kresd@.socket.d/override.conf +[Socket] +ListenDatagram=192.0.2.115:53 +ListenStream=192.0.2.115:53 + +# /etc/systemd/system/kresd-tls@.socket.d/override.conf +[Socket] +ListenStream=192.0.2.115:853 +.RE +.fi + +.SH "NOTES" + +.IP * 2 +When \fIkresd@.service\fR is started, stopped or restarted, its associated +sockets are also automatically started, stopped or restarted. + +.IP * 2 +If your distribution doesn't use socket-based activation, you can configure the +network interfaces for \fBkresd\fR in \fI/etc/knot-resolver/kresd.conf\fR. The +service can be started or enabled in the same way as in the examples below, but +it doesn't have any sockets associated with it. + +.SH "EXAMPLES" + +.B Single instance +.RS 4n + +To start the service: +.nf +.RS 4n +.B systemctl start kresd@1.service +.RE +.fi + +To start the service at boot: +.nf +.RS 4n +.B systemctl enable kresd@1.service +.RE +.fi + +To delay the service startup until some traffic arrives, start (or enable) just +the sockets: +.nf +.RS 4n +.B systemctl start kresd@1.socket +.B systemctl start kresd-tls@1.socket +.RE +.fi + +To disable the TLS socket, you can mask it: + +.RS 4n +.B systemctl mask kresd-tls@1.socket +.RE + +.RE + +.B Multiple instances +.RS 4n + +Multiple instances can be handled with the use of \fIBrace Expansion\fR (see +\fBbash\fR(1)). + +To start multiple instances, for example 16: +.nf +.RS +.B systemctl start kresd@{1..16}.service +.RE +.fi + +.RE + +.SH "SEE ALSO" +\fIkresd(8)\fR, +\fIsystemd.unit(5)\fR, +\fIsystemd.socket(5)\fR, +\fIhttps://knot-resolver.readthedocs.io\fR + +.SH "AUTHORS" +.B kresd developers are mentioned in the AUTHORS file in the distribution. diff --git a/systemd/90-kresd.preset b/systemd/90-kresd.preset index ee9934054..95acccf49 100644 --- a/systemd/90-kresd.preset +++ b/systemd/90-kresd.preset @@ -3,4 +3,4 @@ # associated sockets *are* enabled however, so the kresd service will # be started as soon as anything connects to one of the listening # sockets. -disable kresd.service +disable kresd@1.service diff --git a/systemd/README.md b/systemd/README.md index 0f35cbe38..d44c2bf7a 100644 --- a/systemd/README.md +++ b/systemd/README.md @@ -6,36 +6,33 @@ by systemd (or any supervisor that provides equivalent file descriptor initialization via the interface supported by sd_listen_fds_with_names(3)). -Distributors of systems using systemd may wish to place -./90-kresd.preset in /lib/systemd/systemd-preset/90-kresd.preset if -they want to delay daemon launch until it is accessed. (see -systemd.preset(5)). +Usage and Configuration +----------------------- -When run in this configuration: +See kresd.systemd(8) for details. - * it will be run under a non-privileged user, which means it will not - be able to open any new non-privileged ports. +Manual activation +----------------- - * it will use a single process (implicitly uses --forks=1, and will - fail if that configuration variable is set to a different value). - If you want multiple daemons to listen on these ports publicly - concurrently, you'll need the supervisor to manage them - differently, for example via a systemd generator: +If you wish to use manual activation without sockets, you have to grant +the service the capability to bind to well-known ports. You can use a drop-in +file. - https://www.freedesktop.org/software/systemd/man/systemd.generator.html + # /etc/systemd/system/kresd@.service.d/override.conf + [Service] + AmbientCapabilities=CAP_NET_BIND_SERVICE - If you have a useful systemd generator for multiple concurrent - processes, please contribute it upstream! +Notes +----- -Administrators who wish to make kresd listen on a public network -interface can use: +* If you're using systemd prior to version 227, use a drop-in file to change + the service type to simple. See drop-in/systemd-compat.conf. - systemctl edit kresd.socket +* Distributors of systems using systemd may wish to place + ./90-kresd.preset in /lib/systemd/systemd-preset/90-kresd.preset if + they want to delay daemon launch until it is accessed. (see + systemd.preset(5)). -to add an override file that indicates where they want it to listen. -For example: - - # /etc/systemd/system/kresd.socket.d/override.conf - [Socket] - ListenDatagram=192.0.2.115:53 - ListenStream=192.0.2.115:53 +* Symlinks pointing from @1 to the systemd template are not necessary. They + are only useful to provide users unfamiliar with kresd instances a hint + when using bash completion. diff --git a/systemd/drop-in/listen-tls.conf b/systemd/drop-in/listen-tls.conf new file mode 100644 index 000000000..b03c42526 --- /dev/null +++ b/systemd/drop-in/listen-tls.conf @@ -0,0 +1,7 @@ +# /etc/systemd/system/kresd-tls@.socket.d/override.conf + +# Configure which interfaces should kresd listen on. +# ListenStream can be added multiple times. + +[Socket] +ListenStream=192.0.2.115:853 diff --git a/systemd/drop-in/listen-udp-tcp.conf b/systemd/drop-in/listen-udp-tcp.conf new file mode 100644 index 000000000..c45e1ce58 --- /dev/null +++ b/systemd/drop-in/listen-udp-tcp.conf @@ -0,0 +1,8 @@ +# /etc/systemd/system/kresd@.socket.d/override.conf + +# Configure which interfaces should kresd listen on. +# ListenDatagram and ListenStream can be added multiple times. + +[Socket] +ListenDatagram=192.0.2.115:53 +ListenStream=192.0.2.115:53 diff --git a/systemd/drop-in/manual-activation.conf b/systemd/drop-in/manual-activation.conf new file mode 100644 index 000000000..af7e0d33c --- /dev/null +++ b/systemd/drop-in/manual-activation.conf @@ -0,0 +1,7 @@ +# /etc/systemd/system/kresd@.service.d/override.conf + +# If socket activation isn't used, the CAP_NET_BIND_SERVICE is necessary +# to be able to bind to a well-known port as an unprivilidged user. + +[Service] +AmbientCapabilities=CAP_NET_BIND_SERVICE diff --git a/systemd/drop-in/systemd-compat.conf b/systemd/drop-in/systemd-compat.conf new file mode 100644 index 000000000..b33671a3e --- /dev/null +++ b/systemd/drop-in/systemd-compat.conf @@ -0,0 +1,6 @@ +# /etc/systemd/system/kresd@.service.d/override.conf + +# If systemd.227+ isn't available (e.g. CentOS 7), change the service type. + +[Service] +Type=simple diff --git a/systemd/kresd-control.socket b/systemd/kresd-control@.socket similarity index 61% rename from systemd/kresd-control.socket rename to systemd/kresd-control@.socket index ceba94baf..c31a6d9c6 100644 --- a/systemd/kresd-control.socket +++ b/systemd/kresd-control@.socket @@ -2,13 +2,12 @@ Description=Knot DNS Resolver control socket Documentation=man:kresd(8) Before=sockets.target -PartOf=kresd.socket -Alias=knot-resolver-control.socket +Service=kresd@%i.service +PartOf=kresd@%i.service [Socket] -ListenStream=/run/knot-resolver/control +ListenStream=/run/knot-resolver/control@%i FileDescriptorName=control -Service=kresd.service SocketMode=0660 [Install] diff --git a/systemd/kresd-control@1.socket b/systemd/kresd-control@1.socket new file mode 120000 index 000000000..4a4b9d6f9 --- /dev/null +++ b/systemd/kresd-control@1.socket @@ -0,0 +1 @@ +kresd-control@.socket \ No newline at end of file diff --git a/systemd/kresd-tls.socket b/systemd/kresd-tls@.socket similarity index 57% rename from systemd/kresd-tls.socket rename to systemd/kresd-tls@.socket index 328039f5f..7f1123f5f 100644 --- a/systemd/kresd-tls.socket +++ b/systemd/kresd-tls@.socket @@ -2,13 +2,15 @@ Description=Knot DNS Resolver TLS network listener Documentation=man:kresd(8) Before=sockets.target -PartOf=kresd.socket -Alias=knot-resolver-tls.socket +Service=kresd@%i.service +PartOf=kresd@%i.service [Socket] -ListenStream=853 +ReusePort=true +FreeBind=true FileDescriptorName=tls -Service=kresd.service +ListenStream=[::1]:853 +ListenStream=127.0.0.1:853 [Install] WantedBy=sockets.target diff --git a/systemd/kresd-tls@1.socket b/systemd/kresd-tls@1.socket new file mode 120000 index 000000000..f261c13d9 --- /dev/null +++ b/systemd/kresd-tls@1.socket @@ -0,0 +1 @@ +kresd-tls@.socket \ No newline at end of file diff --git a/systemd/kresd.service b/systemd/kresd@.service similarity index 63% rename from systemd/kresd.service rename to systemd/kresd@.service index a08da00d0..864ebe773 100644 --- a/systemd/kresd.service +++ b/systemd/kresd@.service @@ -1,7 +1,9 @@ [Unit] Description=Knot DNS Resolver daemon Documentation=man:kresd(8) -Alias=knot-resolver.service +Wants=kresd@%i.socket +Wants=kresd-control@%i.socket +Wants=kresd-tls@%i.socket [Service] Type=notify @@ -10,5 +12,3 @@ EnvironmentFile=-/etc/default/kresd ExecStart=/usr/sbin/kresd $KRESD_ARGS User=knot-resolver Restart=on-failure -# CAP_NET_BIND_SERVICE capability is needed for manual service activation -AmbientCapabilities=CAP_NET_BIND_SERVICE diff --git a/systemd/kresd.socket b/systemd/kresd@.socket similarity index 80% rename from systemd/kresd.socket rename to systemd/kresd@.socket index ac7dc6373..29b7e0aa6 100644 --- a/systemd/kresd.socket +++ b/systemd/kresd@.socket @@ -2,14 +2,16 @@ Description=Knot DNS Resolver network listeners Documentation=man:kresd(8) Before=sockets.target -Alias=knot-resolver.socket +Service=kresd@%i.service +PartOf=kresd@%i.service [Socket] -ListenStream=[::1]:53 +ReusePort=true +FreeBind=true ListenDatagram=[::1]:53 -ListenStream=127.0.0.1:53 +ListenStream=[::1]:53 ListenDatagram=127.0.0.1:53 -FreeBind=true +ListenStream=127.0.0.1:53 [Install] WantedBy=sockets.target diff --git a/systemd/kresd@1.socket b/systemd/kresd@1.socket new file mode 120000 index 000000000..c0ed9f248 --- /dev/null +++ b/systemd/kresd@1.socket @@ -0,0 +1 @@ +kresd@.socket \ No newline at end of file -- 2.47.3