Skip to main content

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/ssh

You 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 apply

This 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=web

This 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=uptime

This 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.