···140140# =============================================================================
141141# If configured, moderation reports will be proxied to this service
142142# instead of being stored locally. The service should implement the
143143-# com.atproto.moderation.createReport endpoint (e.g., Bluesky's Ozone).
143143+# com.atproto.moderation.createReport endpoint (eg., Bluesky's Ozone).
144144# Both URL and DID must be set for proxying to be enabled.
145145# REPORT_SERVICE_URL=https://mod.bsky.app
146146# REPORT_SERVICE_DID=did:plc:ar7c4by46qjdydhdevvrndac
···148148# Age Assurance Override
149149# =============================================================================
150150# Enable this if you have separately assured the ages of your users
151151-# (e.g., through your own age verification process). When enabled, the PDS
151151+# (eg., through your own age verification process). When enabled, the PDS
152152# will return "assured" status for age assurance checks instead of proxying
153153# to the appview. This helps migrated users avoid the age assurance
154154# catch-22 on bsky.app.
···158158# =============================================================================
159159# Allow HTTP for proxy requests (development only)
160160# ALLOW_HTTP_PROXY=1
161161-# Custom frontend directory (defaults to ./frontend/dist)
162162-# FRONTEND_DIR=/path/to/frontend/dist
163161# =============================================================================
164162# SSO / Social Login
165163# =============================================================================
···12121313## What's different about Tranquil PDS
14141515-It is a superset of the reference PDS, including: passkeys and 2FA (WebAuthn/FIDO2, TOTP, backup codes, trusted devices), did:web support (PDS-hosted subdomains or bring-your-own), multi-channel communication (email, discord, telegram, signal) for verification and alerts, granular OAuth scopes with a consent UI showing human-readable descriptions, app passwords with granular permissions (read-only, post-only, or custom scopes), account delegation (letting others manage an account with configurable permission levels), automatic backups to s3-compatible object storage (configurable retention and frequency, one-click restore), and a built-in web UI for account management, OAuth consent, repo browsing, and admin.
1515+It is a superset of the reference PDS, including: passkeys and 2FA (WebAuthn/FIDO2, TOTP, backup codes, trusted devices), SSO login and signup, did:web support (PDS-hosted subdomains or bring-your-own), multi-channel communication (email, discord, telegram, signal) for verification and alerts, granular OAuth scopes with a consent UI showing human-readable descriptions, app passwords with granular permissions (read-only, post-only, or custom scopes), account delegation (letting others manage an account with configurable permission levels), automatic backups to s3-compatible object storage (configurable retention and frequency, one-click restore), and a built-in web UI for account management, OAuth consent, repo browsing, and admin.
16161717The PDS itself is a single small binary with no node/npm runtime. It does require postgres, valkey, and s3-compatible storage, which makes setup heavier than the reference PDS's sqlite. The tradeoff is that these are battle-tested pieces of infra that we already know how to scale, back up, and monitor.
1818···45454646```bash
4747cp .env.prod.example .env.prod
4848-podman-compose -f docker-compose.prod.yml up -d
4848+podman-compose -f docker-compose.prod.yaml up -d
4949```
50505151### Installation Guides
···160160 "signal": "Signal",
161161 "signalNumber": "Signal Phone Number",
162162 "signalNumberPlaceholder": "+1234567890",
163163- "signalNumberHint": "Include country code (e.g., +1 for US)",
163163+ "signalNumberHint": "Include country code (eg., +1 for US)",
164164 "notConfigured": "not configured",
165165 "inviteCode": "Invite Code",
166166 "inviteCodePlaceholder": "Enter your invite code",
···263263 "saveFailed": "Failed to save DID document",
264264 "loadFailed": "Failed to load DID document",
265265 "invalidMultibase": "Public key must be a valid multibase string starting with 'z'",
266266- "invalidHandle": "Handle must be an at:// URI (e.g., at://handle.example.com)",
266266+ "invalidHandle": "Handle must be an at:// URI (eg., at://handle.example.com)",
267267 "helpTitle": "What is this?",
268268 "helpText": "When you migrate to another PDS, that PDS generates new signing keys. Update your DID document here so it points to your new keys and location. This enables multi-hop migrations (PDS 1 → PDS 2 → PDS 3)."
269269 },
···385385 "title": "App Passwords",
386386 "description": "App passwords let you sign in to third-party apps without giving them your main password. Each app password can be revoked individually.",
387387 "createNew": "Create New App Password",
388388- "appNamePlaceholder": "App name (e.g., Graysky, Skeets)",
388388+ "appNamePlaceholder": "App name (eg., Graysky, Skeets)",
389389 "created": "App Password Created",
390390 "createdMessage": "Copy this password now. You won't be able to see it again.",
391391 "yourPasswords": "Your App Passwords",
···452452 "adding": "Adding...",
453453 "noPasskeys": "No passkeys registered",
454454 "passkeyName": "Passkey name",
455455- "passkeyNamePlaceholder": "e.g., MacBook Pro, iPhone",
455455+ "passkeyNamePlaceholder": "eg., MacBook Pro, iPhone",
456456 "register": "Register",
457457 "registering": "Registering...",
458458 "rename": "Rename",
···10071007 "infoAppAccess": "Using third-party apps",
10081008 "infoAppAccessDesc": "After creating your account, you will receive an app password. Use this to sign in to Bluesky apps and other AT Protocol clients.",
10091009 "passkeyNameLabel": "Passkey Name (optional)",
10101010- "passkeyNamePlaceholder": "e.g., MacBook Touch ID",
10101010+ "passkeyNamePlaceholder": "eg., MacBook Touch ID",
10111011 "passkeyNameHint": "A friendly name to identify this passkey",
10121012 "passkeyPrompt": "Click the button below to create your passkey. You'll be prompted to use:",
10131013 "passkeyPromptBullet1": "Touch ID or Face ID",
···12791279 "checkingAvailability": "Checking availability...",
12801280 "handleAvailable": "Handle is available!",
12811281 "handleTaken": "Handle is already taken",
12821282- "handleHint": "You can also use your own domain by entering the full handle (e.g., alice.mydomain.com)",
12821282+ "handleHint": "You can also use your own domain by entering the full handle (eg., alice.mydomain.com)",
12831283 "email": "Email Address",
12841284 "authMethod": "Authentication Method",
12851285 "authPassword": "Password",
···13201320 "title": "Set Up Your Passkey",
13211321 "desc": "Your email has been verified. Now set up your passkey for secure, passwordless login.",
13221322 "nameLabel": "Passkey Name (optional)",
13231323- "namePlaceholder": "e.g., MacBook Pro, iPhone",
13231323+ "namePlaceholder": "eg., MacBook Pro, iPhone",
13241324 "nameHint": "A friendly name to identify this passkey",
13251325 "instructions": "Click the button below to register your passkey. Your device will prompt you to use biometrics (fingerprint, Face ID) or a security key.",
13261326 "register": "Register Passkey",
···14181418 "title": "Enter Your DID",
14191419 "desc": "Enter the DID of the account you want to restore.",
14201420 "label": "Your DID",
14211421- "hint": "Your decentralized identifier (e.g., did:plc:abc123...)"
14211421+ "hint": "Your decentralized identifier (eg., did:plc:abc123...)"
14221422 },
14231423 "uploadCar": {
14241424 "title": "Upload Repository Backup",