"I want my CI to deploy a new service version without downtime, without me on the keyboard, and with the deploy failing loudly if something's wrong instead of leaving the production tunnel half-up."
asd's CI story is built from four primitives: a headless login, an
idempotent apply, a verify step, and a clean rollback. Strung
together they give you a deploy that's safe to retry.
You need:
asd token create or your tunnel server's admin UI.asd installed (curl -fsSL https://asd.host/install.sh | bash works in CI too).Two topologies for "where does asd net apply actually run":
asd commands). The deploy host holds the asd state.asd or rsync. Less common.This page assumes topology 1.
# CI step: authenticate without a browser
$ asd login key "$ASD_API_KEY"
✓ Authenticated as <client-id>
Where ASD_API_KEY is a CI secret. The login persists for the
session — re-runs cheap, no token-refresh logic needed in your
pipeline.
For env-var-only deploys (no persistence): asd auth export prints
the credentials in a form your CI's docker run can pass.
$ asd net apply
✅ Apply complete: 0 seeded, 12 routes
Idempotent. If the manifest hasn't changed, 0 seeded and the
existing routes stay up. Re-runs are safe — same input → same state.
$ asd net verify
✓ my-app: HTTP 200 (350ms)
✓ api: HTTP 200 (120ms)
✓ admin: HTTP 200 (200ms)
Returns non-zero if any service fails. Wire this into your CI's
"deploy succeeded" gate.
For a more thorough check (Docker health + Caddy reachability + tunnel
state):
$ asd doctor
asd doctor — 6 probe(s) — overall: ✅ pass
Both net verify and doctor exit non-zero on failure. Your CI
should fail loudly if either does.
# In a CI failure handler
$ git checkout HEAD~1 -- packages/<svc>/net.manifest.yaml
$ asd net apply
$ asd net verify
Roll back the manifest to the previous commit, re-apply, re-verify.
Same primitives, no special rollback API.
For more elaborate rollback (DB migrations, asset rollback) you'll
want a higher-level orchestrator — asd's surface is "routes +
tunnels", which is one slice of the deploy story.
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install asd
run: curl -fsSL https://asd.host/install.sh | bash
- name: Authenticate
env:
ASD_API_KEY: ${{ secrets.ASD_API_KEY }}
run: asd login key "$ASD_API_KEY"
- name: Deploy
run: |
ssh deploy@prod 'cd /opt/my-app && git pull && asd net apply && asd net verify'
- name: Smoke test
run: |
curl -fsS --max-time 10 https://my-app-xyz1.eu2.tn.example.com/healthz
The "Deploy" step does the actual work; the "Smoke test" step is the
external sanity check (because asd net verify runs on the deploy
host, not from outside).
A passing CI run leaves the new routes live and the verifier green.
A failing CI run leaves the previous state in place (net apply
applies a diff; on failure the previous state is what stays).
If net apply itself fails halfway through (e.g. a partial Caddy
config update), the next net apply converges — it's diff-based,
not transactional. For genuinely transactional deploys, run
asd caddy config > /tmp/before.json before the apply and
asd caddy config > /tmp/after.json after, then have your CI diff
them.
Idempotent apply means safe retries. CI runners flake.
Re-running asd net apply on a clean tree is a no-op. Re-running
after a partial failure converges. You never have to write
"have we already applied this?" logic in your pipeline.
Headless login = no browser dance. asd login key is
specifically the CI-friendly path. The interactive OAuth flow
(asd login) is for humans. The two coexist — your laptop and
your CI use different sessions on the same tunnel server.
Verify is built into the binary. No external monitor needed
to gate a deploy. asd net verify and asd doctor are the same
checks you'd run by hand for triage, so the CI failure modes
match the human ones.
Rollback is just git. Because routes are declared in the
manifest, "roll back the route" is "roll back the file". No
per-deploy snapshot to restore, no API to call.
cookbook/debug-a-broken-route — the same decision tree applies in a CI shell.learn/04-multi-environment — set MODE per CI job.reference/cli/index § auth + login — every credential command.