Tempest #
Tempest is a self-hostable AT Protocol Personal Data Server (PDS) built with Elixir and Phoenix.
It stores accounts, repos, records, blobs, sessions, identity state, OAuth state, migration state, and operator backup metadata.

Features #
- Hosts AT Protocol accounts with local SQLite-backed repo storage.
- Implements the core
com.atproto.server,identity,repo, andsyncPDS XRPC surfaces. - Serves CAR exports, blobs, repo status, and a live/backfilled firehose.
- Supports local filesystem blobs and S3-compatible blob/backup storage.
- Provides browser account tools under
/account. - Provides browser admin/operator tools under
/admin. - Supports account migration, repo import/export, backup verification, app passwords, DPoP/OAuth primitives, and compatibility-focused AppView fallbacks.
Tempest is a PDS, not an AppView. Known PDS-owned methods are handled locally;
unknown app.bsky.* and chat.bsky.* methods can proxy to an upstream AppView
when configured.
Quick Start #
mix setup
mix phx.server
The development server runs at http://localhost:4000.
For local configuration, disposable data directories, admin bootstrap, smoke tests, and reset commands, see DEVELOPMENT.md.
Running It #
Local development uses Phoenix directly and stores data under priv/tempest_dev
by default.
Release and reverse-proxy examples live in conf/:
conf/Dockerfilebuilds a Phoenix release image.conf/docker-compose.ymlruns Tempest locally.conf/Caddyfilefronts Tempest with Caddy for HTTPS.conf/.env.exampleis the production env template.
Real federation checks need a public HTTPS hostname with DNS pointing at the host. Localhost is enough for most development and Hurl smoke tests, but relays, handle resolution from outside the host, and real client OAuth flows need a reachable origin.
Configuration #
The main runtime settings are:
| Variable | Purpose |
|---|---|
TEMPEST_HOSTNAME |
Bare hostname served by this PDS. |
TEMPEST_PUBLIC_URL |
Public origin, including scheme. |
TEMPEST_DATA_DIR |
Durable SQLite, blob, temp, and backup directory. |
TEMPEST_HOSTED_DID_METHOD |
Hosted DID method, currently plc or web. |
TEMPEST_CRAWLERS |
Comma-separated relay crawler URLs. |
TEMPEST_APPVIEW_URL |
Optional upstream AppView proxy target. |
TEMPEST_ADMIN_DID |
DID allowed to use the browser admin UI. |
TEMPEST_ADMIN_TOKEN_HASH |
Optional Argon2 hash for admin bearer-token automation. |
TEMPEST_BLOB_STORE |
local by default, or s3 with S3 env vars. |
TEMPEST_BACKUP_STORE |
local by default, or s3 with S3 env vars. |
TEMPEST_SMTP_ENABLED |
Enables SMTP email delivery when true. |
See conf/.env.example for the full production template
and deployment documentation for operational
guidance.
Storage and Backups #
Tempest keeps the account database, sequencer database, per-account repo
databases, local blobs, temp files, and backups under TEMPEST_DATA_DIR.
Local storage is the default. S3-compatible storage is available for blobs and
operator backups through the TEMPEST_BLOB_* and TEMPEST_BACKUP_* env groups.
The admin UI exposes storage and backup status under /admin/storage and
/admin/backups.
Admin and Account UI #
Account operator & admin routes are at /account & /admin respectively.
Browser admin access is anchored to TEMPEST_ADMIN_DID.
Admin bearer tokens are optional and intended for automation; only the Argon2 hash belongs in configuration.
Endpoint Checklist #
The canonical, coverage-aware matrix is
docs/reference/pds-compatibility.md.
The checklist below is a README-sized status snapshot. Operational/admin routes
are listed separately because they are Tempest service routes, not AT Protocol
Lexicon methods.
Server and Account #
- [~]
com.atproto.server.requestPasswordReset - [~]
com.atproto.server.resetPassword - [~]
com.atproto.server.confirmEmail - [~]
com.atproto.server.requestEmailConfirmation - [~]
com.atproto.server.requestEmailUpdate - [~]
com.atproto.server.updateEmail
Identity #
Repository #
Sync #
AppView Compatibility #
Operational and Admin #
Verification #
Tempest uses executable Hurl scripts as black-box PDS checks. The smoke suite exercises the same HTTP and WebSocket surface that clients, relays, and operators use, namely account creation, auth, repo writes, CAR reads, blob lifecycle, firehose events, metadata, proxy fallback, and admin protection.
Common local checks:
mix test
mix precommit
test/smoke/local-pds-compat.sh http://localhost:4000
The smoke profile expects a running server. Deployed-only smoke checks cover
public HTTPS, admin-token status, and relay crawler behavior. See
test/smoke/README.md and
interop-testing for
full Hurl usage.
Documentation #
- Development
- Deployment
- PDS compatibility
- Architecture
- Admin operations
- Interop testing
- Storage and SQLite
- Sync and firehose
The deployed docs viewer is available at https://tempest.desertthunder.dev/docs.

The changelog is available in CHANGELOG.md and at https://tempest.desertthunder.dev/changelog.

References #
- Official TypeScript PDS
- Cocoon, a PDS written in Go
- Tranquil, a PDS written in Rust
- Pegasus, a PDS written in OCaml
- ZDS, a PDS written in Zig