Hosts
Hosts, roles, SSH connection settings, local execution mode, inventory-vs-deploy targets, and the unreachable-host policy.
A host is one deploy target, tagged with the roles it fills.
Hosts usually live in the per-stage file, with connection defaults in the shared ssh: block.
hosts:
- address: web1.example.com
roles: [ app, web ]
- address: db1.example.com
roles: [ db ]
user: dbadmin # override ssh.user for this host
port: 2222 # override ssh.port
identity_file: ~/.ssh/db_key
| Field | Description |
|---|---|
address | Hostname or IP (required unless local: true). |
roles | Roles this host fills, tasks/hooks target by role. |
user / port / identity_file | Per-host SSH overrides. |
local | Run on the operator’s machine via the local shell - see local mode. |
deploy | false keeps the host in inventory without deploying - see below. |
required | true makes its unreachability always fatal - see unreachable. |
Roles let one task hit a subset of the fleet: a task with roles: [db] runs only on db hosts.
The --roles / --host flags narrow any action further (see Usage -> Targeting).
SSH connection settings
Defaults applied to every host. A host may override user/port/identity_file.
ssh:
user: deploy
port: 22
identity_file: ~/.ssh/deploy_key # optional, ssh-agent is also used
known_hosts_file: ~/.ssh/known_hosts # optional custom path
strict_host_key: true # verify host keys (default true)
forward_agent: false # forward your ssh-agent to the host (for remote git auth)
forward_key: ~/.ssh/deploy # OR forward just this one key, in-memory
- Auth uses your
ssh-agent(SSH_AUTH_SOCK) and/oridentity_file. - Host keys are verified against
~/.ssh/known_hostsby default. Setstrict_host_key: falseto skip, orknown_hosts_filefor a custom path. A single task can override this with its ownstrict_host_key: false(see Tasks) - for ephemeral hosts whose key is legitimately unknown (e.g. ASG instances from one AMI), without loosening the rest of the deploy. - Agent forwarding lets the remote
gitclone/fetch authenticate with your credentials (e.g. for a private repo).forward_keyforwards a single unencrypted key in memory (never written to the host) and takes precedence overforward_agent. Forwarding is best-effort: a host withAllowAgentForwarding nowill still run, but its git won’t see your keys. - Liveness: a new connection times out after ~15s. On an established connection whoosh sends a keepalive every 10s and drops a silent host after 3 misses (~30s) so a dead host fails fast instead of hanging.
Local execution mode
Mark a host local: true to run the entire lifecycle on the current machine through the local shell - no SSH, keys,
or known_hosts needed. Useful for deploying on the box itself, or for development.
Everything else (releases, symlinks, current, rollback, tasks, hooks) is identical.
# deploy/local.yml
hosts:
- address: localhost
local: true
roles: [ app, web, db ]
Local and remote hosts can coexist in one stage, each running over its own transport.
Inventory vs deploy targets
By default, every host is a deployment target.
Set deploy: false to keep a host in the inventory - visible in config and the deploy:hosts table - without
deploying to it. Such hosts are excluded from the lifecycle, tasks, hooks, and ad-hoc run.
hosts:
- address: web1.example.com
roles: [ app, web ]
- address: bastion.example.com
roles: [ ops ]
deploy: false # listed, but never deployed to
This pairs with dynamic inventory: a plugin can discover a fleet and flag which hosts
to deploy to (see aws:ec2:inventory deploy_tag).
Two task flags change which hosts a task targets:
non_deploy: true- only thedeploy:falsehosts (inverts the default). For acting on hosts you don’t deploy to, e.g. healthchecking ASG instances booted from a baked AMI.all_hosts: true- every host, ignoring thedeployflag. For a task that should hit the whole fleet (e.g. collecting disk usage). Wins overnon_deploy.
Roles and --roles/--host still narrow within the chosen set.
tasks:
asg-healthcheck:
non_deploy: true # only deploy:false hosts
strict_host_key: false # ASG hosts share a key / rotate IPs -> skip known_hosts
scripts:
- path: healthcheck.sh
disk-usage:
all_hosts: true # every host in the stage
cmds: [ "df -h /" ]
A task’s strict_host_key (true/false) overrides the stage’s ssh.strict_host_key for just that task’s
connections - set false for ephemeral hosts whose key isn’t in known_hosts (the override applies when the
connection is first opened in a run).
Inventory is captured at process start
Both flags operate on the inventory captured at process start.
A fresh run re-fetches dynamic inventory, so instances created during a deployment (e.g. by an ASG refresh) only appear
on
the next invocation, not to a hook within the same deploy.
Run these as their own post-deploy step (whoosh prod asg-healthcheck), not as a deploy hook.
Unreachable hosts (on_unreachable)
By default, a host that becomes unreachable mid-deploy aborts the whole run.
Set on_unreachable: skip to drop the unreachable host and finish on the survivors.
on_unreachable: skip # abort (default) | skip
hosts:
- address: db1.example.com
roles: [ db ]
required: true # never skip this one - its loss always aborts
- address: web1.example.com
roles: [ app, web ] # skippable under `skip`
abort(default) - any unreachable host fails the deploy.skip- an unreachable host is dropped (from remaining phases and hook tasks), the deploy completes on the rest, skipped hosts are logged, and the command exits non-zero so CI notices.required: truekeeps a critical host from being skipped. The lock-holding primary host is always implicitly required.- The policy applies to unreachable hosts only (a failed dial or a connection lost mid-command).
A command that runs and exits non-zero (e.g. a failed migration) always aborts - use a task’s
continue_on_errorto soften those.