zds#
a zig implementation of an at protocol personal data server.
name credit: jim (
calabro.io) suggestedzds.
zds stores atproto accounts, repos, records, blobs, sessions, and identity
state. it uses zat for atproto primitives such as syntax,
did resolution, jwt helpers, dag-cbor, car, mst, repo verification, and key
encoding.
references#
the implementation is informed by:
tranquil.farm/tranquil-pdsfutur.blue/pegasusbluesky-social/pdsandbluesky-social/atproto/packages/pdsalice.mosphere.at/atproto-smokechadtmiller.com/pds.jszzstoatzz.io/pds-message-poczzstoatzz.io/pollzhaileyok/cocoon
run locally#
zig build test
zig build run -- --port 2583 --db dev/zds.sqlite3
caddy run --config dev/Caddyfile
before committing:
zig build test
tools/smoke.sh
zig zen
endpoints#
current server surface includes:
GET /GET /.well-known/did.jsonGET /.well-known/atproto-didGET /xrpc/_healthGET /xrpc/com.atproto.server.describeServerPOST /xrpc/com.atproto.server.createAccountPOST /xrpc/com.atproto.server.createSessionPOST /xrpc/com.atproto.server.refreshSessionGET /xrpc/com.atproto.server.getSessionGET /xrpc/com.atproto.server.getServiceAuth- repo read/write/import/blob endpoints
- sync repo/blob/status endpoints, including
subscribeRepos - identity plc credential/sign/submit endpoints
- generic XRPC service proxying for requests that include
atproto-proxy
blob uploads default to 100000000 bytes. set
ZDS_BLOB_UPLOAD_LIMIT or --blob-upload-limit to change it.
see docs/smoke.md for the first atproto-smoke run.
deploy#
run behind a public https origin:
ZDS_RESEND_API_KEY=... \
ZDS_EMAIL_FROM='ZDS <pds@example.com>' \
ZDS_BLOB_UPLOAD_LIMIT=100000000 \
ZDS_BLOBSTORE_PATH=/var/lib/zds/blobs \
ZDS_HANDLE_DOMAINS='.example.com,example.com' \
ZDS_CRAWLERS='https://bsky.network,https://vsky.network' \
ZDS_JWT_SECRET='at-least-32-random-bytes-here' \
zig build run -- \
--port 2583 \
--db /var/lib/zds/zds.sqlite3 \
--public-url https://pds.example.com \
--server-did did:web:pds.example.com
configuration:
--public-url: public pds origin used in did credentials and blob urls--server-did: pds service did, usuallydid:web:<host>ZDS_HANDLE_DOMAINS: comma-separated handle domains advertised bydescribeServerZDS_JWT_SECRET: stable secret for access and refresh jwt signingZDS_RESEND_API_KEYandZDS_EMAIL_FROM: email delivery for account and plc tokensZDS_BLOB_UPLOAD_LIMIT: genericcom.atproto.repo.uploadBlobbody limitZDS_BLOBSTORE_PATHor--blobstore-path: disk blobstore rootZDS_CRAWLERS: comma-separated relay crawl targets
account migration#
zds implements the pds endpoints used by browser-based migration tools such as pds moover:
- service-auth-gated
createAccountfor an existing did - repo car import/export
- missing blob reporting and blob upload
- recommended did credentials
- plc operation email token, signing, and submission
- account activation/deactivation and status checks
see docs/migration.md.
storage#
sqlite stores accounts, records, repo blocks, commits, expected blobs, imported
blob metadata, oauth requests, and auth tokens. uploaded blob bytes are stored
in the disk blobstore rooted at ZDS_BLOBSTORE_PATH.
next#
- password reset and account recovery flows
- object-store blob backend
- backup/restore docs for the sqlite database and blob store