Entryway and member host
An entryway is the way to grow past one host. It keeps the accounts, the sessions, the OAuth server and the PLC rotation key, and routes everything else to a member host, which keeps the repositories, the blobs, the signing keys and the firehose. The old server becomes the member host and keeps its address, so no DID document changes.
Today an entryway serves one member host. Rehearse the split on a copy first, and tell the people on the server before the day: every OAuth client must sign in again, because the member host is no longer an authorization server.
What to know first
Section titled “What to know first”PDS_ENTRYWAY_URLof the member host is the public address of the entryway. OAuth clients read it, and tokens name it as their issuer.- Sessions with a password or an app password carry on: the client refreshes once and gets tokens of the entryway.
- After local token checks, the member checks current legacy or OAuth
session state at the entryway. Results are not cached. Password recovery
takes effect at the next authenticated member request. This adds one
round trip, capped at five seconds or
PDS_PROXY_HEADERS_TIMEOUTif shorter. If the entryway cannot answer, the member refuses the request with 503UpstreamFailure. PDS_ENTRYWAY_ADMIN_TOKENmust contain the entryway’s admin password. The member uses it for the private/oauth/introspectcheck and admin forwarding. Keep it in the member’s secret store.- The entryway passes uploads, exports and the firehose through to the member host as streams. Only the member host asks the relay to crawl it.
- A member host answers no handle.
/.well-known/atproto-didon the handle names must reach the entryway, so the wildcard DNS and the Caddyfile move to it.
Prepare
Section titled “Prepare”-
Choose the entryway’s name, such as
entryway.example.com, and point it at the new host. -
Create the key of the tokens, 32 random bytes as 64 hexadecimal digits:
Terminal window openssl rand -hex 32It goes into the entryway’s secrets. The member host needs the public key, which the entryway logs at start as
jwt_verify_key_k256_public_key_hex, with its DID. -
Note the
did:keyof the old server’s PLC rotation key. The entryway takes the private key; the member host gets thedid:key.
-
Stop the old server.
-
Copy the complete
account.sqlite, includingcredential_epoch, from its data directory to the entryway’s. -
Configure the entryway with the old server’s variables, and:
Variable Value PDS_HOSTNAMEthe entryway’s name PDS_JWT_SECRETthe old server’s; it takes the refresh tokens from before PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEXthe old server’s PDS_MEMBER_URLthe old server’s public address PDS_MEMBER_INTERNAL_URLwhere the entryway reaches it PDS_MEMBER_ADMIN_PASSWORDthe old server’s admin password PDS_ENTRYWAY_JWT_SIGNING_KEY_K256_PRIVATE_KEY_HEXthe new key -
Configure the old server as the member host. Keep its variables, and:
Variable Value PDS_ENTRYWAY_URLthe entryway’s address PDS_ENTRYWAY_DIDdid:web:and the entryway’s namePDS_ENTRYWAY_JWT_VERIFY_KEY_K256_PUBLIC_KEY_HEXthe public key PDS_ENTRYWAY_PLC_ROTATION_KEYthe did:keyof the rotation keyPDS_ENTRYWAY_ADMIN_TOKENthe entryway’s PDS_ADMIN_PASSWORDPDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEXremove it PDS_JWT_SECRETkeep it; the member host answers ExpiredTokento a token from before, and the client refreshes -
Send
/.well-known/atproto-didof the handle names to the entryway. -
Start the entryway, then the member host.
- Sign in at the member host’s address with a password. The entryway answers, and the session writes a record.
- Refresh a session from before the split.
- Create an account at the entryway. Its DID document names the member host.
- Change a handle. Both servers show it.
- Recover a test account’s password. Its previous legacy and OAuth tokens must fail on the member host; a fresh sign-in must work.
Reconcile
Section titled “Reconcile”A crash during a sign-up can leave a repository on the member host with no account at the entryway. At the entryway:
docker compose exec pds linkjar-pds reconcileIt lists each repository without an account and each account without a
repository, and exits 1 when it finds one. Run it again with
--remove-orphans to remove the repositories without an account; one
with a commit in the last ten minutes stays, because it may be a sign-up
in progress.
Back to one server
Section titled “Back to one server”Stop both. Remove the PDS_ENTRYWAY_* variables from the old server and
give it its rotation key back. Copy account.sqlite from the entryway
back: it has the accounts, sessions and recovery epochs since the split.
A repository the member host created since then is in its directory already. Start the
old server; clients refresh once more.
The runbook in the repository has the same procedure with the specification’s references.
