atagen

malice

public
Star0
Watch0
dffd63b58af439639de9f8e155d0365d83605a8b
2
ssh://brewery@pls.lobotomise.me:33/atagen/malice.git
flake.nixNix313 lines10.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
          nativeBuildInputs = [
91
            pkgs.nodejs_22
92
            pkgs.importNpmLock.hooks.linkNodeModulesHook
93
          ];
94
          buildPhase = ''
95
            runHook preBuild
96
            export HOME=$TMPDIR
97
            npm run ${task}
98
            runHook postBuild
99
          '';
100
          installPhase = ''
101
            runHook preInstall
102
            mkdir -p $out/share/malice
103
            cp -R ${outDir}/. $out/share/malice/
104
            runHook postInstall
105
          '';
106
        };
107
    in
108
    {
109
      packages = forAllSystems (
110
        system:
111
        let
112
          pkgs = nixpkgs.legacyPackages.${system};
113
          wasmPlatform = pkgs.makeRustPlatform {
114
            cargo = wasmToolchain system;
115
            rustc = wasmToolchain system;
116
          };
117
          web = buildWeb pkgs {
118
            pname = "malice-web";
119
            task = "build";
120
            outDir = "dist";
121
          };
122
          backend = pkgs.rustPlatform.buildRustPackage {
123
            pname = "malice-server";
124
            version = "0.1.0";
125
            src = cleanSrc ./.;
126
            cargoLock.lockFile = ./Cargo.lock;
127
            nativeBuildInputs = [ pkgs.pkg-config ];
128
            buildInputs = [ pkgs.sqlite ];
129
            cargoBuildFlags = [
130
              "-p"
131
              "malice"
132
            ];
133
            cargoTestFlags = [
134
              "-p"
135
              "malice"
136
            ];
137
            # preBuild = "export NIX_BUILD_CORES=2";
138
            preCheck = ''
139
              cargo build --release --bin malice --target ${pkgs.stdenv.hostPlatform.rust.rustcTarget} --offline --locked
140
            '';
141
            SSL_CERT_FILE = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
142
          };
143
          staticServer = pkgs.rustPlatform.buildRustPackage {
144
            pname = "malice-static";
145
            version = "0.1.0";
146
            src = cleanSrc ./.;
147
            cargoLock.lockFile = ./Cargo.lock;
148
            cargoBuildFlags = [
149
              "-p"
150
              "malice-static"
151
            ];
152
            cargoTestFlags = [
153
              "-p"
154
              "malice-static"
155
            ];
156
            meta.mainProgram = "malice-static";
157
          };
158
          server = pkgs.symlinkJoin {
159
            name = "malice";
160
            paths = [
161
              backend
162
              web
163
            ];
164
            nativeBuildInputs = [ pkgs.makeWrapper ];
165
            postBuild = ''
166
              wrapProgram $out/bin/malice --set MALICE_WEB_DIR ${web}/share/malice
167
            '';
168
          };
169
          # the wasm-bindgen `--target web` glue for malice-worker's `Host`, consumed by
170
          # web/src/worker/pkg (gitignored, worker-web's TS imports it as ./pkg/malice_worker.js)
171
          workerWasm = wasmPlatform.buildRustPackage {
172
            pname = "malice-worker-wasm";
173
            version = "0.1.0";
174
            src = cleanSrc ./.;
175
            cargoRoot = "crates/malice-worker";
176
            cargoLock.lockFile = ./crates/malice-worker/Cargo.lock;
177
            nativeBuildInputs = [
178
              (wasmBindgenCli pkgs)
179
              pkgs.removeReferencesTo
180
            ];
181
            buildPhase = ''
182
              runHook preBuild
183
              cd crates/malice-worker
184
              cargo build --offline --frozen --release --lib --target wasm32-unknown-unknown
185
              mkdir -p $out
186
              wasm-bindgen --target web --out-dir $out --out-name malice_worker \
187
                target/wasm32-unknown-unknown/release/malice_worker.wasm
188
              remove-references-to -t ${wasmToolchain system} $out/*.wasm
189
              runHook postBuild
190
            '';
191
            doCheck = false;
192
            installPhase = "true";
193
            disallowedReferences = [ (wasmToolchain system) ];
194
          };
195
          web-device = buildWeb pkgs {
196
            pname = "malice-web-device";
197
            task = "build:device";
198
            outDir = "dist-device";
199
            postPatch = ''
200
              mkdir -p src/worker/pkg
201
              cp -R ${workerWasm}/. src/worker/pkg/
202
            '';
203
          };
204
          local = pkgs.symlinkJoin {
205
            name = "malice-local";
206
            paths = [
207
              staticServer
208
              web-device
209
            ];
210
            nativeBuildInputs = [ pkgs.makeWrapper ];
211
            postBuild = ''
212
              wrapProgram $out/bin/malice-static \
213
                --set MALICE_WEB_DIR ${web-device}/share/malice
214
            '';
215
          };
216
        in
217
        {
218
          inherit
219
            web
220
            server
221
            web-device
222
            local
223
            ;
224
          default = server;
225
        }
226
      );
227
228
      devShells = forAllSystems (
229
        system:
230
        let
231
          pkgs = nixpkgs.legacyPackages.${system};
232
        in
233
        {
234
          default = pkgs.mkShell {
235
            packages = [
236
              (wasmToolchain system)
237
              (wasmBindgenCli pkgs)
238
              pkgs.rust-analyzer
239
              pkgs.nodejs_22
240
              pkgs.importNpmLock.hooks.linkNodeModulesHook
241
              pkgs.pkg-config
242
              pkgs.sqlite
243
              pkgs.firefox
244
              pkgs.geckodriver
245
              pkgs.chromium
246
              pkgs.matrix-continuwuity
247
              pkgs.nushell
248
            ];
249
            CHROMIUM_PATH = nixpkgs.lib.getExe pkgs.chromium;
250
            npmDeps = webNodeModules pkgs;
251
            # the hook's own npmRoot would be a store path, so link into the checkout's web/ instead
252
            shellHook = ''
253
              npmRoot="$(git rev-parse --show-toplevel 2>/dev/null || pwd)/web" linkNodeModulesHook
254
            '';
255
            # fenix's rustc links through its bundled rust-lld, which skips nix's ld-wrapper and so
256
            # the store rpaths, leaving the native server unable to find libsqlite3 at run time
257
            "CARGO_TARGET_${
258
              nixpkgs.lib.toUpper (builtins.replaceStrings [ "-" ] [ "_" ] pkgs.stdenv.hostPlatform.config)
259
            }_RUSTFLAGS" =
260
              "-C linker-features=-lld";
261
          };
262
        }
263
      );
264
265
      nixosModules.malice = import ./nix/module.nix { inherit self; };
266
      nixosModules.default = self.nixosModules.malice;
267
      checks = forAllSystems (
268
        system:
269
        let
270
          pkgs = nixpkgs.legacyPackages.${system};
271
          wasmPlatform = pkgs.makeRustPlatform {
272
            cargo = wasmToolchain system;
273
            rustc = wasmToolchain system;
274
          };
275
          # continuwuity refuses to start without /etc/resolv.conf, which the build sandbox lacks, or with
276
          # stdenv's deliberately bogus SSL_CERT_FILE. no exec, run.nu launches through a shell that exits at
277
          # once and would trip --die-with-parent, so this shell stays as the parent run.nu kills
278
          sandboxedHomeserver = pkgs.writeShellScriptBin "conduwuit" ''
279
            export SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt
280
            ${pkgs.lib.getExe pkgs.bubblewrap} --die-with-parent --dev-bind / / --tmpfs /etc \
281
              --ro-bind ${pkgs.writeText "resolv.conf" "nameserver 127.0.0.1\n"} /etc/resolv.conf \
282
              ${pkgs.lib.getExe' pkgs.matrix-continuwuity "conduwuit"} "$@"
283
          '';
284
        in
285
        {
286
          default = self.packages.${system}.default;
287
          worker-wasm = self.packages.${system}.web-device;
288
          worker-browser = wasmPlatform.buildRustPackage {
289
            pname = "malice-worker-browser-check";
290
            version = "0.1.0";
291
            src = cleanSrc ./.;
292
            cargoRoot = "crates/malice-worker";
293
            cargoLock.lockFile = ./crates/malice-worker/Cargo.lock;
294
            nativeBuildInputs = [
295
              (wasmBindgenCli pkgs)
296
              pkgs.firefox
297
              pkgs.geckodriver
298
              sandboxedHomeserver
299
              pkgs.nushell
300
            ];
301
            buildPhase = ''
302
              runHook preBuild
303
              export HOME=$TMPDIR
304
              nu --no-config-file crates/malice-worker/run.nu
305
              runHook postBuild
306
            '';
307
            doCheck = false;
308
            installPhase = "touch $out";
309
          };
310
        }
311
      );
312
    };
313
}