Quickstart
The minimum path from a fresh repo to a single managed host. For multi-host fleets, see RFC-0001 (fleet.nix) and the operator cookbook. For the unattended signed-rollout machinery, see architecture and RFC-0002 (reconciler).
A minimal host
mkFleet is the typical path even for a single host: declare the host, channel, and rollout policy; the framework wires the per-host nixosSystem for you. Direct nixfleet.lib.mkHost is also supported for one-off setups (the rest of this section uses mkFleet; see lib/mk-host.nix for the direct primitive).
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
nixfleet.url = "github:arcanesys/nixfleet";
};
outputs = { nixpkgs, nixfleet, ... }: let
fleet = nixfleet.lib.mkFleet {
hosts.my-server = {
system = "x86_64-linux";
channel = "stable";
tags = [];
nixosArgs = {
hostSpec.userName = "deploy";
modules = [
nixfleet.scopes.persistence.impermanence
nixfleet.scopes.secrets
./hardware-configuration.nix
({ ... }: {
users.users.deploy = {
isNormalUser = true;
extraGroups = [ "wheel" ];
openssh.authorizedKeys.keys = [ "ssh-ed25519 AAAA..." ];
};
services.nixfleet-agent = {
enable = true;
controlPlane.url = "https://cp.example.com:8080";
};
})
];
};
};
channels.stable = {
rolloutPolicy = "all-at-once";
signingIntervalMinutes = 60;
freshnessWindow = 1440;
};
rolloutPolicies.all-at-once = {
strategy = "all-at-once";
waves = [{ selector.all = true; soakMinutes = 0; }];
};
};
in {
nixosConfigurations = fleet.nixosConfigurations;
};
}
fleet.nixosConfigurations.<host> is a standard nixosSystem (or darwinSystem for Darwin platforms). Nothing in the result is NixFleet-specific — if you remove the agent module, the host is a vanilla NixOS configuration deployable with stock tooling.
Deploy
Standard NixOS / Darwin tooling, no NixFleet-specific glue:
nixos-anywhere --flake .#my-server root@192.168.1.50 # fresh install
sudo nixos-rebuild switch --flake .#my-server # local rebuild
darwin-rebuild switch --flake .#my-mac # macOS
Fleet rollouts are git-driven from this point: commit -> CI signs -> CP polls fleet.resolved.json -> agents pull their per-host target on next checkin. There is no operator CLI verb between commit and host activation. See operator cookbook -> Deploy a fleet change.
Build and install the operator CLI
cargo build --release -p nixfleet-cli
install -m 0755 target/release/nixfleet ~/.local/bin/
Alternatively, run without installing: nix run github:arcanesys/nixfleet#nixfleet-cli -- <subcommand>.
Initialise operator config
nixfleet config init \
--cp-url https://cp.example.com:8080 \
--ca-cert /etc/nixfleet/ca.pem \
--client-cert ~/.config/nixfleet/operator.pem \
--client-key ~/.config/nixfleet/operator.key
Writes ~/.config/nixfleet/config.toml (mode 0600). Override values per-invocation via flags or NIXFLEET_* environment variables. The flag > env > file precedence is locked in tests.
Verify
nixfleet status # rendered fleet table
nixfleet status --json # raw HostsResponse for piping
nixfleet rollout hosts <id> # per-host summary for a rollout
nixfleet rollout events <id> # chronological event-log stream
For the full CLI surface (subcommands, flags, status-label precedence, pin markers), see reference/crates/nixfleet-cli.
Next steps
- Enrol additional hosts: operator cookbook -> Add a host to the fleet
- Mint a bootstrap token: bootstrap-token-lifecycle
- Test the loop locally on VMs first: vm-lifecycle
- Verify your fleet config before pushing: testing
- Recovery runbook if cp goes down: disaster-recovery