[exim-cvs] Add systemd units (examples)

Startseite
Nachricht löschen
Nachricht beantworten
Autor: Exim Git Commits Mailing List
Datum:  
To: exim-cvs
Betreff: [exim-cvs] Add systemd units (examples)
Gitweb: https://git.exim.org/exim.git/commitdiff/bb6a0f57e5c1a04c9c191af6a37184970003b1c2
Commit:     bb6a0f57e5c1a04c9c191af6a37184970003b1c2
Parent:     44e53a7361d3f02ea411c3755d7cd2b940107606
Author:     Heiko Schlittermann (HS12-RIPE) <hs@???>
AuthorDate: Sat Oct 22 23:15:44 2022 +0200
Committer:  Heiko Schlittermann (HS12-RIPE) <hs@???>
CommitDate: Thu Oct 19 09:56:29 2023 +0200

    Add systemd units (examples)
    
    - daemon
    - socket activation
    - socket activation (inetd mode)
    - queuerunner
    - maintainance
---
 .gitignore                                         |  2 +-
 configs/ABOUT                                      | 11 +--
 configs/system-integration/README.md               |  8 ++
 configs/system-integration/systemd/.gitignore      |  1 +
 configs/system-integration/systemd/README.md       | 86 ++++++++++++++++++++
 .../system-integration/systemd/daemon/exim.service | 29 +++++++
 .../system-integration/systemd/inetd/exim.socket   | 11 +++
 .../system-integration/systemd/inetd/exim@.service | 27 +++++++
 configs/system-integration/systemd/install         | 92 ++++++++++++++++++++++
 .../systemd/maintenance/exim-maintenance.service   | 24 ++++++
 .../systemd/maintenance/exim-maintenance.timer     | 11 +++
 .../systemd/queuerunner/exim-queuerunner.service   | 21 +++++
 .../systemd/queuerunner/exim-queuerunner.timer     | 11 +++
 .../system-integration/systemd/socket/exim.service | 26 ++++++
 .../system-integration/systemd/socket/exim.socket  | 10 +++
 15 files changed, 364 insertions(+), 6 deletions(-)

diff --git a/.gitignore b/.gitignore
index 8c2660a9f..c55dcdcdd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,4 @@
-exim-*
+!/system-integration/
 !/test/aux-fixed/exim-ca
 *~
 *.bak
diff --git a/configs/ABOUT b/configs/ABOUT
index 13d9230b6..f47f96aa8 100644
--- a/configs/ABOUT
+++ b/configs/ABOUT
@@ -1,7 +1,8 @@
-Exim repository: configs
-------------------------
+Exim repository: configs/
+-------------------------
 
-This directory contains sample configurations and similar files that have been
-submitted by Exim users. The files are not locally modified.
+This directory contains sample configurations and and files for
+integrating Exim with the system. These have been submitted by Exim
+users and may or may not fit your your environment.
 
-End
+But we're interested in feedback and improvements.
diff --git a/configs/system-integration/README.md b/configs/system-integration/README.md
new file mode 100644
index 000000000..d06afc5ab
--- /dev/null
+++ b/configs/system-integration/README.md
@@ -0,0 +1,8 @@
+# System Integration
+
+Various systems use various ways to integrate Exim with the system.
+Mainly these tasks have to be accomplished:
+
+- startup procedure (running as a service or on demand)
+- queue runs
+- regular maintenance tasks (log rotation, database cleanup)
diff --git a/configs/system-integration/systemd/.gitignore b/configs/system-integration/systemd/.gitignore
new file mode 100644
index 000000000..15c1e5d15
--- /dev/null
+++ b/configs/system-integration/systemd/.gitignore
@@ -0,0 +1 @@
+.installed
diff --git a/configs/system-integration/systemd/README.md b/configs/system-integration/systemd/README.md
new file mode 100644
index 000000000..297edbc00
--- /dev/null
+++ b/configs/system-integration/systemd/README.md
@@ -0,0 +1,86 @@
+# Systemd Unit Examples for Exim
+
+This directory contains several examples for Systemd units to manage an Exim installation.
+There is room for improvement, so please share your ideas or setups that are proven to work
+in your environment.
+
+All the service units try to protect the system from unintentional
+writes to locations outside of Exim's spool, and log directories.  You
+may need to override specific settings, we recommend using Systemd's
+override mechanism (`systemd edit …`).
+
+The .service units use `ProtectSystem=strict`, which implies a read-only
+file system structure. Exim needs write access to the spool directory
+(main config option: `spool_directory`), and the log directory (main
+config option: `log_file_path`). For improved security you can even set
+`NoNewPrivileges`, if you don't do local deliveries.
+
+The provides Systemd units are examples, containing placeholders
+`{{…}}`. The [install script](./install) helps substituting them.?v
+The following placeholders are used currently:
+- `exim`:
+- `spooldir:`
+- `logdir`:
+
+
+## Daemon
+
+This is best suited for *average to high traffic systems*, it engages
+all built-in Exim facilities, as queue runner management and system load
+depending message processing.
+
+The [systemd service unit](./daemon/exim.service) starts the Exim main
+process. This process listens on the ports configured in the _runtime
+configuration_ (typically `exim.conf`), and supervises all other
+activities, including management of queue runner startups. Basically it
+calls `exim -odf -q...`.
+
+For regular maintenance tasks (database cleanup) additional units are
+[required](./maintenance).
+
+## Socket
+
+This is best suited for *low traffic* systems, which experience a
+message *burst* from time to time. Regular desktop, and edge systems fit this
+pattern.
+
+Exim's start is delayed until the first connection. Once a connection is
+initiated, Exim starts a listener on the port configured in the [systemd
+socket unit](./socket/exim.socket) and waits for more connections. It
+exits after being idle for a while. Basically it calls `exim -bw ...`.
+
+Additional [_queue runner_ timer and service units](#queue-runner) are required.
+
+For regular maintenance tasks (database cleanup)
+additional units are [required](./maintenance).
+
+## Inetd
+
+This is best suited for systems with *low traffic*, if the
+[socket](#socket) approach doesn't work.
+
+For each incoming connection a new Exim instance starts, handling
+exactly this connection and then exits. The listener port is configured
+in the [systemd socket unit](./inetd/exim.socket).
+
+Additional [_queue runner_ timer and service units](#queue-runner) are required.
+
+For regular maintenance tasks (database cleanup)
+additional units are [required](./maintenance).
+
+## Queue Runner
+
+This is a *timer*, and a *service* unit which starts Exim queue runner
+processes. This is necessary, as the socket activated Exim instances
+(from [socket](#socket) and [inetd](#inetd) do not care, once the first
+delivery attempt is done.
+
+## Maintenance
+
+This is a *timer* unit, and a *service* unit for regular maintenance
+tasks.  For security it is recommended to use the `User=` Systemd
+directive in a local override file.
+
+The service unit cares about tidying Exim's hint databases. It *does
+not* rotate the log files, as most systems have their own mechanism for
+doing this job (e.g. Logrotate).
diff --git a/configs/system-integration/systemd/daemon/exim.service b/configs/system-integration/systemd/daemon/exim.service
new file mode 100644
index 000000000..5d49ab356
--- /dev/null
+++ b/configs/system-integration/systemd/daemon/exim.service
@@ -0,0 +1,29 @@
+[Unit]
+Description=Exim MTA (as daemon)
+Documentation=man:exim
+Documentation=https://exim.org/docs.html
+
+Requires=network.target
+After=networking.target
+
+[Service]
+Environment=DAEMON_OPTS=
+Environment=QUEUE_OPTS=-q15m
+EnvironmentFile=-/etc/default/{{exim}}
+
+Type=exec
+ExecStart={{exim}} -bdf $DAEMON_OPTS $QUEUE_OPTS
+ExecReload=kill -HUP ${MAINPID}
+
+# If you do not need local deliveries, enabling the
+# next option can improve security
+#NoNewPrivileges=yes
+
+ProtectSystem=strict
+ReadWriteDirectories={{spooldir}}
+ReadWriteDirectories={{logdir}}
+
+Slice=exim.slice
+
+[Install]
+WantedBy=multi-user.target
diff --git a/configs/system-integration/systemd/inetd/exim.socket b/configs/system-integration/systemd/inetd/exim.socket
new file mode 100644
index 000000000..a802e8ec2
--- /dev/null
+++ b/configs/system-integration/systemd/inetd/exim.socket
@@ -0,0 +1,11 @@
+[Unit]
+Description=Exim MTA (inetd)
+Documentation=man:exim
+Documentation=https://exim.org/docs.html
+
+[Socket]
+ListenStream=25
+Accept=yes
+
+[Install]
+WantedBy=sockets.target
diff --git a/configs/system-integration/systemd/inetd/exim@.service b/configs/system-integration/systemd/inetd/exim@.service
new file mode 100644
index 000000000..7771fde4a
--- /dev/null
+++ b/configs/system-integration/systemd/inetd/exim@.service
@@ -0,0 +1,27 @@
+[Unit]
+Description=Exim MTA (socket activated - inetd mode)
+Documentation=man:exim
+Documentation=https://exim.org/docs.html
+
+[Service]
+Type=exec
+
+# We can't use -odf, as this would ask exim to keep the connection
+# from the client open until the delivery is done
+ExecStart={{exim}} -bs
+
+StandardInput=socket
+StandardError=journal
+
+# Don't kill the delivery process we spawned as a child
+KillMode=process
+
+# If you do not need local deliveries, enabling the
+# next option can improve security
+#NoNewPrivileges=yes
+
+ProtectSystem=strict
+ReadWriteDirectories={{spooldir}}
+ReadWriteDirectories={{logdir}}
+
+Slice=exim.slice
diff --git a/configs/system-integration/systemd/install b/configs/system-integration/systemd/install
new file mode 100755
index 000000000..83a648ab8
--- /dev/null
+++ b/configs/system-integration/systemd/install
@@ -0,0 +1,92 @@
+#!/bin/bash
+# simple helper, mainly for testing the provided Systemd units.
+
+set -eu
+export LC_ALL=C
+
+: ${EXIM=exim}
+: ${EXIM_LOGDIR=/var/log/exim}
+: ${EXIM_SPOOLDIR=/var/spool/exim}
+
+# Packagers should install to $(systemd-path systemd-system-unit)
+# which mostly is something like /lib/systemd/system
+dstdir=
+
+usage="$0 [OPTIONS] variant...
+  This simple script installs Systemd unit files to the desired destination, replacing
+  the {{Placeholder}}s.
+
+  VARIANT: one of daemon, inet, socket, maintainance, queuerunner
+
+  OPTIONS:
+  --help          print this help and exit cleanly
+  --uninstall|-u  uninstall the installed files
+  --dstdir|-d DIR the destination directory (mandatory, use 'DEFAULT'
+                  to use Systemd's default location (`systemd-path systemd-system-conf`)
+
+  Placeholders:
+  {{exim}} from \$EXIM ($EXIM)
+  {{logdir}} from \$EXIM_LOGDIR ($EXIM_LOGDIR)
+  {{spooldir}} from \$EXIM_SPOOLDIR ($EXIM_SPOOLDIR)
+"
+
+
+tmp=$(getopt -n $0 -o d:n --long dstdir:,help,uninstall -- "$@")
+eval set -- "$tmp"
+while true
+do
+    o=$1; shift
+    case $o in
+                -d|--dstdir) dstdir=$1; shift;;
+                --help) echo "$usage"; exit;;
+        -n|--uninstall) uninstall=1;;
+        --) break
+    esac
+done
+
+if [[ -v uninstall ]]
+then
+    if ! [[ -r .installed ]]
+    then
+        echo "$0: noting to uninstall (.installed is empty or isn't readable)" >&2
+        exit
+    fi
+
+    rm -vf $(<.installed)
+    rm -f .installed
+    exit
+fi
+
+case $dstdir in
+        DEFAULT) dstdir=$(systemd-path systemd-system-conf);;
+        "") echo "$0: --dstdir is mandatory" >&2; exit 1;;
+        *) ;;
+esac
+
+if (( $# == 0 ))
+then echo "$0: need variant" >&2; exit 1;
+fi
+
+function xform() {
+        sed -e "s|{{exim}}|${EXIM:?}|g" \
+            -e "s|{{logdir}}|${EXIM_LOGDIR:?}|g" \
+            -e "s|{{spooldir}}|${EXIM_SPOOLDIR:?}|g"
+}
+
+for dir in ${@:?need source dir(s)}
+do
+        echo "# $dir"
+        for src in "$dir"/*
+        do
+            dst="$dstdir/${src##*/}"
+            echo "installing $dst"
+            xform <"$src" >"$dst"
+            echo $dst >> .installed
+        done
+done
+
+if [[ $dstdir == $(systemd-path systemd-system-conf) ]]
+then
+        echo "# reloading systemd configuration"
+        systemctl daemon-reload
+fi
diff --git a/configs/system-integration/systemd/maintenance/exim-maintenance.service b/configs/system-integration/systemd/maintenance/exim-maintenance.service
new file mode 100644
index 000000000..42722d3fc
--- /dev/null
+++ b/configs/system-integration/systemd/maintenance/exim-maintenance.service
@@ -0,0 +1,24 @@
+[Unit]
+Description=Exim MTA (maintenance)
+Documentation=man:exim
+Documentation=https://exim.org/docs.html
+
+[Service]
+Type=oneshot
+ExecReload=kill -HUP ${MAINPID}
+
+# Dollars are doubled for systemd!
+WorkingDirectory={{spooldir}}
+ExecStart=sh -ec 'for db in db/* ;\
+        do \
+            test -f "$$db" && [ "$${db##*.}" != lockfile ] || continue ;\
+            exim_tidydb $$PWD "$${db##*/}"; \
+        done'
+
+ProtectSystem=strict
+ReadWriteDirectories={{spooldir}}/db
+
+Slice=exim.slice
+
+[Install]
+WantedBy=multi-user.target
diff --git a/configs/system-integration/systemd/maintenance/exim-maintenance.timer b/configs/system-integration/systemd/maintenance/exim-maintenance.timer
new file mode 100644
index 000000000..bd192cd07
--- /dev/null
+++ b/configs/system-integration/systemd/maintenance/exim-maintenance.timer
@@ -0,0 +1,11 @@
+[Unit]
+Description=Exim MTA (maintenance timer)
+Documentation=man:exim
+Documentation=https://exim.org/docs.html
+
+[Timer]
+OnActiveSec=1h
+OnUnitActiveSec=1d
+
+[Install]
+WantedBy=timers.target
diff --git a/configs/system-integration/systemd/queuerunner/exim-queuerunner.service b/configs/system-integration/systemd/queuerunner/exim-queuerunner.service
new file mode 100644
index 000000000..e6e9ca799
--- /dev/null
+++ b/configs/system-integration/systemd/queuerunner/exim-queuerunner.service
@@ -0,0 +1,21 @@
+[Unit]
+Description=Exim MTA (queue runner service)
+Documentation=man:exim
+Documentation=https://exim.org/docs.html
+
+[Service]
+Type=oneshot
+
+ExecStart={{exim}} -q
+KillMode=process
+
+# If you do not need local deliveries, enabling the
+# next option can improve security
+#NoNewPrivileges=yes
+
+ProtectSystem=strict
+ReadWriteDirectories={{spooldir}}
+ReadWriteDirectories={{logdir}}
+ReadWriteDirectories=/var/mail /var/spool/mail
+
+Slice=exim.slice
diff --git a/configs/system-integration/systemd/queuerunner/exim-queuerunner.timer b/configs/system-integration/systemd/queuerunner/exim-queuerunner.timer
new file mode 100644
index 000000000..6988b7c29
--- /dev/null
+++ b/configs/system-integration/systemd/queuerunner/exim-queuerunner.timer
@@ -0,0 +1,11 @@
+[Unit]
+Description=Exim MTA (queue runner timer)
+Documentation=man:exim
+Documentation=https://exim.org/docs.html
+
+[Timer]
+OnActiveSec=120
+OnUnitActiveSec=15m
+
+[Install]
+WantedBy=timers.target
diff --git a/configs/system-integration/systemd/socket/exim.service b/configs/system-integration/systemd/socket/exim.service
new file mode 100644
index 000000000..a4576ae24
--- /dev/null
+++ b/configs/system-integration/systemd/socket/exim.service
@@ -0,0 +1,26 @@
+[Unit]
+Description=Exim MTA (socket activated)
+Documentation=man:exim
+Documentation=https://exim.org/docs.html
+PartOf=exim.socket
+
+[Service]
+Type=exec
+Environment=INACTIVITY_TIMEOUT=5m
+EnvironmentFile=-/etc/default/exim
+
+ExecStart=exim -bw${INACTIVITY_TIMEOUT}
+
+StandardInput=socket
+StandardError=journal
+
+# If you do not need local deliveries, enabling the
+# next option can improve security
+#NoNewPrivileges=yes
+
+ProtectSystem=strict
+ReadWriteDirectories={{spooldir}}
+ReadWriteDirectories={{logdir}}
+ReadWriteDirectories=/var/mail /var/spool/mail
+
+Slice=exim.slice
diff --git a/configs/system-integration/systemd/socket/exim.socket b/configs/system-integration/systemd/socket/exim.socket
new file mode 100644
index 000000000..8b3876663
--- /dev/null
+++ b/configs/system-integration/systemd/socket/exim.socket
@@ -0,0 +1,10 @@
+[Unit]
+Description=Exim MTA (socket)
+Documentation=man:exim
+Documentation=https://exim.org/docs.html
+
+[Socket]
+ListenStream=25
+
+[Install]
+WantedBy=sockets.target


--
## subscription configuration (requires account):
## https://lists.exim.org/mailman3/postorius/lists/exim-cvs.lists.exim.org/
## unsubscribe (doesn't require an account):
## exim-cvs-unsubscribe@???
## Exim details at http://www.exim.org/
## Please use the Wiki with this list - http://wiki.exim.org/