declarative relay deployment on hetzner relay.waow.tech
atproto
Zig 25.4%
HTML 16.4%
Just 15.6%
Go 12.8%
HCL 3.7%
Shell 0.7%
Other 25.4%
65 1 0

Clone this repository

https://tangled.org/zzstoatzz.io/relay https://tangled.org/did:plc:xbtmt2zjwlrfegqvch7fboei/relay
git@knot.tangled.wizardry.systems:zzstoatzz.io/relay git@knot.tangled.wizardry.systems:did:plc:xbtmt2zjwlrfegqvch7fboei/relay

For self-hosted knots, clone URLs may differ based on your setup.

Download tar.gz
README.md

ATProto relay deployments#

experimental — this is a personal project for learning ATProto infrastructure. the endpoints below may go down, lose data, or change without notice. do not depend on them for anything that matters.

two full-network ATProto relays on independent Hetzner Cloud nodes with k3s:

indigo (Go) zlay (Zig)
firehose wss://relay.waow.tech wss://zlay.waow.tech
jetstream wss://jetstream.waow.tech/subscribe (sidecar)
collectiondir sidecar on same endpoint built-in (inspired by lightrail)
health relay.waow.tech/xrpc/_health zlay.waow.tech/_health
metrics relay-metrics.waow.tech zlay-metrics.waow.tech
source bluesky-social/indigo zzstoatzz.io/zlay

try it#

both scripts are self-contained uv scripts — no virtualenv or install needed.

firehose#

consumes the raw CBOR firehose using the atproto python SDK.

# watch posts scroll by for 10 seconds
./scripts/firehose

# run longer, filter by collection
./scripts/firehose --duration 30
./scripts/firehose --collection app.bsky.feed.like
./scripts/firehose --duration 0  # forever (ctrl-c to stop)

# point at a different relay
./scripts/firehose --relay-url wss://zlay.waow.tech
./scripts/firehose --relay-url wss://bsky.network

jetstream#

consumes the simplified JSON firehose via jetstream — no atproto SDK needed, just plain websockets.

# watch all events for 10 seconds
./scripts/jetstream

# filter to specific collections
./scripts/jetstream --collection app.bsky.feed.post
./scripts/jetstream --collection app.bsky.feed.like --collection app.bsky.graph.follow

# run longer, or forever
./scripts/jetstream --duration 30
./scripts/jetstream --duration 0  # forever (ctrl-c to stop)

# point at a different jetstream instance
./scripts/jetstream --url wss://jetstream1.us-east.bsky.network

what's here#

.
├── indigo/            # Go relay (indigo) — justfile, deploy configs, terraform
├── zlay/              # zig relay (zlay)  — justfile, deploy configs, terraform
├── shared/deploy/     # helm values shared by both deployments
├── scripts/           # uv scripts — firehose, jetstream, backfill
├── docs/              # architecture, deployment guide, backfill
└── justfile           # root — `just indigo <recipe>` / `just zlay <recipe>`

each relay is a just module with symmetric recipes:

just indigo deploy     # deploy Go relay
just indigo status     # check Go relay pods
just zlay deploy       # deploy zig relay
just zlay status       # check zig relay pods
just --list            # see all available recipes

why#

the ATProto relay is the piece of infrastructure that aggregates writes from every PDS on the network into a single firehose stream. downstream services (appviews, feed generators, labelers) subscribe to a relay instead of crawling thousands of individual servers.

running one is surprisingly cheap — the relay binary uses modest CPU and memory, and storage requirements are manageable. the main cost driver is bandwidth, which is why Hetzner (unlimited 1 Gbps) is a good fit.

this repo is a template for deploying your own. everything is declarative: terraform for the VM, helm for the workloads, a justfile to tie it together. see docs/deploying.md for setup instructions and docs/architecture.md for how the pieces fit together.

prior art#