diff --git a/listmonk@.service b/listmonk@.service new file mode 100644 index 0000000..9d452ad --- /dev/null +++ b/listmonk@.service @@ -0,0 +1,69 @@ +[Unit] +Description=listmonk mailing list and newsletter manager (%I) +ConditionPathExists=/etc/listmonk/%i.toml +Wants=network.target +# The PostgreSQL database may not be on the same host but if it +# is listmonk should wait for it to start up. +After=postgresql.service + +[Service] +Type=simple +EnvironmentFile=-/etc/default/listmonk +EnvironmentFile=-/etc/default/listmonk-%i +ExecStartPre=/usr/bin/mkdir -p "${HOME}/uploads" +ExecStartPre=/usr/bin/listmonk --config /etc/listmonk/%i.toml --upgrade --yes +ExecStart=/usr/bin/listmonk --config /etc/listmonk/%i.toml $SYSTEMD_LISTMONK_ARGS +Restart=on-failure + +# Create dynamic users for listmonk service instances +# but create a state directory for uploads in /var/lib/private/%i. +DynamicUser=True +StateDirectory=listmonk-%i +Environment=HOME=%S/listmonk-%i +WorkingDirectory=%S/listmonk-%i + +# Use systemd’s ability to disable security-sensitive features +# that listmonk does not explicitly need. +# NoNewPrivileges should be enabled by DynamicUser=yes but systemd-analyze +# still recommended to explicitly enable it. +NoNewPrivileges=True +# listmonk doesn’t need any capabilities as defined by the linux kernel +# see: https://man7.org/linux/man-pages/man7/capabilities.7.html +CapabilityBoundingSet= +# listmonk only executes native code with no need for any other ABIs. +SystemCallArchitectures=native +# Only enable a reasonable set of system calls. +# see: https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter= +SystemCallFilter=@system-service +SystemCallFilter=~@privileged @resources +# ProtectSystem=strict, which is implied by DynamicUser=True, already disabled write calls +# to the entire filesystem hierarchy, leaving only /dev/, /proc/, and /sys/ writable. +# listmonk doesn’t need access to those so might as well disable them. +PrivateDevices=True +ProtectControlGroups=True +ProtectKernelTunables=True +# Make /home/, /root/, and /run/user/ inaccessible. +ProtectHome=True +# listmonk doesn’t handle any specific device nodes. +DeviceAllow=False +# listmonk doesn’t make use of linux namespaces. +RestrictNamespaces=True +# listmonk doesn’t need realtime scheduling. +RestrictRealtime=True +# Make sure files created by listmonk are only readable by itself and +# others in the listmonk system group. +UMask=0027 +# Disable memory mappings that are both writable and executable. +MemoryDenyWriteExecute=True +# listmonk doesn’t make use of linux personality switching. +LockPersonality=True +# listmonk only needs to support the IPv4 and IPv6 address families. +RestrictAddressFamilies=AF_INET AF_INET6 +# listmonk doesn’t need to load any linux kernel modules. +ProtectKernelModules=True +# Create a sandboxed environment where the system users are mapped to a +# service-specific linux kernel namespace. +PrivateUsers=True + +[Install] +WantedBy=multi-user.target