An AT Protocol PDS
1{
2 description = "moonstone — personal ATProto PDS";
3
4 inputs = {
5 nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
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
13 outputs = { self, nixpkgs, flake-utils, rust-overlay }:
14 flake-utils.lib.eachDefaultSystem (system:
15 let
16 pkgs = import nixpkgs {
17 inherit system;
18 overlays = [ (import rust-overlay) ];
19 };
20
21 # Pin Rust to match rust-toolchain.toml (1.86)
22 rustToolchain = pkgs.rust-bin.stable."1.86.0".default;
23
24 nodejs = pkgs.nodejs_20;
25
26 # ---------------------------------------------------------------------------
27 # @ewanc26/moonstone-native — Rust neon addon
28 # ---------------------------------------------------------------------------
29 nativeAddon = pkgs.stdenv.mkDerivation {
30 pname = "moonstone-native";
31 version = "0.1.0";
32 src = ./.;
33
34 nativeBuildInputs = [
35 rustToolchain
36 pkgs.pkg-config
37 nodejs
38 pkgs.pnpm
39 ];
40 buildInputs = [ pkgs.openssl ];
41
42 buildPhase = ''
43 export HOME=$(mktemp -d)
44 cd packages/native
45 cargo build --release --manifest-path Cargo.toml
46 cp ../../target/release/libmoonstone_native.so index.node 2>/dev/null || \
47 cp ../../target/release/libmoonstone_native.dylib index.node 2>/dev/null || \
48 cp ../../target/release/moonstone_native.dll index.node 2>/dev/null
49 '';
50
51 installPhase = ''
52 mkdir -p $out
53 cp index.node $out/
54 cp package.json $out/
55 cp index.d.ts $out/
56 '';
57 };
58
59 # ---------------------------------------------------------------------------
60 # @ewanc26/moonstone-server — full server build (TS + native addon)
61 # ---------------------------------------------------------------------------
62 moonstoneServer = pkgs.buildNpmPackage {
63 pname = "moonstone-server";
64 version = "0.1.0";
65 src = ./.;
66
67 # Fill in with: cd moonstone && prefetch-npm-deps pnpm-lock.yaml
68 npmDepsHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
69
70 nativeBuildInputs = [ nodejs pkgs.pnpm rustToolchain pkgs.pkg-config ];
71 buildInputs = [ pkgs.openssl ];
72
73 buildPhase = ''
74 export HOME=$(mktemp -d)
75 # 1. Build @ewanc26/moonstone-native
76 cargo build --release
77 cp target/release/libmoonstone_native.so packages/native/index.node 2>/dev/null || \
78 cp target/release/libmoonstone_native.dylib packages/native/index.node 2>/dev/null || true
79 # 2. Install JS deps + build @ewanc26/moonstone-config and @ewanc26/moonstone-server
80 pnpm install --frozen-lockfile
81 pnpm run build:ts
82 '';
83
84 installPhase = ''
85 mkdir -p $out/bin $out/lib/moonstone
86
87 # @ewanc26/moonstone-server dist
88 cp -r packages/server/dist $out/lib/moonstone/server
89 cp packages/server/package.json $out/lib/moonstone/
90
91 # @ewanc26/moonstone-native addon
92 install -Dm755 packages/native/index.node $out/lib/moonstone/native/index.node
93 cp packages/native/package.json $out/lib/moonstone/native/
94
95 # node_modules (needed at runtime for @atproto/pds etc.)
96 cp -r node_modules $out/lib/moonstone/
97
98 # Entrypoint wrapper
99 cat > $out/bin/moonstone-pds <<'EOF'
100 #!/usr/bin/env ${nodejs}/bin/node
101 import('${placeholder "out"}/lib/moonstone/server/index.js')
102 EOF
103 chmod +x $out/bin/moonstone-pds
104 '';
105 };
106 in
107 {
108 packages = {
109 native = nativeAddon;
110 server = moonstoneServer;
111 default = moonstoneServer;
112 };
113
114 devShells.default = pkgs.mkShell {
115 buildInputs = [
116 nodejs
117 pkgs.pnpm
118 rustToolchain
119 pkgs.pkg-config
120 pkgs.openssl
121 ];
122 };
123 }
124 ) // {
125 nixosModules.moonstone = import ./nix/module.nix;
126 };
127}