@jaspermayone.com's dotfiles
0
fork

Configure Feed

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

Add PDS gatekeeper and age assurance

+55 -11
+7
flake.nix
··· 44 44 zmx = { 45 45 url = "github:neurosnap/zmx"; 46 46 }; 47 + 48 + tgirlpkgs = { 49 + url = "github:binarycat/tgirlpkgs"; 50 + inputs.nixpkgs.follows = "nixpkgs"; 51 + }; 47 52 }; 48 53 49 54 outputs = { ··· 56 61 nix-darwin, 57 62 deploy-rs, 58 63 tangled, 64 + tgirlpkgs, 59 65 ... 60 66 }@inputs: 61 67 let ··· 90 96 modules = [ 91 97 ./hosts/${hostname}/configuration.nix 92 98 agenix.nixosModules.default 99 + tgirlpkgs.nixosModules.default 93 100 unstable-overlays 94 101 nur.modules.nixos.default 95 102 home-manager.nixosModules.home-manager
+2 -1
hosts/alastor/configuration.nix
··· 162 162 adminEmail = "pds-admin@hogwarts.dev"; 163 163 environmentFile = config.age.secrets.pds.path; 164 164 mailerEnvironmentFile = config.age.secrets.pds-mailer.path; 165 - enableAgeAssurance = false; 165 + enableGatekeeper = true; 166 + enableAgeAssurance = true; 166 167 }; 167 168 168 169
+46 -10
modules/bluesky-pds/default.nix
··· 1 1 # modules/bluesky-pds/default.nix 2 - # NixOS module enabling Bluesky PDS with Caddy reverse proxy 2 + # NixOS module enabling Bluesky PDS with Caddy reverse proxy and optional gatekeeper 3 3 { lib, config, pkgs, ... }: 4 4 let 5 5 cfg = config.services.bluesky-pds-hosting; 6 + pdsSettings = config.services.bluesky-pds.settings; 7 + gatekeeperPort = 3001; 8 + # When gatekeeper is enabled, Caddy proxies to gatekeeper; otherwise directly to PDS 9 + proxyTarget = if cfg.enableGatekeeper then "localhost:${toString gatekeeperPort}" else "localhost:${toString cfg.port}"; 6 10 in 7 11 { 8 12 options.services.bluesky-pds-hosting = { ··· 30 34 default = null; 31 35 description = "Optional env file for SMTP/Resend (pds-mailer.age)."; 32 36 }; 33 - cloudflareCredentialsFile = lib.mkOption { 34 - type = lib.types.nullOr lib.types.path; 35 - default = null; 36 - description = "Path to Cloudflare credentials for ACME DNS challenge."; 37 + enableGatekeeper = lib.mkOption { 38 + type = lib.types.bool; 39 + default = false; 40 + description = "Enable PDS gatekeeper for 2FA email and spam prevention."; 37 41 }; 38 42 enableAgeAssurance = lib.mkOption { 39 43 type = lib.types.bool; 40 44 default = false; 41 - description = "Serve age assurance stub endpoints."; 45 + description = "Serve age assurance stub endpoints (UK Online Safety Act)."; 42 46 }; 43 47 }; 44 48 ··· 66 70 "https://relay.feeds.blue" 67 71 "https://atproto.africa" 68 72 ]; 73 + }; 74 + }; 75 + 76 + # PDS Gatekeeper for 2FA and spam prevention 77 + services.pds-gatekeeper = lib.mkIf cfg.enableGatekeeper { 78 + enable = true; 79 + setupNginx = false; # We use Caddy 80 + settings = { 81 + GATEKEEPER_PORT = gatekeeperPort; 82 + PDS_BASE_URL = "http://127.0.0.1:${toString cfg.port}"; 83 + GATEKEEPER_TRUST_PROXY = "true"; 84 + PDS_ENV_LOCATION = cfg.environmentFile; 69 85 }; 70 86 }; 71 87 72 88 # Caddy reverse proxy for PDS 73 89 services.caddy.virtualHosts = { 74 - # Main domain and wildcard for handles 75 90 "${cfg.hostname}" = { 76 91 serverAliases = [ "*.${cfg.hostname}" ]; 77 92 extraConfig = '' 78 93 tls { 79 94 dns cloudflare {env.CLOUDFLARE_API_TOKEN} 80 95 } 81 - reverse_proxy localhost:${toString cfg.port} { 82 - header_up X-Forwarded-Proto {scheme} 83 - header_up X-Forwarded-For {remote} 96 + 97 + ${lib.optionalString cfg.enableAgeAssurance '' 98 + handle /xrpc/app.bsky.unspecced.getAgeAssuranceState { 99 + header content-type "application/json" 100 + header access-control-allow-headers "authorization,dpop,atproto-accept-labelers,atproto-proxy" 101 + header access-control-allow-origin "*" 102 + respond `{"lastInitiatedAt":"2025-07-14T14:22:43.912Z","status":"assured"}` 200 84 103 } 104 + 105 + handle /xrpc/app.bsky.ageassurance.getConfig { 106 + header content-type "application/json" 107 + header access-control-allow-headers "authorization,dpop,atproto-accept-labelers,atproto-proxy" 108 + header access-control-allow-origin "*" 109 + respond `{"regions":[]}` 200 110 + } 111 + 112 + handle /xrpc/app.bsky.ageassurance.getState { 113 + header content-type "application/json" 114 + header access-control-allow-headers "authorization,dpop,atproto-accept-labelers,atproto-proxy" 115 + header access-control-allow-origin "*" 116 + respond `{"state":{"lastInitiatedAt":"2025-07-14T14:22:43.912Z","status":"assured","access":"full"},"metadata":{"accountCreatedAt":"2022-11-17T00:35:16.391Z"}}` 200 117 + } 118 + ''} 119 + 120 + reverse_proxy ${proxyTarget} 85 121 ''; 86 122 }; 87 123 };