systemd
Systemd User Environment
User-based systemd units may fail over SSH or sudo as generally a full systemd environment is not configured automatically with a non-local login.
# Export required user systemd unit environment variables.
export XDG_RUNTIME_DIR="/run/user/$(id -u)"
export DBUS_SESSION_BUS_ADDRESS="unix:path=${XDG_RUNTIME_DIR}/bus"
# Enable service lingering for user.
loginctl enable-linger {USER}
~/.profile
0644 {USER}:{USER}
if [ -z "$XDG_RUNTIME_DIR" ]; then
export XDG_RUNTIME_DIR="/run/user/$(id -u)"
export DBUS_SESSION_BUS_ADDRESS="unix:path=${XDG_RUNTIME_DIR}/bus"
fi
# Alternatively use machinectl to spawn a fully isolated (systemd/dbus session)
# interactive shell on a given machine. Use this after SSH/sudo.
sudo machinectl shell {USER}@.host
Cron Replacement
Actively migrate cronjobs to systemd timers. They are much more flexible and provide consistency on systemd systems. These may also be deployed per-user.
job.service
0644 root:root
# Service executes the commands or script from original cronjob.
[Unit]
Description=Cronjob service example.
Requires=cron_example.timer
After=network.target
Wants=network.target
[Service]
Type=simple
ExecStart=/bin/bash -c '/usr/bin/tar -cvJf /srv/test.tar.xz" "/opt/test"'
WorkingDirectory=/opt/test
User=test_user
Group=test_user
[Install]
WantedBy=multi-user.target
job.timer
0644 root:root
# Timer acts as the scheduler allowing for fine-grained scheduling of job.
[Unit]
Description=cron_example.service timer.
Requires=cron_example.service
[Timer]
OnBootSec=1d
[Install]
WantedBy=timers.target
systemctl daemon-reload
systemctl enable job.service job.timer
systemctl start job.timer
Analyze Boot Time
Don't rabbit hole. Usually slow boot times are from connected drives and devices.
systemd-analyze plot > plot.svg
Service Security Exposure
Generate exposure threat ratings for current system services.
systemd-analyze security
.NET / Mono applications
Applications based on .NET and Mono require special handling for restarting services.
KillMode=none is explicitly deprecated and will eventually be removed.
KillMode=process allows child forks to escape control group (cgroup) and remain running even while their service is considered stopped and assumed to not consume any resources.
For .NET / Mono apps that spawn sub-processes or handle in-app updates, using mixed or control-group keeps systemd's state machine tracking things correctly.
Use Restart=always
Combine with RestartSec and TimeoutStopSec to gracefully shutdown a running application, killing sub-processes after the timeout.
KillMode=control-group
Restart=always
RestartSec=5
TimeoutStopSec=20