Concepts

Machines

Nests are machines you can deploy to. Register, inspect, and target them.

A nest is a machine you deploy to. Your own machine is the first nest, called local. Registering a remote machine makes it a target that projects can name.

The registry

ant nest machines list            # list registered machines
ant nest machines add prod --hostname prod.example.com
ant nest machines add prod --node-id 7f2e…            # already-running worker
ant nest machines add prod --host ADDR --ssh-key ~/.ssh/id_ed25519   # provision over SSH
ant nest machines remove prod
ant nest machines decommission prod --host ADDR --ssh-key ~/.ssh/id_ed25519 --yes
ant nest machines network prod --name ant-prod --driver bridge

add registers a machine by NodeID, or provisions it over SSH when --host is given (--ssh-user, --ssh-port, --ssh-key, --ssh-password / --ssh-password-stdin, --docker-mode, --no-caddy, --no-caddy-check, and --id). decommission reverses provisioning on the machine over SSH (--purge also removes the worker user, state, containers, images, and networks; --keep-record keeps the local entry). network shows or sets the machine-wide network. See Remote machines.

Each machine has a stable key (local, prod, …) and the machine it points at. A project targets one by name via machine: in ant.yaml.

Everything nests under a machine

In schema v2, groups, projects, and Caddy settings belong to a machine:

machines
└── local
    ├── caddy        { auto_start: true }
    ├── docker       { mode: rootless }
    ├── network      { name: ant-local }
    ├── groups       { backend: { network: {…}, domains: [example.com] } }
    └── project_dirs [ /home/me/code/api, /home/me/code/worker ]

This is what makes remote deploys coherent: a group and its project directories are facts about a machine, not about your laptop in the abstract. When a project joins a group, its directory moves to the group.

v1 configs migrate on load; a top-level local object folds into machines.local, flat groups/project_dirs/caddy are nested, and a legacy group carrying a machine: field nests under that machine.

Inspecting a machine

ant nest                      # overview of the local machine (--json)
ant nest ping [machine]       # is the worker reachable? is iroh available? (--timeout)
ant nest doctor               # Docker, Caddy, docker mode, tools (--machine M for a nest)
ant nest identity show        # a machine's NodeID
ant nest identity generate    # create a machine identity (--force)
ant nest audit                # tamper-evident action log (--limit, --json)
ant nest state export --out state.json   # back up roster and invites
ant nest state import --file state.json  # restore (owner-only; --force)
ant nest tools                # inspect tools (also install | allow-ports)
ant nest tunnel --container app --port 8080   # forward a local port over iroh

ant nest ping reports that iroh is unavailable on platforms built without the transport (see Installation). ant nest doctor checks the Docker daemon, Caddy, the docker mode, and tools; locally, or over the worker RPCs with --machine M (host-level port grants are reported as not applicable remotely). ant nest tunnel reaches a published container port from your machine without opening one on the nest; see Tunnels.

Privileged work is operator-run

Ant's worker never invokes sudo. Provisioning a machine (installing the worker, opening ports) is an operator action; ant nest bootstrap --host runs the same steps over SSH through the SSH user's sudo:

ant nest bootstrap            # print the root-run steps for a machine
ant nest reconcile --apply    # run them (root)

The worker itself runs unprivileged. See Security model.

Copyright © 2026