Fleet
NixOS fleet lifecycle CLI with DAG workflow orchestration.
Fleet manages NixOS machines — deploy, build, diff, status, rollback, reboot — with tag-based targeting and composable multi-step workflows defined in YAML.
Install
# Nix flake
# Or add as a flake input
;
Quick start
Fleet reads its node registry from the FLEET_NODES environment variable (JSON).
The typical setup is a Nix wrapper that injects this at runtime:
fleet-wrapped = pkgs.writeShellScript "fleet" ''
export FLEET_NODES='${builtins.toJSON nodeRegistry}'
export FLEET_FLAKE_DIR="$(git rev-parse --show-toplevel 2>/dev/null || echo "$PWD")"
exec ${fleet}/bin/fleet "$@"
'';
The node registry is a JSON object:
Commands
fleet deploy <targets> Deploy NixOS configurations (deploy-rs / colmena)
fleet build <targets> Build without activating
fleet diff <targets> Show closure diff (current vs. new)
fleet status [targets] Show generation, uptime, kernel, NixOS version
fleet ping [targets] Check SSH connectivity
fleet exec <targets> -- <cmd> Run command on remote nodes
fleet rollback <targets> Rollback to previous generation
fleet reboot <targets> Reboot nodes
fleet ssh <node> Open interactive SSH session
fleet info Print node registry
fleet flow list List defined workflows
fleet flow run <name> Execute a workflow
Targeting
Targets can be node names, @tag selectors, or --all:
Configuration
Fleet reads fleet.yaml from FLEET_FLAKE_DIR (or the current directory). All sections
are optional.
# Global SSH defaults
ssh:
connect_timeout: 5
strict_host_key: accept-new
options:
ServerAliveInterval: "60"
ServerAliveCountMax: "3"
# Deploy defaults
deploy:
show_trace: false
magic_rollback: true
# Per-node overrides
nodes:
bastion:
ssh:
connect_timeout: 15
options:
ProxyJump: "jump.example.com"
# Lifecycle hooks
hooks:
deploy:
pre: "echo 'deploying $FLEET_NODE'"
post: "echo 'deployed $FLEET_NODE'"
build:
pre: "git diff --quiet HEAD || echo 'WARNING: uncommitted changes'"
Hooks
Hooks run shell commands before (pre) and after (post) fleet operations. Available
for: deploy, build, diff, exec, rollback, reboot.
- Pre-hooks abort the operation on failure.
- Post-hooks warn but continue.
Environment variables set during hook execution:
| Variable | Description |
|---|---|
FLEET_NODE |
Node name |
FLEET_HOST |
Hostname |
FLEET_USER |
SSH user |
Flows
Flows are named DAG workflows defined in fleet.yaml. Steps declare dependencies and
fleet resolves them into topological execution levels.
flows:
deploy-cluster:
description: "Build, diff, then rolling deploy with health checks"
steps:
- id: build
action:
targets:
- id: diff
action:
targets:
depends_on:
- id: confirm
action:
type: shell
command: |
echo "Review the diff above. Press enter or Ctrl-C to abort."
read
depends_on:
- id: deploy-server
action:
targets:
depends_on:
- id: health-check
action:
type: shell
command: "ssh root@server kubectl get nodes >/dev/null && echo 'healthy'"
depends_on:
- id: deploy-agent
action:
targets:
depends_on:
Action types
| Type | Description |
|---|---|
build |
nix build / colmena build |
deploy |
deploy-rs / colmena apply |
diff |
Closure diff (current vs. new) |
status |
Node status |
ping |
SSH connectivity check |
exec |
Remote command (command: ["systemctl", "status"]) |
shell |
Local shell command (command: "echo hello") |
rollback |
Rollback NixOS generation |
reboot |
Reboot nodes |
darwin-rebuild |
Run nix run .#darwin-rebuild |
home-manager-rebuild |
Run nix run .#home-manager-rebuild |
flake-update |
Run nix flake update (optional inputs: [...]) |
Dry-run
Preview the execution plan without running anything:
Execution plan (dry-run):
Level 1:
build [build] targets: server, agent
Level 2:
diff [diff] targets: server, agent
depends_on: build
Level 3:
confirm [shell] targets: (inherit CLI targets)
depends_on: diff
Level 4:
deploy-server [deploy] targets: server
depends_on: confirm
Level 5:
health-check [shell] targets: (inherit CLI targets)
depends_on: deploy-server
Level 6:
deploy-agent [deploy] targets: agent
depends_on: health-check
Conditions
Steps can have a condition — a shell command that must succeed for the step to execute.
If the condition fails, the step is skipped.
- id: deploy-canary
action:
targets:
condition:
command: "test -f .canary-enabled"
depends_on:
Backend tools
Fleet dispatches to existing NixOS deployment tools:
- Single node — deploy-rs (magic rollback)
- Multiple nodes — colmena (parallel apply)
- Diff —
nix store diff-closures - Build —
nix build/colmena build
These must be on PATH when fleet runs. The Nix wrapper typically handles this.
License
MIT