Systemd Services

Systemd Services

Systemd service configuration across NixOS hosts ensures automatic scaling, restarts, and dependency management.

Monitored & Orchestrated Services

  • Fail2ban (services.monitoring.fail2ban): Brute-force protection on SSH and other exposed ports.
  • Prometheus (services.monitoring.prometheus): Metrics collection and system monitoring.
  • EarlyOOM (services.system.earlyoom): Out-of-memory daemon to maintain system responsiveness under load.
  • Nginx (services.web.nginx): Web server and reverse proxy, configured for SSL and routing internal services. See Web Services & Databases for detailed configuration.
  • PostgreSQL (services.dev.postgresql): Database backend for multiple services. See Web Services & Databases for maintenance and upgrade guides.
  • Jellyfin (services.media.jellyfin): Media streaming configuration for client/server roles.
  • UDisks2 (services.system.udisks2): Disk management service.
  • Btrbk (services.system.btrbk): Automated Btrfs snapshotting and backup.

All of these are declared modularly under modules/services/ and integrated via systemd.services.<name> using standard Nix expressions.


D-Bus Activation & Double-Instance Race

Some packages (notably Ghostty ≥1.0) ship both a systemd user service AND a desktop file with DBusActivatable=true. This creates a race on first launch from an app launcher (Rofi):

  1. Launcher triggers D-Bus activation → systemd starts app-*.service daemon with --initial-window=false
  2. Simultaneously, the desktop file’s Exec= line runs ghostty directly
  3. If the daemon hasn’t registered on D-Bus yet, the direct launch creates a second full instance → two windows instead of one

Fix Pattern

Override the package desktop file via home.file at ~/.local/share/applications/ (takes priority over Nix profile paths). Drop DBusActivatable=true and use a plain Exec= line without --gtk-single-instance flags — the systemd daemon handles single-instance internally.

# modules/desktop/term/ghostty.nix
home.file.".local/share/applications/com.mitchellh.ghostty.desktop".text = ''
  [Desktop Entry]
  Type=Application
  Name=Ghostty
  Exec=ghostty
  Icon=com.mitchellh.ghostty
  Categories=System;TerminalEmulator;
  Terminal=false
  StartupWMClass=com.mitchellh.ghostty
'';

Audit

As of 2026-06, only com.mitchellh.ghostty.desktop in our fleet uses this pattern. Other D-Bus-activatable desktop files (Rnote, Fractal, Telegram, GNOME apps) are single-process — no systemd daemon, no race. Foot’s foot-server.service uses socket activation, not D-Bus, and is also safe.


User Service Map

Three layers feed systemd --user:

Layer 1 — Package-shipped (/etc/profiles/per-user/.../share/systemd/user/)

Services installed by user packages in the Nix profile. These are D-Bus activated or socket-activated, not enabled at boot.

ServiceOriginActivation
app-com.mitchellh.ghosttyghosttyD-Bus (see race above)
foot-server + .socketfootSocket
flatpak-* (3)flatpakD-Bus
gnome-softwaregnome-softwareD-Bus
org.gnome.EvinceevinceD-Bus
podman* (7)podmanVarious
pulseaudio + .socket + -x11pulseaudioSocket

Layer 2 — System Profile (/run/current-system/sw/share/systemd/user/)

Services declared by NixOS/Home Manager modules. Most are linked-runtime (started via dependency chains, not directly enabled).

ServiceCategoryOrigin
niriCompositorOur host config
dmsShell themingmodules/desktop/shell/dms.nix
sunshineGame streamingmodules/services/media/sunshine.nix
syncthingFile syncmodules/services/sharing/syncthing.nix
wayvncRemote desktopmodules/services/desktop/wayvnc.nix
xwayland-satelliteX11 compatibilitymodules/services/desktop/xwayland-satellite.nix
pipewire (3)AudioNixOS
wireplumber (2)Audio sessionNixOS
gvfs (7)Virtual filesystemGNOME
xdg-* (7)Desktop portalsNixOS/GNOME
blueman (2)Bluetoothmodules/profiles/hardware/bluetooth.nix
dconfConfig storeNixOS
gamemodedGamingmodules/profiles/hardware/cpu/amd.nix
speech-dispatcherAccessibilityGNOME
thunar + tumblerdFile managerXfce
waydroid-monitorAndroidmodules/services/virt/waydroid.nix
xfconfdXfce configXfce

Layer 3 — XDG Autostart (.desktop → transient app-*@autostart.service)

Desktop files in /etc/xdg/autostart/ and ~/.config/autostart/ are processed by the DE (Niri via systemd-xdg-autostart-generator). Each generates a transient app-<id>@autostart.service.

Desktop fileService
at-spi-dbus-bus.desktopAccessibility bus
blueman.desktopBluetooth tray
ca.andyholmes.Valent-autostart.desktopKDE Connect clone
geoclue-demo-agent.desktopGeolocation agent
gnome-keyring-pkcs11.desktopSSH/GPG keyring
gnome-keyring-secrets.desktopSecret storage
org.fcitx.Fcitx5.desktopInput method
print-applet.desktopPrint notifications
xdg-user-dirs.desktopUser dirs setup

Health Check

All services are clean — zero failed units at both system and user level. foot-server and pulseaudio are disabled (socket-activated only). ghostty is D-Bus activated (we override its desktop file to avoid the race).