atagen

malice

public
Star0
Watch0
6d6a4c34bdc1e8cf83db351ae723740a99ab62e7
2
ssh://brewery@pls.lobotomise.me:33/atagen/malice.git
flake.nixNix347 lines11.3 KB
1
{
2
  description = "Malice: a hosted Matrix client backed by macltok";
3
4
  inputs = {
5
    nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
6
    fenix = {
7
      url = "github:nix-community/fenix";
8
      inputs.nixpkgs.follows = "nixpkgs";
9
    };
10
  };
11
12
  outputs =
13
    {
14
      self,
15
      nixpkgs,
16
      fenix,
17
    }:
18
    let
19
      systems = [
20
        "x86_64-linux"
21
        "aarch64-linux"
22
      ];
23
      forAllSystems = nixpkgs.lib.genAttrs systems;
24
      cleanSrc =
25
        root:
26
        nixpkgs.lib.cleanSourceWith {
27
          src = root;
28
          filter =
29
            path: type:
30
            nixpkgs.lib.cleanSourceFilter path type
31
            && !(
32
              type == "directory"
33
              && builtins.elem (baseNameOf path) [
34
                "target"
35
                "node_modules"
36
                "dist"
37
                "dist-device"
38
              ]
39
            );
40
        };
41
      workerLock = builtins.fromTOML (builtins.readFile ./crates/malice-worker/Cargo.lock);
42
      lockedVersion = name: (nixpkgs.lib.findFirst (p: p.name == name) null workerLock.package).version;
43
      # wasm-bindgen-test-runner refuses a module built by any other wasm-bindgen version
44
      wasmBindgenCli =
45
        pkgs:
46
        pkgs.buildWasmBindgenCli rec {
47
          src = pkgs.fetchCrate {
48
            pname = "wasm-bindgen-cli";
49
            version = lockedVersion "wasm-bindgen";
50
            hash = "sha256-a7lcXJnnZkYReja+iUO7NqqrWyv3toxnUgQb8s4IS5s=";
51
          };
52
          cargoDeps = pkgs.rustPlatform.fetchCargoVendor {
53
            inherit src;
54
            inherit (src) pname version;
55
            hash = "sha256-R1Tas33Ursy8kqsxguAkG0ZhNed2n5uFTAhw1l2qlLY=";
56
          };
57
        };
58
      wasmToolchain =
59
        system:
60
        let
61
          toolchains = fenix.packages.${system};
62
        in
63
        toolchains.combine [
64
          toolchains.stable.cargo
65
          toolchains.stable.clippy
66
          toolchains.stable.rustc
67
          toolchains.stable.rustfmt
68
          toolchains.stable.rust-src
69
          toolchains.targets.wasm32-unknown-unknown.stable.rust-std
70
        ];
71
      webNodeModules =
72
        pkgs:
73
        pkgs.importNpmLock.buildNodeModules {
74
          npmRoot = ./web;
75
          nodejs = pkgs.nodejs_22;
76
        };
77
      buildWeb =
78
        pkgs:
79
        {
80
          pname,
81
          task,
82
          outDir,
83
          postPatch ? "",
84
        }:
85
        pkgs.stdenvNoCC.mkDerivation {
86
          inherit pname postPatch;
87
          version = "0.1.0";
88
          src = cleanSrc ./web;
89
          npmDeps = webNodeModules pkgs;
90
          disallowedReferences = [
91
            (webNodeModules pkgs)
92
            pkgs.nodejs_22
93
          ];
94
          nativeBuildInputs = [
95
            pkgs.nodejs_22
96
            pkgs.importNpmLock.hooks.linkNodeModulesHook
97
          ];
98
          buildPhase = ''
99
            runHook preBuild
100
            export HOME=$TMPDIR
101
            npm run ${task}
102
            runHook postBuild
103
          '';
104
          installPhase = ''
105
            runHook preInstall
106
            mkdir -p $out/share/malice
107
            cp -R ${outDir}/. $out/share/malice/
108
            runHook postInstall
109
          '';
110
        };
111
    in
112
    {
113
      packages = forAllSystems (
114
        system:
115
        let
116
          pkgs = nixpkgs.legacyPackages.${system};
117
          wasmPlatform = pkgs.makeRustPlatform {
118
            cargo = wasmToolchain system;
119
            rustc = wasmToolchain system;
120
          };
121
          web = buildWeb pkgs {
122
            pname = "malice-web";
123
            task = "build";
124
            outDir = "dist";
125
          };
126
          backend = pkgs.rustPlatform.buildRustPackage {
127
            pname = "malice-server";
128
            version = "0.1.0";
129
            src = cleanSrc ./.;
130
            cargoLock = {
131
              lockFile = ./Cargo.lock;
132
              allowBuiltinFetchGit = true;
133
            };
134
            nativeBuildInputs = [ pkgs.pkg-config ];
135
            buildInputs = [ pkgs.sqlite ];
136
            cargoBuildFlags = [
137
              "-p"
138
              "malice"
139
            ];
140
            cargoTestFlags = [
141
              "-p"
142
              "malice"
143
            ];
144
            # preBuild = "export NIX_BUILD_CORES=2";
145
            preCheck = ''
146
              cargo build --release --bin malice --target ${pkgs.stdenv.hostPlatform.rust.rustcTarget} --offline --locked
147
            '';
148
            SSL_CERT_FILE = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
149
          };
150
          staticServer = pkgs.rustPlatform.buildRustPackage {
151
            pname = "malice-static";
152
            version = "0.1.0";
153
            src = cleanSrc ./.;
154
            cargoLock = {
155
              lockFile = ./Cargo.lock;
156
              allowBuiltinFetchGit = true;
157
            };
158
            cargoBuildFlags = [
159
              "-p"
160
              "malice-static"
161
            ];
162
            cargoTestFlags = [
163
              "-p"
164
              "malice-static"
165
            ];
166
            meta.mainProgram = "malice-static";
167
          };
168
          server = pkgs.symlinkJoin {
169
            name = "malice";
170
            paths = [
171
              backend
172
              web
173
            ];
174
            nativeBuildInputs = [ pkgs.makeWrapper ];
175
            postBuild = ''
176
              wrapProgram $out/bin/malice --set MALICE_WEB_DIR ${web}/share/malice
177
            '';
178
          };
179
          # the wasm-bindgen `--target web` glue for malice-worker's `Host`, consumed by
180
          # web/src/worker/pkg (gitignored, worker-web's TS imports it as ./pkg/malice_worker.js)
181
          workerWasm = wasmPlatform.buildRustPackage {
182
            pname = "malice-worker-wasm";
183
            version = "0.1.0";
184
            src = cleanSrc ./.;
185
            cargoRoot = "crates/malice-worker";
186
            cargoLock = {
187
              lockFile = ./crates/malice-worker/Cargo.lock;
188
              allowBuiltinFetchGit = true;
189
            };
190
            nativeBuildInputs = [
191
              (wasmBindgenCli pkgs)
192
              pkgs.removeReferencesTo
193
            ];
194
            buildPhase = ''
195
              runHook preBuild
196
              cd crates/malice-worker
197
              cargo build --offline --frozen --release --lib --target wasm32-unknown-unknown
198
              mkdir -p $out
199
              wasm-bindgen --target web --out-dir $out --out-name malice_worker \
200
                target/wasm32-unknown-unknown/release/malice_worker.wasm
201
              remove-references-to -t ${wasmToolchain system} $out/*.wasm
202
              runHook postBuild
203
            '';
204
            doCheck = false;
205
            installPhase = "true";
206
            disallowedReferences = [ (wasmToolchain system) ];
207
          };
208
          web-device = buildWeb pkgs {
209
            pname = "malice-web-device";
210
            task = "build:device";
211
            outDir = "dist-device";
212
            postPatch = ''
213
              mkdir -p src/worker/pkg
214
              cp -R ${workerWasm}/. src/worker/pkg/
215
            '';
216
          };
217
          local = pkgs.symlinkJoin {
218
            name = "malice-local";
219
            paths = [
220
              staticServer
221
              web-device
222
            ];
223
            nativeBuildInputs = [ pkgs.makeWrapper ];
224
            postBuild = ''
225
              wrapProgram $out/bin/malice-static \
226
                --set MALICE_WEB_DIR ${web-device}/share/malice
227
            '';
228
          };
229
        in
230
        {
231
          inherit
232
            web
233
            server
234
            web-device
235
            local
236
            ;
237
          default = server;
238
        }
239
      );
240
241
      devShells = forAllSystems (
242
        system:
243
        let
244
          pkgs = nixpkgs.legacyPackages.${system};
245
        in
246
        {
247
          default = pkgs.mkShell {
248
            packages = [
249
              (wasmToolchain system)
250
              (wasmBindgenCli pkgs)
251
              pkgs.rust-analyzer
252
              pkgs.nodejs_22
253
              pkgs.importNpmLock.hooks.linkNodeModulesHook
254
              pkgs.pkg-config
255
              pkgs.sqlite
256
              pkgs.firefox
257
              pkgs.geckodriver
258
              pkgs.chromium
259
              pkgs.matrix-continuwuity
260
              pkgs.nushell
261
            ];
262
            CHROMIUM_PATH = nixpkgs.lib.getExe pkgs.chromium;
263
            npmDeps = webNodeModules pkgs;
264
            # the hook's own npmRoot would be a store path, so link into the checkout's web/ instead
265
            shellHook = ''
266
              npmRoot="$(git rev-parse --show-toplevel 2>/dev/null || pwd)/web" linkNodeModulesHook
267
            '';
268
            # fenix's rustc links through its bundled rust-lld, which skips nix's ld-wrapper and so
269
            # the store rpaths, leaving the native server unable to find libsqlite3 at run time
270
            "CARGO_TARGET_${
271
              nixpkgs.lib.toUpper (builtins.replaceStrings [ "-" ] [ "_" ] pkgs.stdenv.hostPlatform.config)
272
            }_RUSTFLAGS" =
273
              "-C linker-features=-lld";
274
          };
275
        }
276
      );
277
278
      nixosModules.malice = import ./nix/module.nix { inherit self; };
279
      nixosModules.default = self.nixosModules.malice;
280
      checks = forAllSystems (
281
        system:
282
        let
283
          pkgs = nixpkgs.legacyPackages.${system};
284
          wasmPlatform = pkgs.makeRustPlatform {
285
            cargo = wasmToolchain system;
286
            rustc = wasmToolchain system;
287
          };
288
          # continuwuity refuses to start without /etc/resolv.conf, which the build sandbox lacks, or with
289
          # stdenv's deliberately bogus SSL_CERT_FILE. no exec, run.nu launches through a shell that exits at
290
          # once and would trip --die-with-parent, so this shell stays as the parent run.nu kills
291
          sandboxedHomeserver = pkgs.writeShellScriptBin "conduwuit" ''
292
            export SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt
293
            ${pkgs.lib.getExe pkgs.bubblewrap} --die-with-parent --dev-bind / / --tmpfs /etc \
294
              --ro-bind ${pkgs.writeText "resolv.conf" "nameserver 127.0.0.1\n"} /etc/resolv.conf \
295
              ${pkgs.lib.getExe' pkgs.matrix-continuwuity "conduwuit"} "$@"
296
          '';
297
        in
298
        {
299
          default = self.packages.${system}.default;
300
          worker-wasm = self.packages.${system}.web-device;
301
          web = pkgs.stdenvNoCC.mkDerivation {
302
            pname = "malice-web-check";
303
            version = "0.1.0";
304
            src = cleanSrc ./web;
305
            npmDeps = webNodeModules pkgs;
306
            nativeBuildInputs = [
307
              pkgs.nodejs_22
308
              pkgs.importNpmLock.hooks.linkNodeModulesHook
309
            ];
310
            buildPhase = ''
311
              runHook preBuild
312
              export HOME=$TMPDIR
313
              npm run check
314
              npm test
315
              runHook postBuild
316
            '';
317
            installPhase = "touch $out";
318
          };
319
          worker-browser = wasmPlatform.buildRustPackage {
320
            pname = "malice-worker-browser-check";
321
            version = "0.1.0";
322
            src = cleanSrc ./.;
323
            cargoRoot = "crates/malice-worker";
324
            cargoLock = {
325
              lockFile = ./crates/malice-worker/Cargo.lock;
326
              allowBuiltinFetchGit = true;
327
            };
328
            nativeBuildInputs = [
329
              (wasmBindgenCli pkgs)
330
              pkgs.firefox
331
              pkgs.geckodriver
332
              sandboxedHomeserver
333
              pkgs.nushell
334
            ];
335
            buildPhase = ''
336
              runHook preBuild
337
              export HOME=$TMPDIR
338
              nu --no-config-file crates/malice-worker/run.nu
339
              runHook postBuild
340
            '';
341
            doCheck = false;
342
            installPhase = "touch $out";
343
          };
344
        }
345
      );
346
    };
347
}