A service is a reusable piece of functionality you can add to your machines. Services handle things like backups, networking, user management, and installing packages, all configured from your clan.nix file.
Instead of manually installing software and editing config files on each machine, you declare what services you want, and Clan sets everything up for you.
Every service follows the same pattern:
clan.nixclan machines update <machine-name>The simplest service is packages, which installs software on your machines:
# clan.nix
inventory.instances = {
packages = {
roles.default.machines."test-machine".settings = {
packages = [ "bat" "htop" "ripgrep" ];
};
};
}; Then deploy:
clan machines update test-machine SSH into your machine:
clan ssh test-machine and verify:
bat --version
htop --version To remove a package, delete it from the list and run update again. That's declarative configuration, where your machine matches what's in your config file.
Services have roles that define different behaviors. For example, a backup service has:
inventory.instances = {
borgbackup = {
roles.client.machines."my-laptop" = {};
roles.client.machines."my-desktop" = {};
roles.server.machines."backup-server" = {};
};
}; This says: "Back up my laptop and desktop to my backup server."
Different services have different roles. The packages service only has a default role. The wireguard VPN service has controller and peer roles. Check each service's documentation for its available roles.
A tag is a label you attach to machines so you can reference them as a group. Think of it like labeling boxes when you move; you might label some "kitchen," some "bedroom," and some "office." Then when you want to do something to all kitchen boxes, you just look for that label.
Using tags, you can apply services to multiple machines at once. Every machine automatically has the all tag.
inventory.instances = {
packages = {
# Install these packages on ALL machines
roles.default.tags = [ "all" ];
roles.default.settings.packages = [ "vim" "git" "curl" ];
};
}; You can also define custom tags in your machine definitions:
inventory.machines = {
laptop = {
deploy.targetHost = "root@192.168.0.10";
tags = [ "workstation" ];
};
desktop = {
deploy.targetHost = "root@192.168.0.11";
tags = [ "workstation" ];
};
server = {
deploy.targetHost = "root@192.168.0.12";
tags = [ "server" ];
};
}; Then you can use the above tags:
inventory.instances = {
packages = {
# Only workstations get these packages
roles.default.tags = [ "workstation" ];
roles.default.settings.packages = [ "firefox" "vlc" ];
};
}; Most services have configurable settings. Here's the WiFi service with settings:
inventory.instances = {
wifi = {
roles.default.machines."my-laptop" = {
settings.networks.home = {};
settings.networks.office = {};
};
};
}; When you run clan vars generate, it will prompt you for the SSID and password for each network.
Here's borgbackup with settings:
inventory.instances = {
borgbackup = {
roles.client.machines."my-laptop" = {
settings.startAt = "*-*-* 02:00:00"; # Backup at 2 AM daily
};
roles.server.machines."backup-server" = {};
};
}; You can add as many services as you need:
inventory.instances = {
# SSH access
sshd = {
roles.server.tags = [ "all" ];
roles.server.settings.authorizedKeys = {
"admin" = "ssh-ed25519 AAAA... admin@example.com";
};
};
# Install packages
packages = {
roles.default.tags = [ "all" ];
roles.default.settings.packages = [ "vim" "htop" ];
};
# WiFi (for laptops)
wifi = {
roles.default.machines."laptop" = {
settings.networks.home = {};
};
};
# Backups
borgbackup = {
roles.client.tags = [ "all" ];
roles.server.machines."backup-server" = {};
};
}; One clan machines update command applies all of these services.
Clan includes 30+ built-in services:
| Service | What It Does |
|---|---|
packages | Install packages from nixpkgs |
sshd | SSH server with key management |
users | User accounts and passwords |
wifi | WiFi network configuration |
borgbackup | Encrypted backups |
syncthing | Peer-to-peer file sync |
wireguard | VPN networking |
zerotier | Mesh networking |
monitoring | Prometheus + Grafana |
matrix-synapse | Chat server |
See the full list in the Services Reference (Link coming soon).
Here's the typical workflow when adding services:
# 1. Edit clan.nix to add/modify services
# 2. Generate any secrets (passwords, keys, etc.)
clan vars generate test-machine --no-sandbox # --no-sandbox for Ubuntu
# 3. Deploy to the machine
clan machines update test-machine
# 4. Verify on the machine
ssh root@<ip> When you run clan machines update:
nixos-rebuild switch runs on the targetNo manual steps on the target machine. No logging in to install packages or edit config files. Everything is defined in your clan.nix and applied with one command.