Skip to content

Maintenance

Routine maintenance tasks for both systems, including garbage collection, store optimisation, SSD maintenance, and monitoring.

Garbage Collection

Laptop

Managed automatically by nh:

nix
programs.nh.clean = {
  enable = true;
  dates = "weekly";
  extraArgs = "--keep-since 3d --keep 3";
};
  • Runs weekly as a systemd timer
  • Removes generations older than 3 days
  • Always keeps at least 3 generations

Manual GC:

bash
# Dry run to see what would be removed
nix store gc --dry-run

# Actually collect garbage
nix store gc

Server

nix
nix.gc = {
  automatic = true;
  dates = "weekly";
  options = "--delete-older-than 7d";
};
  • Runs weekly
  • Removes all generations older than 7 days
  • No minimum generation count (the server should always be on the latest)

Store Optimisation

Both systems enable automatic store optimisation:

nix
nix.optimise = {
  automatic = true;
  dates = [ "weekly" ];
};

nix.settings.auto-optimise-store = true;
SettingEffect
nix.optimise.automaticRuns nix store optimise weekly (deduplicates store paths via hardlinks)
auto-optimise-storeOptimises new paths as they're added to the store

Both are enabled for belt-and-suspenders deduplication. The weekly job catches any paths that were added without optimisation.

SSD Maintenance (fstrim)

Both systems enable weekly TRIM:

nix
services.fstrim = {
  enable = true;
  interval = "weekly";
};

This runs fstrim -av weekly, which informs the SSD firmware about unused blocks, maintaining write performance and extending drive lifespan.

Server I/O Schedulers

The server sets I/O schedulers per device type via udev rules:

nix
services.udev.extraRules = ''
  # HDD
  ACTION == "add|change", KERNEL=="sd[a-z]*", ATTR{queue/rotational}=="1", \
    ATTR{queue/scheduler}="bfq"

  # SSD
  ACTION=="add|change", KERNEL=="sd[a-z]*|mmcblk[0-9]*", ATTR{queue/rotational}=="0", \
    ATTR{queue/scheduler}="mq-deadline"

  # NVMe SSD
  ACTION=="add|change", KERNEL=="nvme[0-9]*", ATTR{queue/rotational}=="0", \
    ATTR{queue/scheduler}="none"
'';
Device TypeSchedulerRationale
HDD (rotational)bfqBudget Fair Queuing; optimises for latency with rotating media
SATA SSDmq-deadlineSimple deadline scheduler; good for SATA SSDs with limited parallelism
NVMe SSDnoneNVMe handles its own queuing; any software scheduler adds overhead

Systemd Timers Overview

All automated maintenance tasks are systemd timers. To see the full schedule:

bash
systemctl list-timers --all

Server Timers

TimerScheduleService
nixos-upgrade.timerWeeklySystem auto-upgrade
restic-backups-backup.timerDailyRestic backup
nix-gc.timerWeeklyNix garbage collection
nix-optimise.timerWeeklyNix store optimisation
fstrim.timerWeeklySSD TRIM

Laptop Timers

TimerScheduleService
nh-clean.timerWeeklyGeneration cleanup
nix-optimise.timerWeeklyNix store optimisation
fstrim.timerWeeklySSD TRIM

Disk Usage Monitoring

bash
# Check overall disk usage
df -h

# Check Nix store size
du -sh /nix/store

# Check number of store paths
ls /nix/store | wc -l

# Check Restic repository size (server)
du -sh /backup

# Check persistent data size (server)
du -sh /persist/*

Server-Specific Maintenance

Impermanence Cleanup

Old root subvolumes are automatically cleaned up during the boot rollback script. Subvolumes older than 30 days are deleted:

bash
for i in $(find /btrfs_tmp/old_roots/ -maxdepth 1 -mtime +30); do
    delete_subvolume_recursively "$i"
done

No manual intervention needed.

Container Health

bash
# List running containers
machinectl list

# Check a specific container's status
machinectl status traefik

# View container logs
journalctl -M traefik -f

# Restart a container
sudo machinectl restart traefik

Checking for Failed Services

bash
# List all failed units
systemctl --failed

# On the server, also check inside containers
for c in traefik authelia adguard immich vaultwarden opencloud; do
  echo "=== $c ==="
  machinectl shell $c /run/current-system/sw/bin/systemctl --failed
done

Minimal Server Packages

The server intentionally ships very few packages to minimise attack surface:

nix
environment.systemPackages = with pkgs; [
  btop    # System monitor
  yazi    # File manager
  helix   # Text editor
  lynis   # Security auditor
  agenix  # Secrets management CLI
];

Documentation, fonts, XDG, man pages, and the dynamic linker stub are all disabled. See Server Overview for the full list of disabled features.