From fddca8d53452f3b90d14d082cb145a0696e487ef Mon Sep 17 00:00:00 2001 From: Henry-Hiles Date: Wed, 17 Jun 2026 23:25:24 -0400 Subject: [PATCH] feat: Static musl builds via nix fix: don't do check on all builds Checks can be done with `nix flake check`, no need to slow down build process with this. feat: add static binary build instructions to docs feat: add max-perf package feat: add build-nix workflow chore: add changelog fix: fix max-perf-static packages not statically linking feat: improve docs for building with nix chore: more descriptive name for binary build step of workflow fix: resolve review comment about Haswell CPUs chore: enable __structuredAttrs on build This is a good practice for modern nix packages --- .forgejo/workflows/build-nix.yml | 71 ++++++++++++++++++++++++++ changelog.d/1853.feature | 1 + docs/deploying/generic.mdx | 10 +++- docs/deploying/nixos.mdx | 9 +++- nix/packages/continuwuity.nix | 27 ++++------ nix/packages/default.nix | 87 +++++++++++++++++++++++++------- 6 files changed, 166 insertions(+), 39 deletions(-) create mode 100644 .forgejo/workflows/build-nix.yml create mode 100644 changelog.d/1853.feature diff --git a/.forgejo/workflows/build-nix.yml b/.forgejo/workflows/build-nix.yml new file mode 100644 index 000000000..48abb4919 --- /dev/null +++ b/.forgejo/workflows/build-nix.yml @@ -0,0 +1,71 @@ +name: Build / Static via Nix + +concurrency: + group: "build-nix-${{ forge.ref }}" + cancel-in-progress: true + +on: + push: + tags: + - "v*.*.*" + workflow_dispatch: + schedule: + - cron: '30 0 * * *' + +jobs: + build: + name: "Build ${{ matrix.filename }} Binary" + runs-on: ubuntu-latest + + strategy: + matrix: + include: + - package: default-static-x86_64 + filename: conduwuit-linux-static-amd64 + - package: default-static-aarch64 + filename: conduwuit-linux-static-arm64 + + - package: max-perf-static-aarch64 + filename: conduwuit-linux-static-arm64-maxperf + - package: max-perf-haswell-static-x86_64 + filename: conduwuit-haswell-linux-static-amd64-maxperf + + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 + + - name: Install Lix + uses: https://github.com/samueldr/lix-gha-installer-action@a0fee77b2a98bb7c5c0ed7ae6d6ad4903dbdad0d + with: + extra_nix_config: experimental-features = nix-command flakes flake-self-attrs + + - name: Build static binary + run: | + nix build .#${{ matrix.package }} + install -D result/bin/conduwuit /tmp/binaries/${{ matrix.filename }} + + - name: Upload binary artifact + uses: forgejo/upload-artifact@v4 + with: + name: ${{ matrix.filename }} + path: /tmp/binaries/${{ matrix.filename }} + + release-binaries: + name: "Release Binaries" + runs-on: ubuntu-latest + needs: + - build + permissions: + contents: write + if: startsWith(github.ref, 'refs/tags/') + steps: + - name: Download binary artifacts + uses: forgejo/download-artifact@v4 + with: + pattern: conduwuit* + path: binaries + merge-multiple: true + - name: Create Release and Upload + uses: https://github.com/softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3 + with: + draft: true + files: binaries/* diff --git a/changelog.d/1853.feature b/changelog.d/1853.feature new file mode 100644 index 000000000..3215da0b5 --- /dev/null +++ b/changelog.d/1853.feature @@ -0,0 +1 @@ +Added static builds using Nix, allowing for Continuwuity on musl. During this, we also introduced a `max-perf-haswell` package, separating it from `max-perf`, so you may want to swap to this if you are on NixOS. Contributed by @Henry-Hiles (QuadRadical). diff --git a/docs/deploying/generic.mdx b/docs/deploying/generic.mdx index faf306918..2a07b68de 100644 --- a/docs/deploying/generic.mdx +++ b/docs/deploying/generic.mdx @@ -47,9 +47,15 @@ #### Performance-optimised builds ### Nix -Theres a Nix package defined in our flake, available for Linux and MacOS. Add continuwuity as an input to your flake, and use `inputs.continuwuity.packages.${system}.default` to get a working Continuwuity package. +If you wish to generate a static binary, you can do so using Nix: `nix build git+https://forgejo.ellis.link/continuwuation/continuwuity#packageName`, where `packageName` is one of: -If you simply wish to generate a binary using Nix, you can run `nix build git+https://forgejo.ellis.link/continuwuation/continuwuity` to generate a binary in `result/bin/conduwuit`. +- `default-static-x86_64` +- `default-static-aarch64` +- `max-perf-static-x86_64` +- `max-perf-haswell-static-x86_64` +- `max-perf-static-aarch64` + +`max-perf` takes longer to build, but has more runtime optimizations. Haswell builds are optimized for modern CPUs. ### Compiling diff --git a/docs/deploying/nixos.mdx b/docs/deploying/nixos.mdx index aecc22c64..0d193b4a2 100644 --- a/docs/deploying/nixos.mdx +++ b/docs/deploying/nixos.mdx @@ -47,9 +47,16 @@ ### Available options - `extraEnvironment`: Extra environment variables to pass to the Continuwuity server - `package`: The Continuwuity package to use, defaults to `pkgs.matrix-continuwuity` - You may want to override this to be from our flake, for faster updates and unstable versions: + ```nix - package = inputs.continuwuity.packages.${pkgs.stdenv.hostPlatform.system}.default; + package = inputs.continuwuity.packages.${pkgs.stdenv.hostPlatform.system}.packageName; ``` + + Where `packageName` is one of: + - `default` + - `max-perf`: Takes longer to build, but has more runtime optimizations + - `max-perf-haswell`: Optimized for modern CPUs, don't use if your CPU is not Haswell or later. + - `admin.enable`: Whether to add the `conduwuit` binary to `PATH` for administration (enabled by default) - `settings`: The Continuwuity configuration diff --git a/nix/packages/continuwuity.nix b/nix/packages/continuwuity.nix index 7dc9e9e21..c10312947 100644 --- a/nix/packages/continuwuity.nix +++ b/nix/packages/continuwuity.nix @@ -5,11 +5,10 @@ liburing, craneLib, pkg-config, - callPackage, rustPlatform, cargoExtraArgs ? "", rustflags ? "", - rocksdb ? callPackage ./rocksdb.nix { }, + target_cpu ? null, profile ? "release", }: let @@ -28,18 +27,24 @@ let }; attrs = { + __structuredAttrs = true; + strictDeps = true; + inherit src; + nativeBuildInputs = [ pkg-config rustPlatform.bindgenHook ]; buildInputs = lib.optionals stdenv.hostPlatform.isLinux [ liburing ]; + doCheck = false; env = { - ROCKSDB_INCLUDE_DIR = "${rocksdb}/include"; - ROCKSDB_LIB_DIR = "${rocksdb}/lib"; CARGO_PROFILE = profile; RUSTFLAGS = rustflags; - }; + } + // (lib.optionalAttrs (target_cpu != null) { + TARGET_CPU = target_cpu; + }); }; in craneLib.buildPackage ( @@ -47,18 +52,6 @@ craneLib.buildPackage ( inherit cargoExtraArgs; cargoArtifacts = craneLib.buildDepsOnly attrs; - # Needed to make continuwuity link to rocksdb - postFixup = lib.optionalString stdenv.hostPlatform.isLinux '' - old_rpath="$(patchelf --print-rpath $out/bin/conduwuit)" - extra_rpath="${ - lib.makeLibraryPath [ - rocksdb - ] - }" - - patchelf --set-rpath "$old_rpath:$extra_rpath" $out/bin/conduwuit - ''; - meta = { description = "A community-driven Matrix homeserver in Rust"; mainProgram = "conduwuit"; diff --git a/nix/packages/default.nix b/nix/packages/default.nix index 6052f3649..d73b4b022 100644 --- a/nix/packages/default.nix +++ b/nix/packages/default.nix @@ -1,4 +1,5 @@ { + inputs, self, ... }: @@ -6,29 +7,77 @@ perSystem = { self', + lib, pkgs, + system, craneLib, ... }: { - packages = { - rocksdb = pkgs.callPackage ./rocksdb.nix { }; - default = pkgs.callPackage ./continuwuity.nix { - inherit self craneLib; - # extra features via `cargoExtraArgs` - cargoExtraArgs = "-F http3"; - # extra RUSTFLAGS via `rustflags` - # the stuff below is required for http3 - rustflags = "--cfg reqwest_unstable"; - }; - # users may also override this with other cargo profiles to build for other feature sets - # - # other examples include: - # - # - release-high-perf - max-perf = self'.packages.default.override { - profile = "release-max-perf"; - }; - }; + packages = + let + mkPackages = + pkgs: + let + fnx = inputs.fenix.packages.${system}; + + isStatic = pkgs.stdenv.hostPlatform.isMusl; + + craneLib = (inputs.crane.mkLib pkgs).overrideToolchain ( + _: + if isStatic then + fnx.combine [ + self'.packages.stable-toolchain + (fnx.targets.${pkgs.stdenv.hostPlatform.config}.stable).rust-std + ] + else + self'.packages.stable-toolchain + ); + + default = pkgs.callPackage ./continuwuity.nix { + inherit self craneLib; + liburing = (if isStatic then pkgs.pkgsStatic else pkgs).liburing; + # extra features via `cargoExtraArgs` + cargoExtraArgs = "-F http3"; + # extra RUSTFLAGS via `rustflags` + # the stuff below is required for http3 + rustflags = "--cfg reqwest_unstable"; + }; + + # users may also override this with other cargo profiles to build for other feature sets + # for features configuration see `default` package which enables http3 by default + + max-perf = default.override { + # compiles slower but with more thorough optimizations + profile = "release-max-perf"; + }; + + max-perf-haswell = max-perf.override { + # compiles explicitly for haswell arch cpus + target_cpu = "haswell"; + }; + in + { + inherit default max-perf max-perf-haswell; + + }; + in + (mkPackages pkgs) + // (lib.mapAttrs' (name: value: lib.nameValuePair "${name}-static-x86_64" value) ( + mkPackages ( + import inputs.nixpkgs { + localSystem = system; + crossSystem = "x86_64-unknown-linux-musl"; + } + ) + )) + // (lib.mapAttrs' (name: value: lib.nameValuePair "${name}-static-aarch64" value) ( + mkPackages ( + import inputs.nixpkgs { + localSystem = system; + crossSystem = "aarch64-unknown-linux-musl"; + } + ) + )); }; }