An AT Protocol Personal Data Server written in JavaScript pdsjs.dev
pds atproto
pds.js docs deploy-node.md
2.1 kB

Deploy: Node.js #

The Node server stores the repo in SQLite and the blobs on local disk. Use it to run a PDS from a checkout, or as a library inside your own process.

Docker packages this same server, and needs no checkout.

From a checkout #

pnpm install
npm run build:ui

Install with pnpm. The workspace dependencies use the workspace:* protocol, and npm install fails on it.

npm run build:ui builds the account interface bundle. The node entrypoint does not resolve without it.

Configure the environment:

cp .env.example .env
# Edit .env with your values

PDS_PASSWORD, JWT_SECRET and HOSTNAME matter most. See configuration for the rest.

Start the server:

# Development, with auto-reload
npm run dev:node

# Production
cd examples/node && npm start

As a library #

import { createServer } from '@pdsjs/node'

const { listen } = await createServer({
  dbPath: './pds.db',
  blobsDir: './blobs',
  jwtSecret: process.env.JWT_SECRET,
  hostname: 'your-hostname.com',
  port: 3000,
})

await listen()

createServer reads no environment variables. examples/node/index.js shows the full option set, including the mail sender, the backup target, and the spaces flag.

Finish the setup #

Terminate TLS with a reverse proxy such as nginx or Caddy. Set HOSTNAME to the public domain.

Then register the DID with the PLC directory. Run this once, after the PDS answers at its public URL:

npm run setup -- --pds https://your-hostname.com

Operating notes #

  • The SQLite database and the blobs go to local disk. Back up both. Set PDS_BACKUP_DIR or the PDS_BACKUP_S3_* variables for scheduled backups.
  • subscribeRepos holds a WebSocket per consumer. The reverse proxy must forward the upgrade. Caddy does this by default. nginx needs the Upgrade and Connection headers set on the location.
  • examples/node/index.js installs no signal handler. docker/server.js closes SQLite on SIGTERM and SIGINT. Copy that block for a service unit that stops the process with a signal.