From e296506391175ba22dc4a02e9245995eb9336569 Mon Sep 17 00:00:00 2001 From: "Jonathan M. Wilbur" Date: Mon, 19 Jan 2026 15:28:32 -0500 Subject: [PATCH 1/9] feat(meerkat): build nix package --- .editorconfig | 2 +- .gitignore | 1 + default.nix | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 default.nix diff --git a/.editorconfig b/.editorconfig index 37edb2968..ae265aaa9 100644 --- a/.editorconfig +++ b/.editorconfig @@ -47,7 +47,7 @@ end_of_line = lf [pkg/PKGBUILD] end_of_line = lf -[*.rb] +[*.{rb,nix}] end_of_line = lf indent_size = 2 indent_style = space diff --git a/.gitignore b/.gitignore index 76a4ab9c8..b99c6fe41 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ *.zst demo/ +result/ *.snap k8s/charts/meerkat-dsa/*.tgz diff --git a/default.nix b/default.nix new file mode 100644 index 000000000..57cee38df --- /dev/null +++ b/default.nix @@ -0,0 +1,70 @@ +{ lib +, stdenv +, nodejs_24 +, buildNpmPackage +}: + +let + buildStage = buildNpmPackage { + pname = "meerkat-dsa-build"; + version = "4.0.0"; + src = ./.; + npmDepsHash = "sha256-V7td2VSpJD/3n+j9X8LhvSBMvqaE/o1gCSruQfNa/ME="; + makeCacheWritable = true; + npmFlags = [ "--no-audit" "--no-fund" "--no-save" "--ignore-scripts" "--verbose" "--legacy-peer-deps" ]; + buildPhase = '' + npx nx \ + --tuiAutoExit=true \ + --outputStyle=static \ + run meerkat:build \ + --skipNxCache \ + --skipRemoteCache \ + --skip-nx-cache \ + --verbose + ''; + installPhase = '' + cp -r dist/apps/meerkat $out + ''; + }; + + runtimeStage = buildNpmPackage { + pname = "meerkat-dsa"; + version = "4.0.0"; + src = buildStage; + npmDepsHash = "sha256-xHMniJesi213HX4zbR8hFE9XsdU+2QhWzWMQ6KC1Jvs="; + npmFlags = [ "--no-audit" "--no-fund" "--no-save" "--ignore-scripts" "--verbose" ]; + dontNpmBuild = true; + installPhase = '' + mkdir -p $out/lib + cp -r * $out/lib + cp prisma/prisma.config.ts $out/lib + mkdir -p $out/bin + # This will overwrite the bin that buildNpmPackage creates. + cat > $out/bin/meerkat <<'EOF' + #!${stdenv.shell} + set -euo pipefail + + # If the migration fails, still carry on: we do not want a failed migration + # (which is infrequently needed to begin with) to make us unable to start + # Meerkat DSA + # + # NOTE: Prisma seems to search for migrations relative to the config file, not + # the current directory. + PRISMA_HIDE_UPDATE_MESSAGE=1 ${nodejs_24}/bin/npx prisma migrate deploy \ + --schema @APP_DIR@/lib/prisma/schema.prisma \ + --config @APP_DIR@/lib/prisma.config.ts || true + + exec ${nodejs_24}/bin/node @APP_DIR@/lib/main.js start "$@" + EOF + substituteInPlace $out/bin/meerkat --replace "@APP_DIR@" "$out" + chmod +x $out/bin/meerkat + ''; + meta = with lib; { + description = "Meerkat X.500 Directory System Agent (DSA) and LDAP Server"; + license = licenses.mit; + platforms = platforms.linux; + mainProgram = "meerkat"; + }; + }; +in +runtimeStage From 4dea7e64a74d18b4d64d5efdcbcfc94d0099b8c2 Mon Sep 17 00:00:00 2001 From: "Jonathan M. Wilbur" Date: Mon, 19 Jan 2026 19:50:04 -0500 Subject: [PATCH 2/9] feat(meerkat): possibly broken nixos systemd service --- apps/meerkat-docs/docs/development.md | 27 ++++++++++ pkg/meerkat-dsa.nix | 74 +++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 pkg/meerkat-dsa.nix diff --git a/apps/meerkat-docs/docs/development.md b/apps/meerkat-docs/docs/development.md index 1747e3fe4..33fc04661 100644 --- a/apps/meerkat-docs/docs/development.md +++ b/apps/meerkat-docs/docs/development.md @@ -124,6 +124,33 @@ Run `brew uninstall meerkat_dsa` to uninstall it from your system. Run `brew test -d meerkat_dsa` to run tests after it is installed. +### Nix Package + +First, ensure that `pkg/default.nix` is moved to the root of this repository: +in other words, it should be in the same folder as `nx.json`. Then run: + +```bash +nix-build -E '(import {}).callPackage ./default.nix {}' +``` + +I don't really know why that is needed. Why doesn't it "just work"(tm)? + +Then, your build outputs will be symlinked to `./result`. Just poke around in +there: you'll get it. + +To test the Systemd service (which is a separate package), it seems like you +have to have NixOS. However, you can do a little pre-validation on it like so: + +```bash +nix-instantiate --parse pkg/meerkat-dsa.nix +``` + +Then you can do a little more validation like so: + +```bash +nix-instantiate '' -A config.systemd.services.meerkat-dsa -I nixos-config=./pkg/meerkat-dsa.nix +``` + ## CI [Here](https://github.com/actions/runner-images) are the different runners diff --git a/pkg/meerkat-dsa.nix b/pkg/meerkat-dsa.nix new file mode 100644 index 000000000..5b3419bde --- /dev/null +++ b/pkg/meerkat-dsa.nix @@ -0,0 +1,74 @@ +# This has not been tested. +{ config, lib, pkgs, ... }: + +let + cfg = config.services.meerkat-dsa; +in { + system.stateVersion = "19.03"; # No touchy! + + options.services.meerkat-dsa = { + enable = lib.mkEnableOption "Meerkat X.500 Directory System Agent (DSA) and LDAP Server"; + dataDir = lib.mkOption { + type = lib.types.path; + default = "/var/lib/meerkat"; + }; + + environmentFile = lib.mkOption { + type = lib.types.path; + default = "/etc/meerkat/meerkat.env"; + description = "Environment file (using .env syntax)"; + }; + }; + + config = lib.mkIf cfg.enable { + + users.users.meerkat = { + isSystemUser = true; + group = "meerkat"; + }; + + users.groups.meerkat = {}; + + # Documented here: https://github.com/NixOS/nixos/blob/5f444a4d8d49a497bcfabe2544bda264c845653e/modules/system/boot/systemd-unit-options.nix + # Example application: https://github.com/DMarby/picsum-photos/blob/a4359f9d85e99aaf11a110590a681510e21130c4/flake.nix#L178 + systemd.services.meerkat-dsa = { + description = "Meerkat DSA"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + serviceConfig = { + Type = "simple"; + User = "meerkat"; + Group = "meerkat"; + ExecStart = "${pkgs.meerkat-dsa}/bin/meerkat"; + Restart = "on-failure"; + RestartSec = "30s"; + WorkingDirectory = cfg.dataDir; + EnvironmentFile = cfg.environmentFile; + PassEnvironment = "LANG NO_COLOR"; + NoNewPrivileges = "yes"; + ProtectSystem = "full"; + ProtectHome = "yes"; + ProtectProc = "invisible"; + PrivateTmp = "yes"; + PrivateDevices = "yes"; + PrivateUsers = "self"; + SecureBits = ""; + ProtectClock = "yes"; + ProtectHostname = "yes"; + ProtectKernelModules = "yes"; + ProtectKernelLogs = "yes"; + ProtectControlGroups = "yes"; + RestrictRealtime = "yes"; + PrivateMounts = "yes"; + SystemCallFilter="~@cpu-emuation @chown @debug @keyring @module @mount @obsolete @privileged @reboot @resources @setuid @swap"; + LogNamespace = "meerkat"; + }; + environment = { + NODE_ENV = "production"; + DATABASE_URL = "file:${cfg.dataDir}/meerkat.db"; + PRISMA_HIDE_UPDATE_MESSAGE = "1"; + MEERKAT_LOG_SYSTEMD_LEVEL_PREFIX = "1"; + }; + }; + }; +} From 42d222ea320c9b27ed2c3e37e9486ecc55eb7c25 Mon Sep 17 00:00:00 2001 From: "Jonathan M. Wilbur" Date: Tue, 20 Jan 2026 03:38:54 -0500 Subject: [PATCH 3/9] fix(meerkat): last few issues with systemd service nix package --- pkg/meerkat-dsa.nix | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/pkg/meerkat-dsa.nix b/pkg/meerkat-dsa.nix index 5b3419bde..c371bd753 100644 --- a/pkg/meerkat-dsa.nix +++ b/pkg/meerkat-dsa.nix @@ -1,11 +1,8 @@ -# This has not been tested. { config, lib, pkgs, ... }: let cfg = config.services.meerkat-dsa; in { - system.stateVersion = "19.03"; # No touchy! - options.services.meerkat-dsa = { enable = lib.mkEnableOption "Meerkat X.500 Directory System Agent (DSA) and LDAP Server"; dataDir = lib.mkOption { @@ -22,6 +19,8 @@ in { config = lib.mkIf cfg.enable { + system.stateVersion = "26.05"; + users.users.meerkat = { isSystemUser = true; group = "meerkat"; @@ -35,6 +34,10 @@ in { description = "Meerkat DSA"; wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; + # This seems to be required even though undocumented. + startLimitBurst = 10; + # This seems to be required even though undocumented. + startLimitIntervalSec = 5; serviceConfig = { Type = "simple"; User = "meerkat"; From da1dbbc7c5339d1b24d1056b35ca27dd0a848c8e Mon Sep 17 00:00:00 2001 From: "Jonathan M. Wilbur" Date: Tue, 20 Jan 2026 04:06:56 -0500 Subject: [PATCH 4/9] pkg(meerkat): create flake.nix --- apps/meerkat-docs/docs/development.md | 8 ++++++ flake.nix | 40 +++++++++++++++++++++++++++ pkg/overlay.nix | 3 ++ 3 files changed, 51 insertions(+) create mode 100644 flake.nix create mode 100644 pkg/overlay.nix diff --git a/apps/meerkat-docs/docs/development.md b/apps/meerkat-docs/docs/development.md index 33fc04661..b5ad71f3a 100644 --- a/apps/meerkat-docs/docs/development.md +++ b/apps/meerkat-docs/docs/development.md @@ -151,6 +151,14 @@ Then you can do a little more validation like so: nix-instantiate '' -A config.systemd.services.meerkat-dsa -I nixos-config=./pkg/meerkat-dsa.nix ``` +If you see + +``` +error: attribute 'meerkat-dsa' in selection path 'config.systemd.services.meerkat-dsa' not found +``` + +try removing `lib.mkIf cfg.enable` from `meerkat-dsa.nix`. + ## CI [Here](https://github.com/actions/runner-images) are the different runners diff --git a/flake.nix b/flake.nix new file mode 100644 index 000000000..9bb236507 --- /dev/null +++ b/flake.nix @@ -0,0 +1,40 @@ +{ + description = "Meerkat X.500 Directory System Agent (DSA) and LDAP Server"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + }; + + outputs = { self, nixpkgs }: + let + systems = [ "x86_64-linux" ]; + forAllSystems = f: + nixpkgs.lib.genAttrs systems (system: + f { + inherit system; + pkgs = import nixpkgs { + inherit system; + overlays = [ self.overlays.default ]; + }; + } + ); + in { + packages = forAllSystems ({ pkgs, ... }: { + default = pkgs.meerkat-dsa; + meerkat-dsa = pkgs.meerkat-dsa; + }); + + apps = forAllSystems ({ pkgs, ... }: { + default = { + type = "app"; + program = "${pkgs.meerkat-dsa}/bin/meerkat-dsa"; + }; + }); + + overlays.default = import ./pkg/overlay.nix; + nixosModules.meerkat-dsa = import ./pkg/meerkat-dsa.nix; + checks = forAllSystems ({ pkgs, ... }: { + build = pkgs.meerkat-dsa; + }); + }; +} diff --git a/pkg/overlay.nix b/pkg/overlay.nix new file mode 100644 index 000000000..555a1dd54 --- /dev/null +++ b/pkg/overlay.nix @@ -0,0 +1,3 @@ +final: prev: { + meerkat-dsa = prev.callPackage ../pkg/default.nix {}; +} From fb579db6acb945c9eac450eecc4fcad1ad50f99b Mon Sep 17 00:00:00 2001 From: "Jonathan M. Wilbur" Date: Tue, 20 Jan 2026 04:13:15 -0500 Subject: [PATCH 5/9] pkg(meerkat): add man pages --- default.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/default.nix b/default.nix index 57cee38df..2b41da3f4 100644 --- a/default.nix +++ b/default.nix @@ -24,6 +24,8 @@ let ''; installPhase = '' cp -r dist/apps/meerkat $out + cp doc/man/man1/meerkat-dsa.1 $out + cp doc/man/man5/meerkat.env.5 $out ''; }; @@ -58,6 +60,10 @@ let EOF substituteInPlace $out/bin/meerkat --replace "@APP_DIR@" "$out" chmod +x $out/bin/meerkat + mkdir -p $out/share/man/man1 + mkdir -p $out/share/man/man5 + install -m 644 meerkat-dsa.1 $out/share/man/man1/meerkat-dsa.1 + install -m 644 meerkat.env.5 $out/share/man/man5/meerkat.env.5 ''; meta = with lib; { description = "Meerkat X.500 Directory System Agent (DSA) and LDAP Server"; From b834459b5d13573b75c1680a3c8f8737469f7f8f Mon Sep 17 00:00:00 2001 From: "Jonathan M. Wilbur" Date: Tue, 20 Jan 2026 04:19:03 -0500 Subject: [PATCH 6/9] pkg(meerkat): add proper Github source URL + hash --- default.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/default.nix b/default.nix index 2b41da3f4..cb58447ee 100644 --- a/default.nix +++ b/default.nix @@ -9,6 +9,12 @@ let pname = "meerkat-dsa-build"; version = "4.0.0"; src = ./.; + # src = fetchFromGitHub { + # owner = "Wildboar-Software"; + # repo = "directory"; + # rev = "v4.0.0"; + # hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; + # }; npmDepsHash = "sha256-V7td2VSpJD/3n+j9X8LhvSBMvqaE/o1gCSruQfNa/ME="; makeCacheWritable = true; npmFlags = [ "--no-audit" "--no-fund" "--no-save" "--ignore-scripts" "--verbose" "--legacy-peer-deps" ]; From e8a94ba328b5d8546dab3895b5fd45cfe1f080f2 Mon Sep 17 00:00:00 2001 From: "Jonathan M. Wilbur" Date: Sat, 7 Feb 2026 19:52:58 -0500 Subject: [PATCH 7/9] pkg(meerkat): fetch nix source from github --- default.nix | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/default.nix b/default.nix index cb58447ee..c227210e3 100644 --- a/default.nix +++ b/default.nix @@ -2,20 +2,20 @@ , stdenv , nodejs_24 , buildNpmPackage +, fetchFromGitHub }: let buildStage = buildNpmPackage { pname = "meerkat-dsa-build"; version = "4.0.0"; - src = ./.; - # src = fetchFromGitHub { - # owner = "Wildboar-Software"; - # repo = "directory"; - # rev = "v4.0.0"; - # hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; - # }; - npmDepsHash = "sha256-V7td2VSpJD/3n+j9X8LhvSBMvqaE/o1gCSruQfNa/ME="; + src = fetchFromGitHub { + owner = "Wildboar-Software"; + repo = "directory"; + rev = "v4.0.0-rc1"; + hash = "sha256-n26A/OtmRuMcnrihSl1b+YFKd23EIg2gsXKRC+AZsq8="; + }; + npmDepsHash = "sha256-eih0APtkKpYzJenDP+xNHkfmQ6ynbO57fXRemaFzEHo="; makeCacheWritable = true; npmFlags = [ "--no-audit" "--no-fund" "--no-save" "--ignore-scripts" "--verbose" "--legacy-peer-deps" ]; buildPhase = '' @@ -39,7 +39,7 @@ let pname = "meerkat-dsa"; version = "4.0.0"; src = buildStage; - npmDepsHash = "sha256-xHMniJesi213HX4zbR8hFE9XsdU+2QhWzWMQ6KC1Jvs="; + npmDepsHash = "sha256-uP0+7G8ujB9aG62za4+3t+X6EWaxoGFf/xZZhf/47jw="; npmFlags = [ "--no-audit" "--no-fund" "--no-save" "--ignore-scripts" "--verbose" ]; dontNpmBuild = true; installPhase = '' From 12d0dd7ae2ba6eb26e040a1a3cb263c5df4b98ee Mon Sep 17 00:00:00 2001 From: "Jonathan M. Wilbur" Date: Sun, 8 Feb 2026 13:29:49 -0500 Subject: [PATCH 8/9] pkg(meerkat): fix flake issues found in real NixOS deployment --- flake.nix | 2 +- default.nix => pkg/default.nix | 0 pkg/meerkat-dsa.nix | 2 -- pkg/overlay.nix | 2 +- 4 files changed, 2 insertions(+), 4 deletions(-) rename default.nix => pkg/default.nix (100%) diff --git a/flake.nix b/flake.nix index 9bb236507..c5c9881da 100644 --- a/flake.nix +++ b/flake.nix @@ -27,7 +27,7 @@ apps = forAllSystems ({ pkgs, ... }: { default = { type = "app"; - program = "${pkgs.meerkat-dsa}/bin/meerkat-dsa"; + program = "${pkgs.meerkat-dsa}/bin/meerkat"; }; }); diff --git a/default.nix b/pkg/default.nix similarity index 100% rename from default.nix rename to pkg/default.nix diff --git a/pkg/meerkat-dsa.nix b/pkg/meerkat-dsa.nix index c371bd753..665074418 100644 --- a/pkg/meerkat-dsa.nix +++ b/pkg/meerkat-dsa.nix @@ -19,8 +19,6 @@ in { config = lib.mkIf cfg.enable { - system.stateVersion = "26.05"; - users.users.meerkat = { isSystemUser = true; group = "meerkat"; diff --git a/pkg/overlay.nix b/pkg/overlay.nix index 555a1dd54..d687b788c 100644 --- a/pkg/overlay.nix +++ b/pkg/overlay.nix @@ -1,3 +1,3 @@ final: prev: { - meerkat-dsa = prev.callPackage ../pkg/default.nix {}; + meerkat-dsa = prev.callPackage ./default.nix {}; } From 581d9e66463d1f973e1c24e7542399e68bfa947e Mon Sep 17 00:00:00 2001 From: "Jonathan M. Wilbur" Date: Sun, 8 Feb 2026 13:34:07 -0500 Subject: [PATCH 9/9] doc: nix decision --- apps/meerkat-docs/docs/development.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/apps/meerkat-docs/docs/development.md b/apps/meerkat-docs/docs/development.md index b5ad71f3a..52e04cabc 100644 --- a/apps/meerkat-docs/docs/development.md +++ b/apps/meerkat-docs/docs/development.md @@ -159,6 +159,22 @@ error: attribute 'meerkat-dsa' in selection path 'config.systemd.services.meerka try removing `lib.mkIf cfg.enable` from `meerkat-dsa.nix`. +### UPDATE ON NIX + +Creating the Nix package wasn't too hard. Actually, it was one of the easiest +packagings I have done so far! But using a Flake on NixOS, wiring up the +Systemd service, etc. is from Hell. I had to write so much Nix "code" to still +have problem after problem. One remaining problem I have is `pkgs.meerkat-dsa` +not being defined. I can try to get this working with an overlay, but that is +not how this would really be used once a proper Nix package is published; doing +so would make this whole thing a lot simpler. + +So I have decided on this: I am going to release Meerkat DSA 4.0.0 without a +Nix package. Then, once I have the commit hash, I am going to submit a PR to +get a Nix package published for Meerkat DSA. Once that's out, then I will work +on the OS module, flake, whatever. If that doesn't work out, or if I never get +to it, too bad: stop being so damn difficult. + ## CI [Here](https://github.com/actions/runner-images) are the different runners