this repo has no description
1
fork

Configure Feed

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

Tranquil PDS

Ben C e505ed55 d896dbdf

+133 -186
+38
flake.lock
··· 728 728 "type": "github" 729 729 } 730 730 }, 731 + "nixpkgs-fetch-deno": { 732 + "locked": { 733 + "lastModified": 1766410835, 734 + "narHash": "sha256-dRhVt0aFDyTqppyzRLxiO1JZEAoIA2fUnaeyJTe+UwU=", 735 + "owner": "aMOPel", 736 + "repo": "nixpkgs", 737 + "rev": "c9801acc8c4fac6377d076bc1c102b15bd9cfa6f", 738 + "type": "github" 739 + }, 740 + "original": { 741 + "owner": "aMOPel", 742 + "ref": "feat/fetchDenoDeps", 743 + "repo": "nixpkgs", 744 + "type": "github" 745 + } 746 + }, 731 747 "nixpkgs-stable": { 732 748 "locked": { 733 749 "lastModified": 1774388614, ··· 830 846 "nu_plugin_dbus": "nu_plugin_dbus", 831 847 "spoon": "spoon", 832 848 "tangled": "tangled", 849 + "tranquil": "tranquil", 833 850 "wayland-mpris-idle-inhibit": "wayland-mpris-idle-inhibit" 834 851 } 835 852 }, ··· 993 1010 "original": { 994 1011 "type": "git", 995 1012 "url": "https://tangled.org/tangled.org/core" 1013 + } 1014 + }, 1015 + "tranquil": { 1016 + "inputs": { 1017 + "nixpkgs": [ 1018 + "nixpkgs" 1019 + ], 1020 + "nixpkgs-fetch-deno": "nixpkgs-fetch-deno" 1021 + }, 1022 + "locked": { 1023 + "lastModified": 1774731283, 1024 + "narHash": "sha256-LfppsJnSH1ZQTJw78Z25wYVZ7RIAfKDZWQh8QN04z3Y=", 1025 + "ref": "refs/heads/main", 1026 + "rev": "6abc0eaca28400e8653bece34108d696aa976211", 1027 + "revCount": 269, 1028 + "type": "git", 1029 + "url": "https://tangled.org/tranquil.farm/tranquil-pds" 1030 + }, 1031 + "original": { 1032 + "type": "git", 1033 + "url": "https://tangled.org/tranquil.farm/tranquil-pds" 996 1034 } 997 1035 }, 998 1036 "treefmt-nix": {
+3
flake.nix
··· 39 39 musnix.inputs.nixpkgs.follows = "nixpkgs"; 40 40 tangled.url = "git+https://tangled.org/tangled.org/core"; 41 41 tangled.inputs.nixpkgs.follows = "nixpkgs"; 42 + tranquil.url = "git+https://tangled.org/tranquil.farm/tranquil-pds"; 43 + tranquil.inputs.nixpkgs.follows = "nixpkgs"; 42 44 43 45 spoon.url = "git+https://codeberg.org/spoonbaker/mono"; 44 46 }; ··· 64 66 niri, 65 67 musnix, 66 68 tangled, 69 + tranquil, 67 70 }: 68 71 flakelight ./. { 69 72 inherit inputs;
+25 -28
nixosConfigurations/black-mesa.nix
··· 94 94 { 95 95 config, 96 96 pkgs, 97 + lib, 97 98 ... 98 99 }: { 99 100 # Self hosted stuff 100 101 101 102 cow = { 102 - cocoon = let 103 - secure = x: "/nix/persist/secure/cocoon-keys/${x}"; 104 - in { 103 + tranquil = { 105 104 enable = true; 106 - did = config.cow.bean.atproto.did; 107 - favicon = ../res/favicon.ico; 108 - port = 8080; 109 - jwkPath = secure "jwk.key"; 110 - rotationPath = secure "rotation.key"; 111 - adminPassPath = secure "admin.pass"; 112 - sessionSecretPath = secure "session.key"; 113 - emailSetupPath = secure "email.env"; 114 - relays = [ 115 - "https://bsky.network" 116 - "https://relay.cerulea.blue" 117 - "https://relay.fire.hose.cam" 118 - "https://relay2.fire.hose.cam" 119 - "https://relay3.fr.hose.cam" 120 - "https://relay.hayescmd.net" 121 - "https://relay.xero.systems" 122 - "https://relay.upcloud.world" 123 - "https://relay.feeds.blue" 124 - "https://atproto.africa" 125 - "https://relay.whey.party" 126 - ]; 127 - email = "ben@bwc9876.dev"; 128 - hostname = "pds.bwc9876.dev"; 105 + domainName = "tranquil.bwc9876.dev"; 106 + envFile = "/nix/persist/secure/tranquil.env"; 129 107 }; 130 108 tangled = { 131 109 knot = { ··· 162 140 acmeRoot = null; # Doing DNS challenges 163 141 useACMEHost = "bwc9876.dev"; 164 142 }; 165 - virtualHosts."spindle.bwc9876.dev" = { 143 + virtualHosts."tranquil.bwc9876.dev" = { 166 144 addSSL = true; 167 145 acmeRoot = null; # DNS 168 146 useACMEHost = "bwc9876.dev"; 169 147 }; 170 - virtualHosts."pds.bwc9876.dev" = { 148 + virtualHosts."spindle.bwc9876.dev" = { 171 149 addSSL = true; 172 150 acmeRoot = null; # DNS 173 151 useACMEHost = "bwc9876.dev"; ··· 180 158 proxyPass = "http://localhost:6767"; 181 159 recommendedProxySettings = true; 182 160 }; 161 + }; 162 + }; 163 + 164 + services.tranquil-pds.settings.email = { 165 + from_address = lib.strings.join "@" ["beanpds" (lib.strings.join "." ["gmail" "com"])]; 166 + from_name = "Bean PDS"; 167 + }; 168 + 169 + programs.msmtp = { 170 + enable = true; 171 + accounts.default = { 172 + auth = true; 173 + # ssshhhhh 174 + host = "smtp.gmail.com"; 175 + user = lib.strings.join "@" ["beanpds" (lib.strings.join "." ["gmail" "com"])]; 176 + from = lib.strings.join "@" ["beanpds" (lib.strings.join "." ["gmail" "com"])]; 177 + passwordeval = "cat /nix/persist/secure/smtp-pass"; 178 + port = 587; 179 + tls = true; 183 180 }; 184 181 }; 185 182
-158
nixosModules/cocoon.nix
··· 1 - {inputs, ...}: { 2 - config, 3 - lib, 4 - pkgs, 5 - ... 6 - }: { 7 - options.cow.cocoon = { 8 - enable = lib.mkEnableOption "Cocoon PDS"; 9 - did = lib.mkOption { 10 - type = lib.types.str; 11 - description = "DID of server owner"; 12 - }; 13 - port = lib.mkOption { 14 - type = lib.types.port; 15 - description = "Port to bind to"; 16 - default = 8080; 17 - }; 18 - userName = lib.mkOption { 19 - type = lib.types.str; 20 - description = "User name to create and use for the service."; 21 - default = "cocoon"; 22 - }; 23 - dataDir = lib.mkOption { 24 - type = lib.types.str; 25 - description = "Runtime path to store data at"; 26 - default = "/var/lib/cocoon"; 27 - }; 28 - jwkPath = lib.mkOption { 29 - type = lib.types.str; 30 - description = "Runtime path of the JWK key"; 31 - }; 32 - rotationPath = lib.mkOption { 33 - type = lib.types.str; 34 - description = "Runtime path of the rotation key"; 35 - }; 36 - sessionSecretPath = lib.mkOption { 37 - type = lib.types.str; 38 - description = "Runtime path of the session secret"; 39 - }; 40 - adminPassPath = lib.mkOption { 41 - type = lib.types.str; 42 - description = "Runtime path of the admin password"; 43 - }; 44 - email = lib.mkOption { 45 - type = lib.types.str; 46 - description = "Contact email for this PDS' administrator"; 47 - }; 48 - relays = lib.mkOption { 49 - type = lib.types.listOf lib.types.str; 50 - description = "Relay servers to use for event syncing"; 51 - default = ["https://bsky.network"]; 52 - }; 53 - fallbackProxy = lib.mkOption { 54 - type = lib.types.str; 55 - description = "Proxy for xrpc requests that we can't service"; 56 - default = "did:web:api.bsky.app#bsky_appview"; 57 - }; 58 - hostname = lib.mkOption { 59 - type = lib.types.str; 60 - description = "Public facing hostname for the server"; 61 - }; 62 - favicon = lib.mkOption { 63 - type = lib.types.nullOr lib.types.path; 64 - description = "Path to favicon file to serve"; 65 - default = null; 66 - }; 67 - emailSetupPath = lib.mkOption { 68 - type = lib.types.nullOr lib.types.path; 69 - description = "Path of file to use to configure email sending with SMTP"; 70 - default = null; 71 - }; 72 - }; 73 - 74 - config = let 75 - conf = config.cow.cocoon; 76 - in 77 - lib.mkIf conf.enable { 78 - cow.imperm.keep = [ 79 - conf.dataDir 80 - ]; 81 - 82 - services.nginx.virtualHosts.${conf.hostname} = { 83 - serverAliases = [".${conf.hostname}"]; 84 - 85 - # All stolen from Isabel 86 - # https://github.com/isabelroses/dotfiles/blob/262ae19c1e92be5d759f40020e894113ba5d5d44/modules/nixos/services/pds/default.nix 87 - locations = let 88 - mkAgeAssured = state: { 89 - return = "200 '${builtins.toJSON state}'"; 90 - extraConfig = '' 91 - default_type application/json; 92 - add_header access-control-allow-headers "authorization,dpop,atproto-accept-labelers,atproto-proxy" always; 93 - add_header access-control-allow-origin "*" always; 94 - add_header X-Frame-Options SAMEORIGIN always; 95 - add_header X-Content-Type-Options nosniff; 96 - ''; 97 - }; 98 - in { 99 - "/xrpc/app.bsky.unspecced.getAgeAssuranceState" = mkAgeAssured { 100 - lastInitiatedAt = "2026-01-19T05:59:50.391Z"; 101 - status = "assured"; 102 - }; 103 - "/xrpc/app.bsky.ageassurance.getConfig" = mkAgeAssured { 104 - regions = []; 105 - }; 106 - "/xrpc/app.bsky.ageassurance.getState" = mkAgeAssured { 107 - state = { 108 - lastInitiatedAt = "2026-01-19T05:59:50.391Z"; 109 - status = "assured"; 110 - access = "full"; 111 - }; 112 - metadata = { 113 - accountCreatedAt = "2026-01-19T05:59:50.391Z"; 114 - }; 115 - }; 116 - "=/favicon.ico" = lib.mkIf (conf.favicon != null) { 117 - extraConfig = '' 118 - alias ${conf.favicon}; 119 - ''; 120 - }; 121 - 122 - # pass everything else to the pds 123 - "/" = { 124 - proxyPass = "http://localhost:${toString conf.port}"; 125 - proxyWebsockets = true; 126 - extraConfig = '' 127 - add_header access-control-allow-headers "authorization,dpop,atproto-accept-labelers,atproto-proxy" always; 128 - ''; 129 - }; 130 - }; 131 - }; 132 - 133 - services.cocoon = { 134 - enable = true; 135 - environmentFiles = 136 - [ 137 - conf.adminPassPath 138 - conf.sessionSecretPath 139 - ] 140 - ++ lib.optional (conf.emailSetupPath != null) conf.emailSetupPath; 141 - settings = lib.mapAttrs' (k: v: lib.nameValuePair "COCOON_${k}" v) { 142 - JWK_PATH = conf.jwkPath; 143 - ROTATION_KEY_PATH = conf.rotationPath; 144 - 145 - DID = conf.did; 146 - HOSTNAME = conf.hostname; 147 - ADDR = ":${builtins.toString conf.port}"; 148 - CONTACT_EMAIL = conf.email; 149 - 150 - RELAYS = lib.join "," conf.relays; 151 - FALLBACK_PROXY = conf.fallbackProxy; 152 - 153 - DB_TYPE = "sqlite"; 154 - DB_NAME = "${conf.dataDir}/cocoon.db"; 155 - }; 156 - }; 157 - }; 158 - }
+67
nixosModules/tranquil.nix
··· 1 + {inputs, ...}: { 2 + config, 3 + lib, 4 + pkgs, 5 + ... 6 + }: { 7 + imports = [inputs.tranquil.nixosModules.default]; 8 + 9 + options.cow.tranquil = { 10 + enable = lib.mkEnableOption "tranquil PDS"; 11 + port = lib.mkOption { 12 + type = lib.types.port; 13 + description = "Port to bind to"; 14 + default = 3300; 15 + }; 16 + envFile = lib.mkOption { 17 + type = lib.types.path; 18 + description = "Path to environment file to use for secrets"; 19 + }; 20 + domainName = lib.mkOption { 21 + type = lib.types.str; 22 + description = "Public hostname for tranquil server"; 23 + }; 24 + }; 25 + 26 + config = let 27 + conf = config.cow.tranquil; 28 + in 29 + lib.mkIf conf.enable { 30 + cow.imperm.keep = [config.services.tranquil-pds.dataDir]; 31 + 32 + services.tranquil-pds = { 33 + enable = true; 34 + database.createLocally = true; 35 + environmentFiles = [conf.envFile]; 36 + 37 + settings = { 38 + server = { 39 + inherit (conf) port; 40 + hostname = conf.domainName; 41 + invite_code_required = true; 42 + age_assurance_override = true; 43 + }; 44 + 45 + firehose.crawlers = [ 46 + "https://bsky.network" 47 + "https://relay.cerulea.blue" 48 + "https://relay.fire.hose.cam" 49 + "https://relay2.fire.hose.cam" 50 + "https://relay3.fr.hose.cam" 51 + "https://relay.hayescmd.net" 52 + "https://relay.xero.systems" 53 + "https://relay.upcloud.world" 54 + "https://relay.feeds.blue" 55 + "https://atproto.africa" 56 + "https://relay.whey.party" 57 + ]; 58 + }; 59 + }; 60 + 61 + services.nginx.virtualHosts.${conf.domainName}.locations."/" = { 62 + proxyPass = "http://127.0.0.1:${toString conf.port}"; 63 + proxyWebsockets = true; 64 + extraConfig = "client_max_body_size ${toString config.services.tranquil-pds.settings.server.max_blob_size};"; 65 + }; 66 + }; 67 + }