Exosphere is a set of small, modular, self-hostable community tools built on the AT Protocol.
app.exosphere.site
1/**
2 * Initialize the local PDS environment for development.
3 *
4 * Generates the pds/pds.env file with the necessary secrets and configuration.
5 * Run this once before starting the PDS for the first time.
6 *
7 * Usage: bun run scripts/pds-init.ts
8 */
9
10import { existsSync, mkdirSync, writeFileSync } from "node:fs";
11import { join } from "node:path";
12import { randomBytes } from "node:crypto";
13
14const ROOT = join(import.meta.dir, "..");
15const PDS_DIR = join(ROOT, "pds");
16const ENV_FILE = join(PDS_DIR, "pds.env");
17
18if (existsSync(ENV_FILE)) {
19 console.log("pds/pds.env already exists. Delete it to regenerate.");
20 process.exit(0);
21}
22
23mkdirSync(PDS_DIR, { recursive: true });
24
25const jwtSecret = randomBytes(32).toString("hex");
26const adminPassword = "localdev";
27const plcRotationKey = randomBytes(32).toString("hex");
28
29// AT Protocol disallows these TLDs for handles:
30// .local, .arpa, .invalid, .localhost, .internal, .example, .alt, .onion
31// We use a real-looking domain so handle validation passes.
32// Handles will be <name>.pds.dev — they won't resolve via DNS, but that's
33// fine for local dev (use the DID to log in instead).
34const pdsHostname = "pds.dev";
35
36const env = `# Generated by scripts/pds-init.ts — do not commit
37PDS_HOSTNAME=${pdsHostname}
38PDS_PORT=3000
39PDS_JWT_SECRET=${jwtSecret}
40PDS_ADMIN_PASSWORD=${adminPassword}
41PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX=${plcRotationKey}
42PDS_DATA_DIRECTORY=/pds/data
43PDS_BLOBSTORE_DISK_LOCATION=/pds/data/blocks
44PDS_DID_PLC_URL=https://plc.directory
45PDS_DEV_MODE=1
46PDS_LOG_ENABLED=true
47
48# AppView and moderation are not needed for local dev
49# but the PDS may require them to start
50PDS_BSKY_APP_VIEW_URL=https://api.bsky.app
51PDS_BSKY_APP_VIEW_DID=did:web:api.bsky.app
52PDS_REPORT_SERVICE_URL=https://mod.bsky.app
53PDS_REPORT_SERVICE_DID=did:plc:ar7c4by46qjdydhdevvrndac
54PDS_CRAWLERS=
55`;
56
57writeFileSync(ENV_FILE, env);
58console.log("Created pds/pds.env");
59console.log(` Admin password: ${adminPassword}`);
60console.log("");
61console.log("Start the PDS with:");
62console.log(" docker compose -f docker-compose.dev.yml up -d");