A tiny Subsonic/Jellyfin/S3 server in Rust
navidrome subsonic s3 emby jellyfin
0

Configure Feed

Select the types of activity you want to include in your feed.

smolsonic / flake.nix
6.6 kB 227 lines
1{ 2 description = "smolsonic - A tiny Subsonic-compatible music server"; 3 4 inputs = { 5 nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; 6 7 crane = { 8 url = "github:ipetkov/crane"; 9 inputs.nixpkgs.follows = "nixpkgs"; 10 }; 11 12 fenix = { 13 url = "github:nix-community/fenix"; 14 inputs.nixpkgs.follows = "nixpkgs"; 15 inputs.rust-analyzer-src.follows = ""; 16 }; 17 18 flake-utils.url = "github:numtide/flake-utils"; 19 20 advisory-db = { 21 url = "github:rustsec/advisory-db"; 22 flake = false; 23 }; 24 }; 25 26 outputs = { self, nixpkgs, crane, fenix, flake-utils, advisory-db, ... }: 27 flake-utils.lib.eachDefaultSystem (system: 28 let 29 pkgs = import nixpkgs { 30 inherit system; 31 }; 32 33 inherit (pkgs) lib; 34 35 craneLib = crane.mkLib pkgs; 36 37 src = craneLib.cleanCargoSource ./.; 38 39 # node_modules for the s3webui SPA. `bun install` needs the network, 40 # so dependency resolution lives in a fixed-output derivation. 41 # 42 # The tree is NOT platform-independent: native optional deps (e.g. 43 # @tailwindcss/oxide-*) are installed per-OS/CPU, so each system 44 # needs its own hash. 45 # 46 # Updating: change package.json/bun.lock, set the current system's 47 # hash below to lib.fakeHash, run `nix build`, copy the hash Nix 48 # reports on mismatch back in. Repeat per platform. 49 s3webuiNodeModules = pkgs.stdenv.mkDerivation { 50 pname = "smolsonic-s3webui-node-modules"; 51 version = "0.10.0"; 52 53 src = lib.fileset.toSource { 54 root = ./s3webui; 55 fileset = lib.fileset.unions [ 56 ./s3webui/package.json 57 ./s3webui/bun.lock 58 ]; 59 }; 60 61 nativeBuildInputs = [ pkgs.bun ]; 62 63 dontConfigure = true; 64 65 buildPhase = '' 66 runHook preBuild 67 export HOME=$(mktemp -d) 68 bun install --frozen-lockfile --no-progress 69 runHook postBuild 70 ''; 71 72 installPhase = '' 73 runHook preInstall 74 mv node_modules $out 75 runHook postInstall 76 ''; 77 78 dontFixup = true; 79 80 outputHashMode = "recursive"; 81 outputHashAlgo = "sha256"; 82 outputHash = { 83 x86_64-linux = "sha256-yKUGN1F8I1S6M5GgXeVA5y/u2gm8vYjyKxGLNO1nB90="; 84 aarch64-linux = lib.fakeHash; 85 aarch64-darwin = "sha256-VuAM4wkTAL8kIE0KseAC79F4+qLbLzR4g3AWiQjwaT0="; 86 x86_64-darwin = lib.fakeHash; 87 }.${system}; 88 }; 89 90 # Build the React SPA. The resulting `dist/` is embedded into the 91 # smolsonic binary at compile time via rust-embed. 92 s3webui = pkgs.stdenv.mkDerivation { 93 pname = "smolsonic-s3webui"; 94 version = "0.10.0"; 95 96 src = ./s3webui; 97 98 nativeBuildInputs = [ pkgs.bun pkgs.nodejs ]; 99 100 configurePhase = '' 101 runHook preConfigure 102 cp -r ${s3webuiNodeModules} node_modules 103 chmod -R u+w node_modules 104 patchShebangs node_modules 105 export HOME=$(mktemp -d) 106 runHook postConfigure 107 ''; 108 109 buildPhase = '' 110 runHook preBuild 111 bun run build 112 runHook postBuild 113 ''; 114 115 installPhase = '' 116 runHook preInstall 117 cp -r dist $out 118 runHook postInstall 119 ''; 120 }; 121 122 # Common arguments can be set here to avoid repeating them later 123 commonArgs = { 124 inherit src; 125 126 pname = "smolsonic"; 127 version = "0.10.0"; 128 129 nativeBuildInputs = [ 130 pkgs.pkg-config 131 ]; 132 133 buildInputs = [ 134 pkgs.openssl 135 pkgs.openssl.dev 136 ] ++ lib.optionals pkgs.stdenv.isDarwin [ 137 pkgs.libiconv 138 ]; 139 140 # rust-embed reads s3webui/dist at compile time. cleanCargoSource 141 # strips the s3webui directory, so we drop the pre-built SPA back 142 # in before cargo runs. 143 preBuild = '' 144 mkdir -p s3webui 145 cp -r ${s3webui} s3webui/dist 146 chmod -R u+w s3webui/dist 147 ''; 148 }; 149 150 craneLibLLvmTools = craneLib.overrideToolchain 151 (fenix.packages.${system}.complete.withComponents [ 152 "cargo" 153 "llvm-tools" 154 "rustc" 155 ]); 156 157 # Build *just* the cargo dependencies, so we can reuse 158 # all of that work (e.g. via cachix) when running in CI 159 cargoArtifacts = craneLib.buildDepsOnly commonArgs; 160 161 # Build the actual crate itself, reusing the dependency 162 # artifacts from above. 163 smolsonic = craneLib.buildPackage (commonArgs // { 164 inherit cargoArtifacts; 165 }); 166 167 in 168 { 169 checks = { 170 # Build the crate as part of `nix flake check` for convenience 171 inherit smolsonic; 172 173 # Run clippy (and deny all warnings) on the crate source, 174 # again, reusing the dependency artifacts from above. 175 smolsonic-clippy = craneLib.cargoClippy (commonArgs // { 176 inherit cargoArtifacts; 177 cargoClippyExtraArgs = "--all-targets -- --deny warnings"; 178 }); 179 180 smolsonic-doc = craneLib.cargoDoc (commonArgs // { 181 inherit cargoArtifacts; 182 }); 183 184 # Check formatting 185 smolsonic-fmt = craneLib.cargoFmt { 186 inherit src; 187 }; 188 189 # Audit dependencies 190 smolsonic-audit = craneLib.cargoAudit { 191 inherit src advisory-db; 192 }; 193 194 # Run tests with cargo-nextest 195 smolsonic-nextest = craneLib.cargoNextest (commonArgs // { 196 inherit cargoArtifacts; 197 partitions = 1; 198 partitionType = "count"; 199 }); 200 } // lib.optionalAttrs (system == "x86_64-linux") { 201 # NB: cargo-tarpaulin only supports x86_64 systems 202 smolsonic-coverage = craneLib.cargoTarpaulin (commonArgs // { 203 inherit cargoArtifacts; 204 }); 205 }; 206 207 packages = { 208 default = smolsonic; 209 smolsonic-llvm-coverage = craneLibLLvmTools.cargoLlvmCov (commonArgs // { 210 inherit cargoArtifacts; 211 }); 212 }; 213 214 apps.default = flake-utils.lib.mkApp { 215 drv = smolsonic; 216 }; 217 218 devShells.default = pkgs.mkShell { 219 inputsFrom = builtins.attrValues self.checks.${system}; 220 221 nativeBuildInputs = with pkgs; [ 222 cargo 223 rustc 224 ]; 225 }; 226 }); 227}