Skip to content
NullString1 edited this page Jan 13, 2026 · 1 revision

Services

System and user services configuration in NullOS.

Overview

NullOS configures services at two levels:

  • System services - NixOS configuration (require sudo)
  • User services - Home Manager (run as user)

System Services

Configured in modules/services/ directory.

Audio

Pipewire (modules/services/audio.nix):

services.pipewire={enable=true;alsa.enable=true;alsa.support32Bit=true;pulse.enable=true;jack.enable=true;wireplumber.enable=true;};hardware.pulseaudio.enable=false;

Features:

  • Low-latency audio
  • ALSA compatibility
  • PulseAudio replacement
  • JACK support
  • Bluetooth audio

Control:

# Volume control
wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+
wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
# List devices
wpctl status

Display Manager

SDDM (modules/services/sddm.nix):

services.displayManager.sddm={enable=true;wayland.enable=true;theme="sugar-candy";package=pkgs.kdePackages.sddm;};

Auto-login:

services.displayManager.autoLogin={enable=vars.autoLogin;user=vars.username;};

Desktop Portal

XDG Desktop Portal (modules/services/xdg-portal.nix):

xdg.portal={enable=true;extraPortals=withpkgs;[xdg-desktop-portal-gtkxdg-desktop-portal-hyprland];config.common.default="*";};

Provides:

  • Screen sharing
  • File picker
  • Notifications
  • Screenshot portal

Network

NetworkManager:

networking.networkmanager.enable=true;users.users.${vars.username}.extraGroups=["networkmanager"];

Control:

# CLI
nmcli device wifi list
nmcli device wifi connect SSID password PASSWORD
# GUI
nm-applet # System tray

Bluetooth

BlueZ:

hardware.bluetooth={enable=true;powerOnBoot=true;settings={General={Enable="Source,Sink,Media,Socket";Experimental=true;};};};services.blueman.enable=true;

Control:

# CLI
bluetoothctl
> scan on
> pair XX:XX:XX:XX:XX:XX
> connect XX:XX:XX:XX:XX:XX
# GUI
blueman-manager

Printing

CUPS:

services.printing={enable=true;drivers=withpkgs;[gutenprinthplipsplix];};services.avahi={enable=true;nssmdns4=true;openFirewall=true;};

Manage:

# Web interface
http://localhost:631/
# CLI
lpstat -p -d
lpr -P printer-name file.pdf

Virtualization

Docker (modules/services/virtualisation.nix):

virtualisation.docker={enable=true;enableOnBoot=true;daemon.settings={data-root="/var/lib/docker";};};users.users.${vars.username}.extraGroups=["docker"];

Libvirt (optional):

virtualisation.libvirtd={enable=true;qemu={package=pkgs.qemu_kvm;ovmf.enable=true;swtpm.enable=true;};};users.users.${vars.username}.extraGroups=["libvirtd"];

SSH

services.openssh={enable=true;settings={PermitRootLogin="no";PasswordAuthentication=false;};ports=[22];};

Firewall:

networking.firewall.allowedTCPPorts=[22];

Locate

plocate:

services.locate={enable=true;package=pkgs.plocate;localuser=null;};

Usage:

# Update database
sudo updatedb
# Search
locate filename

Flatpak

services.flatpak.enable=true;xdg.portal.enable=true;

Usage:

# Add Flathub
flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
# Install
flatpak install flathub org.gimp.GIMP
# Run
flatpak run org.gimp.GIMP

Automatic Upgrades

system.autoUpgrade={enable=false;# Manual recommendedflake="/home/${vars.username}/NullOS";dates="weekly";allowReboot=false;};

Garbage Collection

nix.gc={automatic=true;dates="weekly";options="--delete-older-than 30d";};nix.optimise={automatic=true;dates=["weekly"];};

User Services

Configured via Home Manager in home/ directory.

Hyprpaper

Wallpaper Service:

systemd.user.services.hyprpaper={Unit={Description="Hyprland wallpaper daemon";PartOf=["graphical-session.target"];After=["graphical-session.target"];};Service={ExecStart="${pkgs.hyprpaper}/bin/hyprpaper";Restart="on-failure";};Install={WantedBy=["hyprland-session.target"];};};

SwayNC

Notification Daemon (home/swaync.nix):

services.swaync={enable=true;settings={positionX="right";positionY="top";control-center-width=380;notification-visibility={telegram={state="muted";};};};};

SwayOSD

On-Screen Display (home/swayosd.nix):

services.swayosd={enable=true;topMargin=0.9;};

Shows OSD for:

  • Volume changes
  • Brightness changes
  • Caps Lock

Syncthing

services.syncthing={enable=true;user=vars.username;dataDir="/home/${vars.username}/.syncthing";configDir="/home/${vars.username}/.config/syncthing";overrideDevices=true;overrideFolders=true;settings={devices={"device1"={id="DEVICE-ID-HERE";};};folders={"Documents"={path="/home/${vars.username}/Documents";devices=["device1"];};};};};

Backup Service

Backup services are typically configured at the system level using Restic.

See Backup for complete configuration.

MPD

Music Player Daemon:

services.mpd={enable=true;musicDirectory="/home/${vars.username}/Music";extraConfig='' audio_output { type "pipewire" name "PipeWire" } '';};services.mpdris2.enable=true;# MPRIS support

Espanso

Text Expander:

services.espanso={enable=true;configs={default={toggle_key="CTRL";};};matches={base={matches=[{trigger=":shrug";replace=\\_(ツ)_/¯";}];};};};

Managing Services

System Services

Check status:

sudo systemctl status service-name

Start/Stop:

sudo systemctl start service-name
sudo systemctl stop service-name
sudo systemctl restart service-name

Enable/Disable:

sudo systemctl enable service-name
sudo systemctl disable service-name

View logs:

sudo journalctl -u service-name
sudo journalctl -u service-name -f # Follow

User Services

Check status:

systemctl --user status service-name

Start/Stop:

systemctl --user start service-name
systemctl --user stop service-name
systemctl --user restart service-name

Enable/Disable:

systemctl --user enable service-name
systemctl --user disable service-name

View logs:

journalctl --user -u service-name
journalctl --user -u service-name -f

List Services

All system services:

systemctl list-units --type=service

All user services:

systemctl --user list-units --type=service

Failed services:

systemctl list-units --failed
systemctl --user list-units --failed

Creating Custom Services

System Service

Create modules/services/my-service.nix:

{config,pkgs,vars, ... }:
{systemd.services.my-service={description="My Custom Service";wantedBy=["multi-user.target"];after=["network.target"];serviceConfig={Type="simple";ExecStart="${pkgs.my-package}/bin/my-command";Restart="on-failure";RestartSec="5s";User=vars.username;Group="users";# SecurityPrivateTmp=true;NoNewPrivileges=true;ProtectSystem="strict";ProtectHome=true;};};}

Import in configuration.nix or modules/services/default.nix.

User Service

In home/my-service.nix:

{config,pkgs, ... }:
{systemd.user.services.my-service={Unit={Description="My User Service";After=["graphical-session.target"];};Service={ExecStart="${pkgs.my-package}/bin/my-command";Restart="on-failure";RestartSec="5s";};Install={WantedBy=["default.target"];};};}

Timer Service

System timer:

systemd.timers.my-timer={wantedBy=["timers.target"];timerConfig={OnCalendar="daily";OnBootSec="5m";Persistent=true;};};systemd.services.my-timer={serviceConfig={Type="oneshot";ExecStart="${pkgs.bash}/bin/bash -c 'echo hello'";};};

User timer:

systemd.user.timers.my-timer={Unit={Description="My Timer";};Timer={OnCalendar="hourly";Persistent=true;};Install={WantedBy=["timers.target"];};};

Service Dependencies

Ordering

systemd.services.my-service={after=["network.target""other-service.service"];before=["another-service.service"];requires=["required-service.service"];wants=["optional-service.service"];};

Difference:

  • requires - Hard dependency (fails if missing)
  • wants - Soft dependency (continues if missing)
  • after - Start after other service
  • before - Start before other service

Service Security

Hardening Options

serviceConfig={# ProcessUser="specific-user";Group="specific-group";NoNewPrivileges=true;# FilesystemPrivateTmp=true;ProtectSystem="strict";ProtectHome=true;ReadWritePaths=["/var/lib/myservice"];# NetworkPrivateNetwork=false;RestrictAddressFamilies=["AF_INET""AF_INET6"];# CapabilitiesCapabilityBoundingSet=["CAP_NET_BIND_SERVICE"];AmbientCapabilities=["CAP_NET_BIND_SERVICE"];# System callsSystemCallFilter="@system-service";SystemCallErrorNumber="EPERM";};

Analyzing Security

systemd-analyze security service-name

Environment Variables

System Service

systemd.services.my-service={environment={MY_VAR="value";PATH="${pkgs.package}/bin";};# Or from fileenvironmentFile="/run/secrets/service-env";};

User Service

systemd.user.services.my-service={Service={Environment="MY_VAR=value";EnvironmentFile="/home/user/.env";};};

Troubleshooting Services

Service Won't Start

# Check status
systemctl status service-name
# View full logs
journalctl -u service-name -n 100
# Check for errors
journalctl -p err -u service-name

Service Crashes

# Check restart count
systemctl show service-name -p NRestarts
# Increase verbosity
journalctl -u service-name -f --output=verbose

Permission Issues

# Check which user runs service
systemctl show service-name -p User
# Check file permissions
ls -l /path/to/file
# Test command manually
sudo -u username /path/to/command

Best Practices

  1. Use Security Options - Restrict what services can access
  2. Set Restart Policies - Handle crashes gracefully
  3. Log Appropriately - Use structured logging
  4. Resource Limits - Prevent resource exhaustion
  5. User Services When Possible - Don't run as root unnecessarily

Next Steps

Clone this wiki locally