perlsky is a Perl 5 implementation of an AT Protocol Personal Data Server.
13
fork

Configure Feed

Select the types of activity you want to include in your feed.

Document built-in OAuth provider deployment

alice bbe6a054 02ea81f9

+12
+3
README.md
··· 33 33 34 34 - Generic single-node deployment instructions live in `docs/DEPLOYMENT.md`. 35 35 - The deployment guide includes a reverse-proxy layout, a sample `systemd` unit, validation commands, and a `createAccount` example for bootstrapping the first user. 36 + - `perlsky` now includes a built-in ATProto OAuth provider surface, so modern third-party clients that use the Bluesky OAuth flow can authenticate directly against your PDS without extra auth-server infrastructure. 37 + - The built-in provider publishes `/.well-known/oauth-protected-resource`, `/.well-known/oauth-authorization-server`, `/oauth/jwks`, `/oauth/par`, `/oauth/authorize`, `/oauth/token`, and `/oauth/revoke` from the same host as the PDS. 36 38 - If `service_handle_domain` is `example.com`, submitting `handle: "alice"` to `com.atproto.server.createAccount` creates `alice.example.com`. 37 39 - If `invite_code_required` is enabled, public signup is disabled until a valid invite code is supplied. 38 40 - `com.atproto.server.createInviteCode` and `com.atproto.server.createInviteCodes` are admin-only by default. Set `self_service_invite_codes` to enable self-service invite minting for authenticated full-access sessions, limited to the caller's own account. 39 41 - `script/perlsky-admin create-invite` can mint invite codes locally on the server without needing an existing user session. 40 42 - The invite-only bootstrap flow is documented with copy-pasteable commands in `docs/DEPLOYMENT.md`. 41 43 - Browser clients such as `bsky.app` can talk to `perlsky` directly because XRPC and DID-document responses include CORS headers and answer OPTIONS preflight requests. 44 + - OAuth clients such as Tangled can also discover and use `perlsky` directly as both the protected resource and authorization server, using PAR, PKCE, `private_key_jwt`, and DPoP as required by the ATProto OAuth profile. 42 45 - Unknown `app.bsky.*` requests are proxied to `https://api.bsky.app` by default, and unknown `chat.bsky.*` requests are proxied to `https://api.bsky.chat` by default using per-account service-auth JWTs. 43 46 - Set `bsky_appview_url` / `bsky_appview_did` or `chat_service_url` / `chat_service_did` in your config if you want different upstream services. 44 47
+9
docs/DEPLOYMENT.md
··· 82 82 - `service_handle_domain`: the suffix used for local handles 83 83 - `jwt_secret`: required; the server now refuses to start if it is missing or still set to the old `perlsky-dev-secret` fallback 84 84 - `sentry_dsn`: optional; when set, perlsky reports unhandled XRPC exceptions to Sentry with request context and Perl stack frames 85 + - `base_url` also drives the built-in ATProto OAuth provider metadata and endpoints, so it must be the same public origin that third-party clients will use for login 85 86 - If you want users like `alice.pds.example.com`, set `service_handle_domain` to `pds.example.com`, not `example.com`. 86 87 - Public handle resolution for `alice.pds.example.com` also requires wildcard DNS for `*.pds.example.com` and a reverse proxy/TLS setup that will answer those subdomains. 87 88 - `invite_code_required`: if true, `createAccount` requires a valid invite code ··· 234 235 ```sh 235 236 curl https://pds.example.com/_health 236 237 curl https://pds.example.com/.well-known/did.json 238 + curl https://pds.example.com/.well-known/oauth-protected-resource 239 + curl https://pds.example.com/.well-known/oauth-authorization-server 240 + curl https://pds.example.com/oauth/jwks 237 241 curl https://pds.example.com/xrpc/com.atproto.server.describeServer 238 242 curl --resolve alice.pds.example.com:443:SERVER_IP https://alice.pds.example.com/.well-known/atproto-did 239 243 ``` ··· 250 254 251 255 - a healthy `_health` response 252 256 - a `did:web:pds.example.com` DID document 257 + - OAuth protected-resource metadata advertising the same host as the authorization server 258 + - OAuth authorization-server metadata advertising `private_key_jwt`, PAR, PKCE `S256`, DPoP-bound access tokens, and the local `/oauth/*` endpoints 259 + - a JWK set with at least one signing key from `/oauth/jwks` 253 260 - `describeServer.availableUserDomains` matching `service_handle_domain` 254 261 - a per-handle `/.well-known/atproto-did` response returning the account DID when queried on the handle host 262 + 263 + Modern third-party ATProto OAuth clients should now be able to discover and authenticate directly against your PDS. For example, a client like Tangled will start by fetching `/.well-known/oauth-protected-resource`, follow the advertised authorization-server metadata, submit a pushed authorization request, and then send the browser through `/oauth/authorize`. 255 264 256 265 ## First Account 257 266