1{ lib, config, ... }:
2let
3 pdsLocalhost = "http://localhost:${toString config.services.bluesky-pds.settings.PDS_PORT}";
4in
5{
6 age.secrets.pdsConfig.file = ../../../secrets/pdsConfig.age;
7
8 services.nginx.virtualHosts.${config.services.bluesky-pds.settings.PDS_HOSTNAME} = {
9 useACMEHost = "gaze.systems";
10 forceSSL = true;
11 locations = {
12 # we need to proxy /xrpc for pds to work
13 # silly but i want root domain >:3
14 "/xrpc" = {
15 proxyPass = pdsLocalhost;
16 proxyWebsockets = true;
17 # pass ws headers so we can actually proxy the ws
18 extraConfig = ''
19 proxy_set_header id $request_id;
20 client_max_body_size 100M;
21 '';
22 # higher prio just to make sure
23 priority = 100;
24 };
25 "/xrpc/app.bsky.unspecced.getAgeAssuranceState".extraConfig = ''
26 default_type application/json;
27 add_header access-control-allow-headers "authorization,dpop,atproto-accept-labelers,atproto-proxy" always;
28 add_header access-control-allow-origin "*" always;
29 return 200 '{"lastInitiatedAt":"2025-07-14T14:22:43.912Z","status":"assured"}';
30 '';
31 }
32 # others
33 // (lib.genAttrs
34 [
35 "/account"
36 "/@atproto"
37 "/oauth"
38 "=/.well-known/oauth-protected-resource"
39 "=/.well-known/oauth-authorization-server"
40 ]
41 (_: {
42 proxyPass = pdsLocalhost;
43 # higher prio just to make sure
44 priority = 100;
45 })
46 );
47 };
48 # setup pds stuff
49 services.bluesky-pds = {
50 enable = true;
51 settings = {
52 PDS_HOSTNAME = "gaze.systems";
53 PDS_PORT = 1334;
54
55 PDS_SERVICE_NAME = ''"gazing at the sky"'';
56 PDS_LOGO_URL = "https://gaze.systems/icons/gaze_site.webp";
57
58 PDS_RATE_LIMITS_ENABLED = "true";
59 PDS_INVITE_REQUIRED = "true";
60
61 PDS_DID_PLC_URL = "https://plc.directory";
62 PDS_BSKY_APP_VIEW_URL = "https://api.bsky.app";
63 PDS_BSKY_APP_VIEW_DID = "did:web:api.bsky.app";
64 PDS_REPORT_SERVICE_URL = "https://mod.bsky.app";
65 PDS_REPORT_SERVICE_DID = "did:plc:ar7c4by46qjdydhdevvrndac";
66 PDS_CRAWLERS = "https://bsky.network";
67 };
68 environmentFiles = [ config.age.secrets.pdsConfig.path ];
69 };
70
71 services.fluent-bit.settings = {
72 parsers = [
73 {
74 name = "pds_json";
75 format = "json";
76 time_key = "time";
77 time_strict = false;
78 }
79 ];
80 pipeline = {
81 inputs = [
82 {
83 name = "systemd";
84 tag = "logs.pds";
85 systemd_filter = "_SYSTEMD_UNIT=bluesky-pds.service";
86 }
87 ];
88 filters = [
89 {
90 name = "parser";
91 match = "logs.pds";
92 key_name = "MESSAGE";
93 parser = "pds_json";
94 }
95 {
96 name = "modify";
97 match = "logs.pds";
98 Rename = [ "msg _msg" ];
99 }
100 ];
101 };
102 };
103
104 services.vmalert.instances."".rules.groups = [
105 {
106 name = "pds-logs";
107 type = "vlogs";
108 interval = "1m";
109 rules = [
110 {
111 record = "pds_request_count";
112 expr = "name:pds | stats (res.statusCode) count() as total_requests";
113 }
114 {
115 record = "pds_response_latency";
116 expr = "name:pds | stats avg(responseTime) avg, quantile(0.5, responseTime) p50, quantile(0.9, responseTime) p90, quantile(0.99, responseTime) p99";
117 }
118 ];
119 }
120 ];
121}