From 5f16cf565f00a7d14cd8641c95a23e5243ebb44a Mon Sep 17 00:00:00 2001 From: Damir Modyarov Date: Fri, 18 Sep 2026 18:08:12 +0300 Subject: [PATCH] build: Implement nix packaging --- flake.lock | 61 +++++++++++++++++++++++++++++++++ flake.nix | 34 +++++++++++++++++++ nix/module.nix | 81 ++++++++++++++++++++++++++++++++++++++++++++ nix/node-modules.nix | 55 ++++++++++++++++++++++++++++++ nix/package.nix | 76 +++++++++++++++++++++++++++++++++++++++++ package.json | 2 +- 6 files changed, 308 insertions(+), 1 deletion(-) create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 nix/module.nix create mode 100644 nix/node-modules.nix create mode 100644 nix/package.nix diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..5a9e372 --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1788450739, + "narHash": "sha256-glZLQlzIn1fXH6PazR2iUmTo7kzzyYSshrWhLS9TqCU=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "31729ca8cbdb4fa927b34e5f4353e6a83f39e993", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1789546076, + "narHash": "sha256-zVxLZiSnmaaPLwnhj7pwmqe3axBg/C6nG5JZsJMh2g4=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "b1b875982b17dabde9b4a37f3e229e74913e6db3", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib": { + "locked": { + "lastModified": 1788057806, + "narHash": "sha256-DTQSMxzDWmT0zhguthvegnVkn7CFqGCv4IHCzk5ZUpM=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "596e2e3940e09b2abbeb03f75fa1828c57fcd72c", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-parts": "flake-parts", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..15ec379 --- /dev/null +++ b/flake.nix @@ -0,0 +1,34 @@ +{ + description = "Hackfed daemon"; + + inputs = { + flake-parts.url = "github:hercules-ci/flake-parts"; + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + }; + + outputs = inputs@{ flake-parts, ... }: + let + mkPackage = pkgs: pkgs.callPackage ./nix/package.nix {}; + in flake-parts.lib.mkFlake { inherit inputs; } { + systems = [ "x86_64-linux" "aarch64-linux" "aarch64-darwin" "x86_64-darwin" ]; + perSystem = { config, self', inputs', pkgs, system, ... }: { + devShells.default = pkgs.mkShell { + packages = with pkgs; [ + bun + ]; + }; + packages = let + hackfedd = mkPackage pkgs; + in { + inherit hackfedd; + default = hackfedd; + }; + }; + flake = { + overlays.default = final: prev: { + hackfedd = mkPackage prev; + }; + nixosModules.default = { imports = [ ./nix/module.nix ]; }; + }; + }; +} diff --git a/nix/module.nix b/nix/module.nix new file mode 100644 index 0000000..66a94c7 --- /dev/null +++ b/nix/module.nix @@ -0,0 +1,81 @@ +{ config, lib, pkgs, ... }: let + hackfedd = pkgs.callPackage ./package.nix {}; + cfg = config.services.hackfedd; + defaultUser = "hackfedd"; + defaultGroup = "hackfedd"; + format = pkgs.formats.yaml { }; + configFile = format.generate "config.yml" cfg.settings; +in with lib; { + options.services.hackfedd = { + enable = mkEnableOption "hackfedd service"; + + settings = mkOption { + default = { }; + description = '' + Configuration for hackfedd. See + + for more information. + ''; + type = types.submodule { + freeformType = format.type; + }; + example = literalExpression '' + { + general = { + org_id = "acme"; + }; + } + ''; + }; + + package = mkOption { + type = types.package; + default = hackfedd; + defaultText = literalExpression "pkgs.callPackage ./package.nix {}"; + }; + + user = mkOption { + description = "User account under which hackfedd service runs."; + default = defaultUser; + type = types.str; + }; + + group = mkOption { + description = "Group under which hackfedd service runs."; + default = defaultGroup; + type = types.str; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = [ cfg.package ]; + + users.users = mkIf (cfg.user == defaultUser) { + hackfedd = { + description = "hackfedd service user"; + isSystemUser = true; + group = cfg.group; + home = "/var/lib/hackfedd"; + createHome = true; + }; + }; + + users.groups = mkIf (cfg.group == defaultGroup) { + hackfedd = { }; + }; + + systemd.services.hackfedd = { + description = "hackfedd service"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + Type = "simple"; + User = cfg.user; + Group = cfg.group; + WorkingDirectory = "/var/lib/hackfedd"; + ExecStart = "${getExe cfg.package} agent --config ${configFile}"; + Restart = "on-failure"; + }; + }; + }; +} diff --git a/nix/node-modules.nix b/nix/node-modules.nix new file mode 100644 index 0000000..0aad3b5 --- /dev/null +++ b/nix/node-modules.nix @@ -0,0 +1,55 @@ +# References: +# https://github.com/NixOS/nixpkgs/blob/c79db2f14a7deda260c8cd4f5e66f1b059321cee/pkgs/by-name/eq/equibop/package.nix +# https://github.com/NixOS/nixpkgs/blob/c79db2f14a7deda260c8cd4f5e66f1b059321cee/pkgs/by-name/op/opencode/package.nix +{ + lib, + stdenvNoCC, + hackfedd, + bun, + writableTmpDirAsHomeHook, +}: +stdenvNoCC.mkDerivation { + inherit (hackfedd) version src; + pname = hackfedd.pname + "-modules"; + + impureEnvVars = lib.fetchers.proxyImpureEnvVars ++ [ + "GIT_PROXY_COMMAND" + "SOCKS_SERVER" + ]; + + nativeBuildInputs = [ + bun + writableTmpDirAsHomeHook + ]; + + dontConfigure = true; + dontFixup = true; + + buildPhase = '' + runHook preBuild + + export BUN_INSTALL_CACHE_DIR=$(mktemp -d) + + bun install \ + --cpu "*" \ + --os "*" \ + --filter ./ \ + --frozen-lockfile \ + --ignore-scripts \ + --no-progress + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + cp -R ./node_modules $out + + runHook postInstall + ''; + + outputHash = "sha256-uLJo1yvsd3EMqidgKt47WHCXl+IZ2Ix8JZd2YtPh6ME="; + outputHashAlgo = "sha256"; + outputHashMode = "recursive"; +} diff --git a/nix/package.nix b/nix/package.nix new file mode 100644 index 0000000..6117be4 --- /dev/null +++ b/nix/package.nix @@ -0,0 +1,76 @@ +{ + lib, + stdenv, + callPackage, + makeWrapper, + bun, + nodejs, + ast-grep, + writableTmpDirAsHomeHook, +}: +stdenv.mkDerivation (finalAttrs: { + pname = "hackfedd"; + version = "0.0.0"; + + src = ../.; + + node-modules = callPackage ./node-modules.nix { hackfedd = finalAttrs.finalPackage; }; # helps when the parent package is overidden + + nativeBuildInputs = [ + bun + nodejs + makeWrapper + writableTmpDirAsHomeHook + ast-grep + ]; + + configurePhase = '' + runHook preConfigure + + cp -R ${finalAttrs.node-modules} node_modules + chmod u+w -R node_modules + + # https://github.com/oven-sh/bun/issues/13076 + substituteInPlace node_modules/css-tree/package.json \ + --replace-fail './lib/index.js' './cjs/index.cjs' + + # jsdom uses fs.readFile to load assets from relative paths, replacing them to bundled paths + ast-grep -U -p 'path.resolve(__dirname, "../../../browser/default-stylesheet.css")' --rewrite 'path.resolve(import.meta.dir, "default-stylesheet.css")' -l js node_modules/jsdom/lib/jsdom/living/css/helpers/computed-style.js + ast-grep -U -p 'require.resolve("./xhr-sync-worker.js")' --rewrite 'require("node:path").resolve(import.meta.dir, "xhr-sync-worker.js")' -l js node_modules/jsdom/lib/jsdom/living/xhr/XMLHttpRequest-impl.js + + runHook postConfigure + ''; + + buildPhase = '' + runHook preBuild + bun build --compile --outfile=hackfedd \ + --asset ./node_modules/jsdom/lib/jsdom/browser/default-stylesheet.css \ + --asset ./node_modules/jsdom/lib/jsdom/living/xhr/xhr-sync-worker.js \ + ./src/index.ts + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + mkdir -p $out/bin + cp hackfedd $out/bin + + runHook postInstall + ''; + + dontStrip = true; + + meta = { + description = "Daemon for Hackerspace Federation"; + homepage = "https://github.com/hackfed/hackfedd"; + license = lib.licenses.mpl20; + maintainers = [ { + name = "Damir Modyarov"; + email = "damir@otomir23.me"; + github = "otomir23"; + githubId = 21289906; + } ]; + mainProgram = "hackfedd"; + }; +}) diff --git a/package.json b/package.json index 0dad6b4..37cf368 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/hackfed/hfd.git" + "url": "git+https://github.com/hackfed/hackfedd.git" }, "scripts": { "lint": "tsc --noEmit && eslint .",