Your CI, on your cloud. Without running a single runner yourself.

Commit an airship.yaml, point runs-on at an airship- label, and every job gets its own machine in your cloud account. Airship launches it, watches it and tears it down.

AWS · Google Cloud · Azure

acme/Runners
live
Busy14
Idle pool2 / 2
Spot71%
Cap14 / 40
JobLabelMachineRegionStateTime
test (ubuntu, node 24)acme/webairship-buildAWSc7i.xlargespotus-east-1busy2m 41s
train-smokeacme/modelsairship-gpuGCPg2-standard-8spotus-central1-blaunching0m 12s
e2e (shard 3/4)acme/webairship-buildAWSm7i.xlargeus-east-1running0m 38s
msbuild releaseacme/desktopairship-windowsAzureStandard_D4s_v5eastusbusy6m 02s
lintacme/apiairship-smallAWSt4g.mediumspotus-west-2pending—
cargo build --releaseacme/engineairship-armAWSc7g.2xlargespoteu-west-1finished4m 19s
.github/workflows/ci.yml
jobs:
  test:
    runs-on: airship-build--${{ github.run_id }}
    steps:
      - uses: actions/checkout@v5
      - run: make test

Your account, your bill

Machines launch in your AWS, Google Cloud or Azure account. You pay the cloud, at your rates.

One file per repo

airship.yaml says what a runner is: machine type, image, region, spot, GPU. runs-on picks it.

Fresh machine per job

Every job gets a new machine that registers for that one job and is gone when it ends.

Spot, then fall back

List instance types in order. Spot capacity first, on-demand when the cloud says no.

Everything a runner needs, in one file

Each repository describes its runners in airship.yaml. Airship turns that into machines.

airship.yaml
runners:
  - name: build
    cloud: aws                 # or gcp · azure
    instance_type: c7i.xlarge
    region: us-east-1
    labels: [airship-build]
 
  - name: windows
    cloud: azure
    instance_type: Standard_D4s_v5
    machine_image:
      publisher: MicrosoftWindowsServer
      offer: WindowsServer
      sku: 2022-datacenter-g2
    labels: [airship-windows]

We run the fleet. You own the machines.

Airship's control plane holds your sealed cloud key, listens to GitHub, and launches, watches and terminates machines in your account. Nothing long-lived runs on your side.

Connect a cloud

A job asks. A machine answers.

GitHub tells Airship a job wants an airship- label. Airship finds the runner in that repository's airship.yaml and launches it in your account, registered for exactly that job.

Labels without the airship- prefix cost no API calls.

cloudaws · us-east-1
access_keyAKIA••••••••••••
secret_key••••••••••••••••••••
sealed · bound to this row
opened forRunInstances→ dropped

Your key, sealed at rest

The access key you connect is encrypted, tied to its own database row, and opened only for the length of one cloud call. It is never logged and never sent back.

Give it a role scoped to what Airship launches.

  1. pending
  2. launching
  3. running
  4. busy
  5. finished

finished, and why

  • completed
  • cancelled
  • idle
  • launch_failed
  • lost
  • max_lifetime

Nothing left running

Every runner moves through one lifecycle, and every ending is recorded. A reconciler compares the cloud with the database and removes machines nobody is using, so a lost answer from the cloud doesn't become a bill.

Idle 10 minutes, or 8 hours old: the machine goes.

  • AWSEC2 · S3 cacheconnected
  • Google CloudCompute Engine · GPUsconnected
  • AzureVirtual Machinesconnected

runs

  • ubuntu2404
  • Windows Server
  • arm64
  • nvidia-l4
  • spot
  • custom AMI
  • gallery image

Runs where your account already is

Connect one cloud or all three. Each runner names its cloud, and machines launch with your credentials, in your regions, on your bill.

Change cloud: in airship.yaml and nothing else.

Your jobs run on machines you own

Airship reads airship.yaml and job events from GitHub and makes cloud calls with your key. Your code, secrets and build output stay between GitHub and your machines.

Runners register with a just-in-time config for a single job, so a machine can't pick up work it wasn't launched for. Only labels starting with airship- are looked up, and only in repositories someone activated.

Your first runner in four steps.

  1. 1Install the GitHub App
  2. 2Connect a cloud
  3. 3Activate a repository
  4. 4Commit airship.yaml
Start for free
airship.yaml
runners:
  - name: build
    cloud: aws
    instance_type: [c7i.xlarge, m7i.xlarge]
    preemptible: [true, false]
    labels: [airship-build]
    extra_config:
      cache: true