{
  "id": "osc-stack-host-bluesky-pds",
  "job": "Host your own Bluesky Personal Data Server (PDS) on the AT Protocol, sign in to it from the Bluesky app, and manage it from a browser, with your AI agent doing the setup over MCP.",
  "aliases": [
    "how to host a bluesky pds",
    "host your own bluesky pds",
    "bluesky pds",
    "bluesky self host",
    "pds admin"
  ],
  "distinctFrom": [
    {
      "id": "osc-stack-deploy-agent-written-app",
      "descriptorUrl": "https://www.osaas.io/stacks/deploy-agent-written-app.json",
      "why": "That recipe deploys code you or your agent wrote. This one runs an existing open source server, the Bluesky PDS, plus its admin UI."
    }
  ],
  "inputs": [
    {
      "protocol": "secret",
      "source": "an admin password stored as an OSC service secret and referenced as AdminPassword"
    },
    {
      "protocol": "https",
      "source": "optional: your own domain (DnsName), with a wildcard TLS certificate and a wildcard DNS A record, per the docs custom domain step"
    }
  ],
  "outputs": [
    {
      "protocol": "https",
      "consumer": "the PDS URL, entered as a custom hosting provider in the Bluesky app"
    },
    {
      "protocol": "https",
      "consumer": "the PDS Admin URL: a browser UI for invite codes, accounts and server status"
    }
  ],
  "recommendedPath": {
    "chain": [
      {
        "step": 1,
        "serviceId": "bluesky-social-pds",
        "role": "the Personal Data Server: stores your account, posts and identity and talks to the rest of the AT Protocol network",
        "requiredConfig": ["name", "AdminPassword"],
        "requiresCredential": true,
        "note": "Optional: DnsName (public hostname, set when you add your own domain), EmailSmtpUrl and EmailFromAddress (verification email). Leave DnsName empty on first create."
      },
      {
        "step": 2,
        "action": "create-invite-code",
        "role": "POST {pdsUrl}/xrpc/com.atproto.server.createInviteCode with Basic auth (user admin, the admin password) and body {\"useCount\": 1}; the response holds the code. Or create it in PDS Admin (step 4)."
      },
      {
        "step": 3,
        "action": "create-account",
        "role": "done by the human in the Bluesky app: choose a custom hosting provider, enter the PDS URL, the invite code, an email and a password. The agent does not do this step."
      },
      {
        "step": 4,
        "serviceId": "eyevinn-pds-admin",
        "role": "browser admin UI for the PDS: create invite codes, list accounts, review server status",
        "requiredConfig": ["name", "PdsUrl"],
        "requiresCredential": false,
        "note": "PdsUrl is the full URL of the running PDS instance."
      }
    ],
    "measuredWallClockSeconds": null,
    "wallClockMeasured": false,
    "gapNote": "No end-to-end run of this recipe has been timed for this page. Both schemas and the docs steps were read live on 2026-10-24; a PDS was not created for this page."
  },
  "configSurface": {
    "servicesInChain": 2,
    "totalRequiredFieldsAcrossChain": 4,
    "sensitiveFields": ["AdminPassword"],
    "note": "get-service-schema on bluesky-social-pds, 2026-10-24: name and AdminPassword (sensitive) required; DnsName, EmailSmtpUrl, EmailFromAddress optional; no storage or volume field; serviceAssociations []. get-service-schema on eyevinn-pds-admin, 2026-10-24: name and PdsUrl required; serviceAssociations []."
  },
  "setup": {
    "codeRequired": false,
    "knownDeployGotcha": "Create the admin password as a service secret first and reference it; the create form takes a secret reference, not a typed password. Leave DnsName empty until your own domain is in place."
  },
  "cost": {
    "unit": "tokens/day",
    "ceiling": 20,
    "ceilingBreakdown": {
      "bluesky-social-pds": 10,
      "eyevinn-pds-admin": 10
    },
    "ceilingSource": "estimate-service-cost on bluesky-social-pds and eyevinn-pds-admin, 2026-10-24 (ceiling rates; observed burn is typically lower per the tool's own note)",
    "freePlanTokens": 100,
    "freePlanTokensAreOneTime": true,
    "daysToExhaustFreePlan": 5,
    "daysToExhaustFreePlanPdsOnly": 10,
    "cheapestPlanCoveringContinuousUse": {
      "name": "Personal",
      "eurPerMonth": 15,
      "tokensPerDay": 40
    },
    "pricingSource": "https://www.osaas.io/pricing"
  },
  "exitPath": {
    "account": "the AT Protocol supports migrating an account to another PDS without the old server's involvement",
    "server": "the PDS is the open source bluesky-social/pds (upstream https://github.com/bluesky-social/pds), which runs anywhere its container runs"
  },
  "notVerified": [
    "a timed run of this recipe from start to finish",
    "whether account data survives an instance restart: the schema exposes no storage or volume field",
    "the custom domain step end to end (documented in the docs, not executed for this page)",
    "an account migration off this PDS"
  ],
  "servicesVerifiedLive": {
    "date": "2026-10-24",
    "method": "osc_call_tool get-service-schema and estimate-service-cost on bluesky-social-pds and eyevinn-pds-admin; docs.osaas.io Service: Bluesky Personal Data Server and Service: PDS Admin read the same day."
  },
  "gateCheck": {
    "gatedServiceId": "eyevinn-just-go-live",
    "usesGatedService": false,
    "note": "This stack does not name or link eyevinn-just-go-live; the P3 gate does not bind it."
  },
  "verifiedOn": "2026-10-24",
  "publishedAt": "https://www.osaas.io/use-cases/bluesky-pds",
  "descriptorUrl": "https://www.osaas.io/stacks/host-bluesky-pds.json"
}
