Vow, uncensorable PDS written in Go
Go 96.2%
HTML 1.4%
Shell 0.8%
Makefile 0.6%
CSS 0.4%
Dockerfile 0.2%
Other 0.4%
148 1 36

Clone this repository

https://tangled.org/julien.rbrt.fr/vow https://tangled.org/did:plc:7kpq3n7brenbgyp2gx36hl6x/vow
git@knot.srv.rbrt.fr:julien.rbrt.fr/vow git@knot.srv.rbrt.fr:did:plc:7kpq3n7brenbgyp2gx36hl6x/vow

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

Download tar.gz
readme.md

Vow#

WARNING

This is highly experimental software. Use with caution, especially during account migration.

Vow is a PDS (Personal Data Server) implementation in Go for the AT Protocol.

Incoming Features#

  • BYOK (Bring Your Own Key) for PDS — users supply their own signing key for their PDS, keeping full custody of their identity.
  • IPFS for account storage — repository data is stored on IPFS, giving users a decentralised and portable data layer.
  • x402 payments for IPFS storage — IPFS pinning costs are settled via x402, paid directly by the user. The payment key is derived from the user's EVM wallet, so no separate key management is required.
  • Extension for action signing — a browser extension intercepts each write operation sent to the user's PDS and prompts the user to sign it locally, so private keys never leave the client.

Quick Start with Docker Compose#

Prerequisites#

  • Docker and Docker Compose installed
  • A domain name pointing to your server
  • Ports 80 and 443 open

Installation#

  1. Clone the repository

    git clone https://pkg.rbrt.fr/vow.git
    cd vow
    
  2. Create your configuration file

    cp .env.example .env
    
  3. Edit .env with your settings

    VOW_DID="did:web:your-domain.com"
    VOW_HOSTNAME="your-domain.com"
    VOW_CONTACT_EMAIL="you@example.com"
    VOW_RELAYS="https://bsky.network"
    
    # Generate with: openssl rand -hex 16
    VOW_ADMIN_PASSWORD="your-secure-password"
    
    # Generate with: openssl rand -hex 32
    VOW_SESSION_SECRET="your-session-secret"
    
  4. Start the services

    docker-compose pull
    docker-compose up -d
    
  5. Get your invite code

    On first run, an invite code is automatically created. View it with:

    docker-compose logs create-invite
    

    Or check the saved file:

    cat keys/initial-invite-code.txt
    
  6. Monitor the services

    docker-compose logs -f
    

What Gets Set Up#

  • init-keys: Generates cryptographic keys (rotation key and JWK) on first run
  • vow: The main PDS service running on port 8080
  • create-invite: Creates an initial invite code on first run

Data Persistence#

  • ./keys/ — Cryptographic keys (generated automatically)
    • rotation.key — PDS rotation key
    • jwk.key — JWK private key
    • initial-invite-code.txt — Your first invite code (first run only)
  • ./data/ — SQLite database and blockstore

Configuration#

Database#

Vow uses SQLite by default. No additional setup required.

VOW_DB_NAME="/data/vow/vow.db"

SMTP Email#

VOW_SMTP_USER="your-smtp-username"
VOW_SMTP_PASS="your-smtp-password"
VOW_SMTP_HOST="smtp.example.com"
VOW_SMTP_PORT="587"
VOW_SMTP_EMAIL="noreply@example.com"
VOW_SMTP_NAME="Vow PDS"

IPFS Blob Storage#

By default blobs are stored in SQLite. Optionally, blobs can be stored on IPFS via a local Kubo node:

VOW_IPFS_BLOBSTORE_ENABLED=true

# URL of the local Kubo RPC API (default: http://127.0.0.1:5001)
VOW_IPFS_NODE_URL="http://127.0.0.1:5001"

# Optional: redirect getBlob to a public gateway instead of proxying
VOW_IPFS_GATEWAY_URL="https://ipfs.io"

# Optional: remote pinning service
VOW_IPFS_PINNING_SERVICE_URL="https://api.pinata.cloud/psa"
VOW_IPFS_PINNING_SERVICE_TOKEN="your-token"

Management Commands#

Create an invite code:

docker exec vow-pds /vow create-invite-code --uses 1

Reset a user's password:

docker exec vow-pds /vow reset-password --did "did:plc:xxx"

Updating#

docker-compose pull
docker-compose up -d

Implemented Endpoints#

NOTE

Just because something is implemented doesn't mean it is finished. Many endpoints still have rough edges around validation and error handling.

Identity#

  • com.atproto.identity.getRecommendedDidCredentials
  • com.atproto.identity.requestPlcOperationSignature
  • com.atproto.identity.resolveHandle
  • com.atproto.identity.signPlcOperation
  • com.atproto.identity.submitPlcOperation
  • com.atproto.identity.updateHandle

Repo#

  • com.atproto.repo.applyWrites
  • com.atproto.repo.createRecord
  • com.atproto.repo.putRecord
  • com.atproto.repo.deleteRecord
  • com.atproto.repo.describeRepo
  • com.atproto.repo.getRecord
  • com.atproto.repo.importRepo (Works "okay". Use with extreme caution.)
  • com.atproto.repo.listRecords
  • com.atproto.repo.listMissingBlobs

Server#

  • com.atproto.server.activateAccount
  • com.atproto.server.checkAccountStatus
  • com.atproto.server.confirmEmail
  • com.atproto.server.createAccount
  • com.atproto.server.createInviteCode
  • com.atproto.server.createInviteCodes
  • com.atproto.server.deactivateAccount
  • com.atproto.server.deleteAccount
  • com.atproto.server.deleteSession
  • com.atproto.server.describeServer
  • com.atproto.server.getAccountInviteCodes
  • com.atproto.server.getServiceAuth
  • com.atproto.server.refreshSession
  • com.atproto.server.requestAccountDelete
  • com.atproto.server.requestEmailConfirmation
  • com.atproto.server.requestEmailUpdate
  • com.atproto.server.requestPasswordReset
  • com.atproto.server.reserveSigningKey
  • com.atproto.server.resetPassword
  • com.atproto.server.updateEmail

Sync#

  • com.atproto.sync.getBlob
  • com.atproto.sync.getBlocks
  • com.atproto.sync.getLatestCommit
  • com.atproto.sync.getRecord
  • com.atproto.sync.getRepoStatus
  • com.atproto.sync.getRepo
  • com.atproto.sync.listBlobs
  • com.atproto.sync.listRepos
  • com.atproto.sync.requestCrawl
  • com.atproto.sync.subscribeRepos

Other#

  • com.atproto.label.queryLabels
  • com.atproto.moderation.createReport
  • app.bsky.actor.getPreferences
  • app.bsky.actor.putPreferences

License#

MIT. server/static/pico.css is also MIT licensed, available at https://github.com/picocss/pico/.

Thanks#

Vow is based on Cocoon. Many thanks for the solid foundation.

Vow vs Cocoon#

Feature Vow Cocoon
Language Go Go
SQLite blockstore
PostgreSQL support ❌ removed
S3 blob storage ❌ removed
S3 database backups ❌ removed
IPFS blob storage ✅ (Kubo)
IPFS account storage 🔜 incoming
BYOK (Bring Your Own Key) 🔜 incoming
x402 payments for IPFS 🔜 incoming
Extension for action signing 🔜 incoming

Vow trades Cocoon's operational storage flexibility (PostgreSQL, S3) for a leaner SQLite-only core, with a roadmap focused on decentralised storage and user-controlled keys.