GETTING STARTED WITH SSH FLEETS IN SWAMP
In this tutorial, we will declare a fleet of three SSH hosts as one Swamp behavior. Then we will ask Swamp which hosts a tag and a CEL expression match, and run a command on the hosts that match.
What we will build
We will build a behavior named web-fleet of type @swamp/ssh. It holds two
web hosts and one database host, all tagged prod. We will write a record for
each host, resolve two selectors against the fleet without opening any
connection, and run uptime on the web hosts. Each host records its own result.
Prerequisites
- Swamp installed (see Install Swamp) and signed
in with
swamp auth login - A terminal open in an initialized Swamp repository
- Three hosts you can reach over SSH as the user
deploy, with your key loaded in ssh-agent. This tutorial uses the addresses 10.0.0.11, 10.0.0.12 and 10.0.0.21. If your hosts have other addresses, use those in the definition below.
Pull the extension
First, we pull the extension that provides the @swamp/ssh behavior type:
swamp extension pull @swamp/sshYou will see output like:
INF extension·pull: Pulling "@swamp/ssh"@"2026.10.13.1"
INF extension·pull: Identity verified: "@swamp/ssh"@"2026.10.13.1"
INF extension·pull: Pulled "@swamp/ssh"@"2026.10.13.1"
INF extension·pull: Extracted 14 files:Declare the fleet
Now we create a behavior named web-fleet of type @swamp/ssh. If you have not
created a behavior before,
Create and Run a Behavior
shows how. We give it these global arguments:
globalArguments:
name: web-fleet
transport:
kind: ssh
user: deploy
port: 22
auth:
kind: key
connectTimeoutSec: 10
extraOptions: []
controlMaster:
enabled: true
persistSec: 600
hosts:
- name: web-1
address: 10.0.0.11
tags: [web, prod]
attrs: {}
- name: web-2
address: 10.0.0.12
tags: [web, prod]
attrs: {}
- name: db-1
address: 10.0.0.21
tags: [db, prod]
attrs: {}Notice that the connection settings appear once, under transport, and every
host uses them. Notice also the tags: web-1 and web-2 are tagged web,
db-1 is tagged db, and all three are tagged prod.
Write the host records
Next, we run apply:
swamp behavior run web-fleet applyThis command writes one host resource for each of web-1, web-2 and db-1.
If you later remove a host from hosts, the next apply deletes its record.
Resolve the web tag
Before we run anything on a host, we ask the fleet which hosts the tag web
matches:
swamp behavior run web-fleet resolve --input hosts=webThis command does not connect to any host. It writes a selection resource that
lists the matched hosts, web-1 and web-2, and a match count of 2.
Notice that the selection holds addresses, tags and attrs but no credentials.
Resolve with a CEL expression
Now we use a CEL expression as the selector. The cel: prefix marks it as an
expression:
swamp behavior run web-fleet resolve --input 'hosts=cel:"prod" in host.tags'This command writes another selection resource. This time it lists all three
hosts, because each one carries the prod tag.
Run a command on the web hosts
Finally, we run uptime on the hosts that the web tag matched:
swamp behavior run web-fleet exec --input hosts=web --input command=uptimeThis command connects to web-1 and web-2 in parallel and runs uptime on
each. It writes one resource per host, run-exec-web-1 and run-exec-web-2,
holding that host's exit code and output. If one host fails, the method fails,
and that host's resource shows the exit code it returned.
Notice that db-1 was not touched. The selector decided which hosts the command
ran on, and resolve showed us that set before we ran anything.
What we built
We declared a three-host fleet as one @swamp/ssh behavior, wrote a record for
each host, and resolved a tag and a CEL expression to sets of hosts without
connecting to any of them. Then we ran a command on the web hosts, with a
separate result for each one.
Understanding SSH automation in Swamp
describes how these pieces fit together.