Alternative ATProto PDS implementation
at oauth 5.9 kB view raw
1{ 2 description = "Alternative Bluesky PDS implementation"; 3 inputs = { 4 nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 5 crane.url = "github:ipetkov/crane"; 6 flake-utils.url = "github:numtide/flake-utils"; 7 rust-overlay = { 8 url = "github:oxalica/rust-overlay"; 9 inputs.nixpkgs.follows = "nixpkgs"; 10 }; 11 }; 12 outputs = { self, nixpkgs, crane, flake-utils, rust-overlay, ... }: 13 flake-utils.lib.eachDefaultSystem (system: 14 let 15 pkgs = import nixpkgs { 16 inherit system; 17 overlays = [ (import rust-overlay) ]; 18 }; 19 craneLib = (crane.mkLib pkgs).overrideToolchain (p: p.rust-bin.selectLatestNightlyWith (toolchain: toolchain.default.override { 20 extensions = [ 21 "rust-src" # for rust-analyzer 22 "rust-analyzer" 23 ]; 24 })); 25 26 inherit (pkgs) lib; 27 unfilteredRoot = ./.; # The original, unfiltered source 28 src = lib.fileset.toSource { 29 root = unfilteredRoot; 30 fileset = lib.fileset.unions [ 31 # Default files from crane (Rust and cargo files) 32 (craneLib.fileset.commonCargoSources unfilteredRoot) 33 # Include all the .sql migrations as well 34 ./migrations 35 ]; 36 }; 37 # Common arguments can be set here to avoid repeating them later 38 commonArgs = { 39 inherit src; 40 strictDeps = true; 41 nativeBuildInputs = with pkgs; [ 42 pkg-config 43 gcc 44 ]; 45 buildInputs = [ 46 # Add additional build inputs here 47 pkgs.openssl 48 ] ++ lib.optionals pkgs.stdenv.isDarwin [ 49 # Additional darwin specific inputs can be set here 50 pkgs.libiconv 51 pkgs.darwin.apple_sdk.frameworks.Security 52 ]; 53 54 # Additional environment variables can be set directly 55 # MY_CUSTOM_VAR = "some value"; 56 }; 57 58 # Build *just* the cargo dependencies, so we can reuse 59 # all of that work (e.g. via cachix) when running in CI 60 cargoArtifacts = craneLib.buildDepsOnly commonArgs; 61 62 # Build the actual crate itself, reusing the dependency 63 # artifacts from above. 64 bluepds = craneLib.buildPackage (commonArgs // { 65 inherit cargoArtifacts; 66 nativeBuildInputs = (commonArgs.nativeBuildInputs or [ ]) ++ [ 67 pkgs.sqlx-cli 68 ]; 69 preBuild = '' 70 export DATABASE_URL=sqlite:./sqlite.db 71 cargo sqlx database create 72 cargo sqlx migrate run 73 ''; 74 postInstall = '' 75 mkdir -p $out/var/lib/bluepds 76 cp ./default.toml $out/var/lib/bluepds/ 77 cp ./sqlite.db $out/var/lib/bluepds/ 78 ''; 79 }); 80 in 81 { 82 checks = { 83 # Build the crate as part of `nix flake check` for convenience 84 inherit bluepds; 85 }; 86 87 packages = { 88 default = bluepds; 89 inherit bluepds; 90 }; 91 92 devShells.default = craneLib.devShell { 93 # Inherit inputs from checks. 94 checks = self.checks.${system}; 95 96 # Additional dev-shell environment variables can be set directly 97 # MY_CUSTOM_DEVELOPMENT_VAR = "something else"; 98 RUST_BACKTRACE = 1; 99 NIXOS_OZONE_WL=1; 100 101 # Extra inputs can be added here; cargo and rustc are provided by default. 102 packages = with pkgs; [ 103 sqlx-cli 104 bacon 105 sqlite 106 rust-analyzer 107 rustfmt 108 clippy 109 git 110 nixd 111 direnv 112 libpq 113 ]; 114 }; 115 }) 116 // flake-utils.lib.eachDefaultSystemPassThrough (system: 117 { 118 nixosModules = { 119 default = { pkgs, lib, config, ... }: with lib; let 120 cfg = config.services.bluepds; 121 in 122 { 123 options.services.bluepds = { 124 enable = mkEnableOption "Enable bluepds"; 125 host_name = mkOption { 126 type = types.str; 127 default = "pds.example.com"; 128 description = "The public hostname of the PDS."; 129 }; 130 listen_address = mkOption { 131 type = types.str; 132 default = "0.0.0.0:8000"; 133 description = "The address to listen to for incoming requests."; 134 }; 135 test = mkOption { 136 type = types.str; 137 default = "true"; 138 description = "Test mode. This instructs BluePDS not to federate with the rest of the AT network."; 139 }; 140 package = mkOption { 141 type = types.package; 142 default = self.packages.${pkgs.system}.default; 143 description = "The path to the bluepds package."; 144 }; 145 }; 146 config = mkIf cfg.enable { 147 systemd.services.bluepds = { 148 description = "ATProto PDS server"; 149 wantedBy = [ "multi-user.target" ]; 150 after = [ "network.target" ]; 151 requires = [ "network-online.target" ]; 152 environment = { 153 BLUEPDS_TEST = "${cfg.test}"; 154 BLUEPDS_HOST_NAME = "${cfg.host_name}"; 155 BLUEPDS_LISTEN_ADDRESS = "${cfg.listen_address}"; 156 }; 157 serviceConfig = { 158 ExecStart = "${cfg.package}/bin/bluepds"; 159 ProtectHome = true; 160 WorkingDirectory= "/var/lib/bluepds"; 161 Restart = "on-failure"; 162 Type = "exec"; 163 }; 164 }; 165 }; 166 }; 167 }; 168 }); 169}