Socket
Book a DemoInstallSign in
Socket

@ascorbic/pds

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ascorbic/pds

AT Protocol PDS on Cloudflare Workers

Source
npmnpm
Version
0.0.0
Version published
Weekly downloads
25
-95.64%
Maintainers
1
Weekly downloads
 
Created
Source

@ascorbic/pds

A single-user AT Protocol Personal Data Server (PDS) that runs on Cloudflare Workers. Host your own Bluesky identity with minimal infrastructure.

⚠️ Experimental Software

This is an early-stage project under active development. Do not migrate your main Bluesky account to this PDS yet. Use a test account or create a new identity for experimentation. Data loss, breaking changes, and missing features are expected.

What is this?

A PDS is where your Bluesky data lives - your posts, follows, profile, and media. This package lets you run your own PDS on Cloudflare's edge network, giving you:

  • Your own identity - Use your own domain as your Bluesky handle
  • Data ownership - Your content lives in your Cloudflare account
  • Federation - Works with the Bluesky network via relay sync
  • Low cost - Runs on Cloudflare's generous free tier

Quick Start

The fastest way to get started:

npm create pds

This scaffolds a new project, installs dependencies, and runs the setup wizard to configure your PDS.

Then start the dev server:

cd pds-worker
npm run dev

Manual Installation

If you prefer to set things up yourself:

1. Install the package

npm install @ascorbic/pds

2. Create a worker entry point

// src/index.ts
export { default, AccountDurableObject } from "@ascorbic/pds";

3. Configure wrangler.jsonc

{
	"name": "my-pds",
	"main": "src/index.ts",
	"compatibility_date": "2024-12-01",
	"compatibility_flags": ["nodejs_compat"],
	"durable_objects": {
		"bindings": [{ "name": "ACCOUNT", "class_name": "AccountDurableObject" }],
	},
	"migrations": [
		{ "tag": "v1", "new_sqlite_classes": ["AccountDurableObject"] },
	],
	"r2_buckets": [{ "binding": "BLOBS", "bucket_name": "pds-blobs" }],
}

4. Run the setup wizard

pnpm pds init

This prompts for your hostname, handle, and password, then generates signing keys and writes configuration.

CLI

The package includes a CLI for setup and configuration:

pds init                 # Interactive setup (writes to .dev.vars)
pds init --production    # Deploy secrets to Cloudflare
pds secret key           # Generate new signing keypair
pds secret jwt           # Generate new JWT secret
pds secret password      # Set account password

Deploying to Production

npx pds init --production
  • Deploy your worker:
wrangler deploy
  • Configure DNS to point your domain to the worker.

Identity: DIDs and Handles

AT Protocol uses two types of identifiers:

  • DID (Decentralized Identifier): Your permanent, cryptographic identity (e.g., did:web:pds.example.com). This never changes and is tied to your signing key.
  • Handle: Your human-readable username (e.g., alice.example.com). This can be any domain you control.

The DID document (served at /.well-known/did.json) contains your public key and tells the network where your PDS is. The alsoKnownAs field links your DID to your handle.

Handle Verification

Bluesky verifies that you control your handle domain. There are two methods:

Option A: Handle matches PDS hostname

If your handle is the same as your PDS hostname (e.g., both are pds.example.com):

  • The PDS automatically serves /.well-known/atproto-did returning your DID
  • No additional DNS setup needed
  • This is the simplest option

Option B: Handle on a different domain

If you want a handle on a different domain (e.g., handle alice.example.com while PDS is at pds.example.com):

  • Add a DNS TXT record to your handle domain:
_atproto.alice.example.com  TXT  "did=did:web:pds.example.com"
  • Verify it's working:
dig TXT _atproto.alice.example.com

This lets you use any domain you own as your Bluesky handle, even your personal website.

Configuration

The PDS uses environment variables for configuration. Public values go in wrangler.jsonc, secrets are stored via Wrangler or in .dev.vars for local development.

Public Variables (wrangler.jsonc)

VariableDescription
PDS_HOSTNAMEPublic hostname (e.g., pds.example.com)
DIDAccount DID (did:web:... or did:plc:...)
HANDLEAccount handle
SIGNING_KEY_PUBLICPublic key for DID document (multibase)

Secrets

VariableDescription
AUTH_TOKENBearer token for API write operations
SIGNING_KEYPrivate signing key (secp256k1 JWK)
JWT_SECRETSecret for signing session JWTs
PASSWORD_HASHBcrypt hash of password for app login

API Endpoints

Public

EndpointDescription
GET /.well-known/did.jsonDID document
GET /.well-known/atproto-didHandle verification
GET /xrpc/com.atproto.sync.getRepoExport repository as CAR
GET /xrpc/com.atproto.sync.subscribeReposWebSocket firehose
GET /xrpc/com.atproto.repo.describeRepoRepository metadata
GET /xrpc/com.atproto.repo.getRecordGet a single record
GET /xrpc/com.atproto.repo.listRecordsList records in a collection

Authenticated

EndpointDescription
POST /xrpc/com.atproto.server.createSessionLogin (returns JWT)
POST /xrpc/com.atproto.server.refreshSessionRefresh JWT
POST /xrpc/com.atproto.repo.createRecordCreate a record
POST /xrpc/com.atproto.repo.deleteRecordDelete a record
POST /xrpc/com.atproto.repo.putRecordCreate or update a record
POST /xrpc/com.atproto.repo.uploadBlobUpload a blob
POST /xrpc/com.atproto.repo.importRepoImport repository from CAR

Architecture

The PDS runs as a Cloudflare Worker with a Durable Object for state:

  • Worker: Handles routing, authentication, and DID document serving
  • AccountDurableObject: Stores repository data in SQLite, manages the Merkle tree
  • R2: Stores blobs (images, videos)

Limitations

  • Single-user only: One account per deployment
  • No account creation: The owner is configured at deploy time
  • did:web only: Uses domain-based DIDs (did:plc support planned)

Resources

Keywords

atproto

FAQs

Package last updated on 28 Dec 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts