From 81927334f25313f0807588a91fbfa061a9665932 Mon Sep 17 00:00:00 2001 From: MichaIng Date: Sun, 18 Sep 2022 21:44:06 +0200 Subject: [PATCH] Add native systemd service Inspired by: https://github.com/pi-hole/pi-hole/pull/2112 A pre-start and a post-stop script are added to reduce doubled setup and cleanup code. Since systemd services do not natively support dynamic users, test once whether capabilities are supported during install/update, and remove User=pihole otherwise. Signed-off-by: MichaIng Co-authored-by: DL6ER --- advanced/Templates/pihole-FTL-poststop.sh | 13 +++++++ advanced/Templates/pihole-FTL-prestart.sh | 38 +++++++++++++++++++++ advanced/Templates/pihole-FTL.service | 40 +++++----------------- advanced/Templates/pihole-FTL.systemd | 41 +++++++++++++++++++++++ automated install/basic-install.sh | 25 ++++++++++++-- 5 files changed, 123 insertions(+), 34 deletions(-) create mode 100755 advanced/Templates/pihole-FTL-poststop.sh create mode 100755 advanced/Templates/pihole-FTL-prestart.sh create mode 100644 advanced/Templates/pihole-FTL.systemd diff --git a/advanced/Templates/pihole-FTL-poststop.sh b/advanced/Templates/pihole-FTL-poststop.sh new file mode 100755 index 00000000..ac3898d2 --- /dev/null +++ b/advanced/Templates/pihole-FTL-poststop.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env sh + +# Source utils.sh for getFTLPIDFile() +PI_HOLE_SCRIPT_DIR='/opt/pihole' +utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" +# shellcheck disable=SC1090 +. "${utilsfile}" + +# Get file paths +FTL_PID_FILE="$(getFTLPIDFile)" + +# Cleanup +rm -f /run/pihole/FTL.sock /dev/shm/FTL-* "${FTL_PID_FILE}" diff --git a/advanced/Templates/pihole-FTL-prestart.sh b/advanced/Templates/pihole-FTL-prestart.sh new file mode 100755 index 00000000..ff4abf3a --- /dev/null +++ b/advanced/Templates/pihole-FTL-prestart.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env sh + +# Source utils.sh for getFTLPIDFile() +PI_HOLE_SCRIPT_DIR='/opt/pihole' +utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" +# shellcheck disable=SC1090 +. "${utilsfile}" + +# Get file paths +FTL_PID_FILE="$(getFTLPIDFile)" + +# Touch files to ensure they exist (create if non-existing, preserve if existing) +# shellcheck disable=SC2174 +mkdir -pm 0755 /run/pihole /var/log/pihole +[ -f "${FTL_PID_FILE}" ] || install -D -m 644 -o pihole -g pihole /dev/null "${FTL_PID_FILE}" +[ -f /var/log/pihole/FTL.log ] || install -m 644 -o pihole -g pihole /dev/null /var/log/pihole/FTL.log +[ -f /var/log/pihole/pihole.log ] || install -m 640 -o pihole -g pihole /dev/null /var/log/pihole/pihole.log +[ -f /etc/pihole/dhcp.leases ] || install -m 644 -o pihole -g pihole /dev/null /etc/pihole/dhcp.leases +# Ensure that permissions are set so that pihole-FTL can edit all necessary files +chown pihole:pihole /run/pihole /etc/pihole /var/log/pihole /var/log/pihole/FTL.log /var/log/pihole/pihole.log /etc/pihole/dhcp.leases +# Ensure that permissions are set so that pihole-FTL can edit the files. We ignore errors as the file may not (yet) exist +chmod -f 0644 /etc/pihole/macvendor.db /etc/pihole/dhcp.leases /var/log/pihole/FTL.log +chmod -f 0640 /var/log/pihole/pihole.log +# Chown database files to the user FTL runs as. We ignore errors as the files may not (yet) exist +chown -f pihole:pihole /etc/pihole/pihole-FTL.db /etc/pihole/gravity.db /etc/pihole/macvendor.db +# Chmod database file permissions so that the pihole group (web interface) can edit the file. We ignore errors as the files may not (yet) exist +chmod -f 0664 /etc/pihole/pihole-FTL.db + +# Backward compatibility for user-scripts that still expect log files in /var/log instead of /var/log/pihole +# Should be removed with Pi-hole v6.0 +if [ ! -f /var/log/pihole.log ]; then + ln -sf /var/log/pihole/pihole.log /var/log/pihole.log + chown -h pihole:pihole /var/log/pihole.log +fi +if [ ! -f /var/log/pihole-FTL.log ]; then + ln -sf /var/log/pihole/FTL.log /var/log/pihole-FTL.log + chown -h pihole:pihole /var/log/pihole-FTL.log +fi diff --git a/advanced/Templates/pihole-FTL.service b/advanced/Templates/pihole-FTL.service index bc1b1d20..15096972 100644 --- a/advanced/Templates/pihole-FTL.service +++ b/advanced/Templates/pihole-FTL.service @@ -9,9 +9,10 @@ # Description: Enable service provided by pihole-FTL daemon ### END INIT INFO -#source utils.sh for getFTLPIDFile(), getFTLPID () +# Source utils.sh for getFTLPIDFile(), getFTLPID() PI_HOLE_SCRIPT_DIR="/opt/pihole" utilsfile="${PI_HOLE_SCRIPT_DIR}/utils.sh" +# shellcheck disable=SC1090 . "${utilsfile}" @@ -28,33 +29,8 @@ start() { if is_running; then echo "pihole-FTL is already running" else - # Touch files to ensure they exist (create if non-existing, preserve if existing) - mkdir -pm 0755 /run/pihole /var/log/pihole - [ ! -f "${FTL_PID_FILE}" ] && install -D -m 644 -o pihole -g pihole /dev/null "${FTL_PID_FILE}" - [ ! -f /var/log/pihole/FTL.log ] && install -m 644 -o pihole -g pihole /dev/null /var/log/pihole/FTL.log - [ ! -f /var/log/pihole/pihole.log ] && install -m 640 -o pihole -g pihole /dev/null /var/log/pihole/pihole.log - [ ! -f /etc/pihole/dhcp.leases ] && install -m 644 -o pihole -g pihole /dev/null /etc/pihole/dhcp.leases - # Ensure that permissions are set so that pihole-FTL can edit all necessary files - chown pihole:pihole /run/pihole /etc/pihole /var/log/pihole /var/log/pihole/FTL.log /var/log/pihole/pihole.log /etc/pihole/dhcp.leases - # Ensure that permissions are set so that pihole-FTL can edit the files. We ignore errors as the file may not (yet) exist - chmod -f 0644 /etc/pihole/macvendor.db /etc/pihole/dhcp.leases /var/log/pihole/FTL.log - chmod -f 0640 /var/log/pihole/pihole.log - # Chown database files to the user FTL runs as. We ignore errors as the files may not (yet) exist - chown -f pihole:pihole /etc/pihole/pihole-FTL.db /etc/pihole/gravity.db /etc/pihole/macvendor.db - # Chown database file permissions so that the pihole group (web interface) can edit the file. We ignore errors as the files may not (yet) exist - chmod -f 0664 /etc/pihole/pihole-FTL.db - - # Backward compatibility for user-scripts that still expect log files in /var/log instead of /var/log/pihole/ - # Should be removed with Pi-hole v6.0 - if [ ! -f /var/log/pihole.log ]; then - ln -s /var/log/pihole/pihole.log /var/log/pihole.log - chown -h pihole:pihole /var/log/pihole.log - - fi - if [ ! -f /var/log/pihole-FTL.log ]; then - ln -s /var/log/pihole/FTL.log /var/log/pihole-FTL.log - chown -h pihole:pihole /var/log/pihole-FTL.log - fi + # Run pre-start script, which pre-creates all expected files with correct permissions + sh "${PI_HOLE_SCRIPT_DIR}/pihole-FTL-prestart.sh" if setcap CAP_NET_BIND_SERVICE,CAP_NET_RAW,CAP_NET_ADMIN,CAP_SYS_NICE,CAP_IPC_LOCK,CAP_CHOWN+eip "/usr/bin/pihole-FTL"; then su -s /bin/sh -c "/usr/bin/pihole-FTL" pihole || exit $? @@ -89,8 +65,8 @@ stop() { else echo "Not running" fi - # Cleanup - rm -f /run/pihole/FTL.sock /dev/shm/FTL-* "${FTL_PID_FILE}" + # Run post-stop script, which does cleanup among runtime files + sh "${PI_HOLE_SCRIPT_DIR}/pihole-FTL-poststop.sh" echo } @@ -108,11 +84,11 @@ status() { ### main logic ### -# Get file paths +# Get FTL's PID file path FTL_PID_FILE="$(getFTLPIDFile)" # Get FTL's current PID -FTL_PID="$(getFTLPID ${FTL_PID_FILE})" +FTL_PID="$(getFTLPID "${FTL_PID_FILE}")" case "$1" in stop) diff --git a/advanced/Templates/pihole-FTL.systemd b/advanced/Templates/pihole-FTL.systemd new file mode 100644 index 00000000..2a114199 --- /dev/null +++ b/advanced/Templates/pihole-FTL.systemd @@ -0,0 +1,41 @@ +[Unit] +Description=Pi-hole FTL +# This unit is supposed to indicate when network functionality is available, but it is only +# very weakly defined what that is supposed to mean, with one exception: at shutdown, a unit +# that is ordered after network-online.target will be stopped before the network +Wants=network-online.target +After=network-online.target +# A target that should be used as synchronization point for all host/network name service lookups. +# All services for which the availability of full host/network name resolution is essential should +# be ordered after this target, but not pull it in. +Wants=nss-lookup.target +Before=nss-lookup.target + +# Limit (re)start loop to 5 within 1 minute +StartLimitBurst=5 +StartLimitIntervalSec=60s + +[Service] +User=pihole +PermissionsStartOnly=true +AmbientCapabilities=CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_NET_ADMIN CAP_SYS_NICE CAP_IPC_LOCK CAP_CHOWN + +ExecStartPre=/opt/pihole/pihole-FTL-prestart.sh +ExecStart=/usr/bin/pihole-FTL -f +Restart=on-failure +RestartSec=5s +ExecReload=/bin/kill -HUP $MAINPID +ExecStopPost=/opt/pihole/pihole-FTL-poststop.sh + +# Use graceful shutdown with a reasonable timeout +TimeoutStopSec=10s + +# Make /usr, /boot, /etc and possibly some more folders read-only... +ProtectSystem=full +# ... except /etc/pihole +# This merely retains r/w access rights, it does not add any new. +# Must still be writable on the host! +ReadWriteDirectories=/etc/pihole + +[Install] +WantedBy=multi-user.target diff --git a/automated install/basic-install.sh b/automated install/basic-install.sh index d4c1ce77..2831e7ec 100755 --- a/automated install/basic-install.sh +++ b/automated install/basic-install.sh @@ -1377,8 +1377,29 @@ installConfigs() { fi fi - # Install pihole-FTL.service - install -T -m 0755 "${PI_HOLE_LOCAL_REPO}/advanced/Templates/pihole-FTL.service" "/etc/init.d/pihole-FTL" + # Install pihole-FTL systemd or init.d service, based on whether systemd is the init system or not + # Follow debhelper logic, which checks for /run/systemd/system to derive whether systemd is the init system + if [[ -d '/run/systemd/system' ]]; then + install -T -m 0644 "${PI_HOLE_LOCAL_REPO}/advanced/Templates/pihole-FTL.systemd" '/etc/systemd/system/pihole-FTL.service' + + # Set net admin permissions so that FTL can serve DNS, DHCP and IMAP (for DHCPv6). If this does not work, run FTL as root user. + if ! setcap CAP_NET_BIND_SERVICE,CAP_NET_RAW,CAP_NET_ADMIN,CAP_SYS_NICE,CAP_IPC_LOCK,CAP_CHOWN+eip '/usr/bin/pihole-FTL'; then + sed -i '/^User=/d' '/etc/systemd/system/pihole-FTL.service' + fi + + # Remove init.d service if present + if [[ -e '/etc/init.d/pihole-FTL' ]]; then + rm '/etc/init.d/pihole-FTL' + update-rc.d pihole-FTL remove + fi + + # Load final service + systemctl daemon-reload + else + install -T -m 0755 "${PI_HOLE_LOCAL_REPO}/advanced/Templates/pihole-FTL.service" '/etc/init.d/pihole-FTL' + fi + install -T -m 0755 "${PI_HOLE_LOCAL_REPO}/advanced/Templates/pihole-FTL-prestart.sh" "${PI_HOLE_INSTALL_DIR}/pihole-FTL-prestart.sh" + install -T -m 0755 "${PI_HOLE_LOCAL_REPO}/advanced/Templates/pihole-FTL-poststop.sh" "${PI_HOLE_INSTALL_DIR}/pihole-FTL-poststop.sh" # If the user chose to install the dashboard, if [[ "${INSTALL_WEB_SERVER}" == true ]]; then