Microservice to bring 2FA to self hosted PDSes
1# PDS gatekeeper 2 3A microservice that sits on the same server as the PDS to add some of the security that the entryway does. 4 5![Picture in black and white of a grassy hill with a gate at the top](./images/gate.jpg) 6 7PDS gatekeeper works by overriding some of the PDS endpoints inside your Caddyfile to provide gatekeeping to certain 8endpoints. Mainly, the ability to have 2FA on a self hosted PDS like it does on a Bluesky mushroom(PDS). Most of the 9logic of these endpoints still happens on the PDS via a proxied request, just some are gatekept. 10 11# Features 12 13## 2FA 14 15- Overrides The login endpoint to add 2FA for both Bluesky client logged in and OAuth logins 16- Overrides the settings endpoints as well. As long as you have a confirmed email you can turn on 2FA 17 18## Captcha on Create Account 19 20Future feature? 21 22# Setup 23 24PDS Gatekeeper has 2 parts to its setup, docker compose file and a reverse proxy (Caddy in this case). I will be 25assuming you setup the PDS following the directions 26found [here](https://atproto.com/guides/self-hosting), but if yours is different, or you have questions, feel free to 27let 28me know, and we can figure it out. 29 30## Docker compose 31 32The pds gatekeeper container can be found on docker hub under the name `fatfingers23/pds_gatekeeper`. The container does 33need access to the `/pds` root folder to access the same db's as your PDS. The part you need to add would look a bit 34like below. You can find a full example of what I use for my pds at [./examples/compose.yml](./examples/compose.yml). 35This is usually found at `/pds/compose.yaml`on your PDS> 36 37```yml 38 gatekeeper: 39 container_name: gatekeeper 40 image: fatfingers23/pds_gatekeeper:latest 41 network_mode: host 42 restart: unless-stopped 43 #This gives the container to the access to the PDS folder. Source is the location on your server of that directory 44 volumes: 45 - type: bind 46 source: /pds 47 target: /pds 48 depends_on: 49 - pds 50``` 51 52## Caddy setup 53 54For the reverse proxy I use caddy. This part is what overwrites the endpoints and proxies them to PDS gatekeeper to add 55in extra functionality. The main part is below, for a full example see [./examples/Caddyfile](./examples/Caddyfile). 56This is usually found at `/pds/caddy/etc/caddy/Caddyfile` on your PDS. 57 58```caddyfile 59 @gatekeeper { 60 path /xrpc/com.atproto.server.getSession 61 path /xrpc/com.atproto.server.updateEmail 62 path /xrpc/com.atproto.server.createSession 63 path /xrpc/com.atproto.server.createAccount 64 path /@atproto/oauth-provider/~api/sign-in 65 } 66 67 handle @gatekeeper { 68 reverse_proxy http://localhost:8080 69 } 70 71 reverse_proxy http://localhost:3000 72``` 73 74If you use a cloudflare tunnel then your caddyfile would look a bit more like below with your tunnel proxying to 75`localhost:8081` (or w/e port you want). 76 77```caddyfile 78http://*.localhost:8082, http://localhost:8082 { 79 @gatekeeper { 80 path /xrpc/com.atproto.server.getSession 81 path /xrpc/com.atproto.server.updateEmail 82 path /xrpc/com.atproto.server.createSession 83 path /@atproto/oauth-provider/~api/sign-in 84 } 85 86 handle @gatekeeper { 87 reverse_proxy http://localhost:8080 88 } 89 90 reverse_proxy http://localhost:3000 91} 92 93``` 94 95# Environment variables and bonuses 96 97Every environment variable can be set in the `pds.env` and shared between PDS and gatekeeper and the PDS, with the 98exception of `PDS_ENV_LOCATION`. This can be set to load the pds.env, by default it checks `/pds/pds.env` and is 99recommended to mount the `/pds` folder on the server to `/pds` in the pds gatekeeper container. 100 101`PDS_DATA_DIRECTORY` - Root directory of the PDS. Same as the one found in `pds.env` this is how pds gatekeeper knows 102knows the rest of the environment variables. 103 104`GATEKEEPER_EMAIL_TEMPLATES_DIRECTORY` - The folder for templates of the emails PDS gatekeeper sends. You can find them 105in [./email_templates](./email_templates). You are free to edit them as you please and set this variable to a location 106in the pds gateekeper container and it will use them in place of the default ones. Just make sure ot keep the names the 107same. 108 109`GATEKEEPER_TWO_FACTOR_EMAIL_SUBJECT` - Subject of the email sent to the user when they turn on 2FA. Defaults to 110`Sign in to Bluesky` 111 112`PDS_BASE_URL` - Base url of the PDS. You most likely want `https://localhost:3000` which is also the default 113 114`GATEKEEPER_HOST` - Host for pds gatekeeper. Defaults to `127.0.0.1` 115 116`GATEKEEPER_PORT` - Port for pds gatekeeper. Defaults to `8080` 117 118`GATEKEEPER_CREATE_ACCOUNT_PER_SECOND` - Sets how often it takes a count off the limiter. example if you hit the rate 119limit of 5 and set to 60, then in 60 seconds you will be able to make one more. Or in 5 minutes be able to make 5 more. 120 121`GATEKEEPER_CREATE_ACCOUNT_BURST` - Sets how many requests can be made in a burst. In the prior example this is where 122the 5 comes from. Example can set this to 10 to allow for 10 requests in a burst, and after 60 seconds it will drop one 123off.