From 6567382bd53d48a3d5a589863f7ab172be8cb8d8 Mon Sep 17 00:00:00 2001 From: padreug Date: Fri, 9 Jan 2026 18:52:53 +0100 Subject: [PATCH] lamassu: clone and build from git source on target MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add lamassu-build systemd service that clones the lamassu-server repo directly on the target and builds it. This makes the module self-contained with no external deployment of source code required. New options: - source.url: Git repository URL (default: git.atitlan.io/aiolabs/lamassu-server) - source.ref: Git ref to checkout (default: main) The build service: - Clones repo on first run, fetches updates on subsequent runs - Only rebuilds when source changes or build artifacts are missing - Source is stored in ${dataDir}/source 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- modules/lamassu-lnbits.nix | 116 ++++++++++++++++++++++++++++++++++--- 1 file changed, 107 insertions(+), 9 deletions(-) diff --git a/modules/lamassu-lnbits.nix b/modules/lamassu-lnbits.nix index 7bb6b4e..4c92176 100644 --- a/modules/lamassu-lnbits.nix +++ b/modules/lamassu-lnbits.nix @@ -7,8 +7,8 @@ let nbLib = config.nix-bitcoin.lib; secretsDir = config.nix-bitcoin.secretsDir; - # Path to the deployed lamassu-server (krops puts it in /var/src) - lamassuServerPath = "/var/src/lamassu-server-built"; + # Source directory for lamassu-server (cloned from git) + lamassuSourceDir = "${cfg.dataDir}/source"; # Basic hardening settings (simplified from nix-bitcoin) defaultHardening = { @@ -67,10 +67,24 @@ in package = mkOption { type = types.path; - default = lamassuServerPath; + default = lamassuSourceDir; description = "The path to the lamassu-server source directory"; }; + source = { + url = mkOption { + type = types.str; + default = "https://git.atitlan.io/aiolabs/lamassu-server"; + description = "Git repository URL for lamassu-server source"; + }; + + ref = mkOption { + type = types.str; + default = "main"; + description = "Git ref (branch, tag, or commit) to checkout"; + }; + }; + logLevel = mkOption { type = types.enum [ "error" "warn" "info" "verbose" "debug" "silly" ]; default = "info"; @@ -243,8 +257,7 @@ in "d '${cfg.dataDir}/photos/idcards' 0770 ${cfg.user} ${cfg.group} - -" "d '${cfg.dataDir}/photos/frontcamera' 0770 ${cfg.user} ${cfg.group} - -" "d '${cfg.dataDir}/operator' 0770 ${cfg.user} ${cfg.group} - -" - # Ensure lamassu-server user can read/write to the source directory - "Z '${cfg.package}' 0755 ${cfg.user} ${cfg.group} - -" + # Source directory is created by lamassu-build service via git clone ]; # Service to set PostgreSQL password from nix-bitcoin secrets @@ -275,12 +288,97 @@ in ''; }; + # Build service - clones source and runs pnpm install/build on target + systemd.services.lamassu-build = { + description = "Clone and Build Lamassu Server"; + wantedBy = [ "multi-user.target" ]; + after = [ "network-online.target" ]; + wants = [ "network-online.target" ]; + + path = with pkgs; [ nodejs_22 nodePackages.pnpm python3 git coreutils gnused ]; + + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + User = cfg.user; + Group = cfg.group; + # Build can take a while, especially on first run + TimeoutStartSec = "30min"; + # Allow write access to data directory for cloning and building + ReadWritePaths = [ cfg.dataDir ]; + }; + + script = '' + set -euo pipefail + + SOURCE_DIR="${cfg.package}" + GIT_URL="${cfg.source.url}" + GIT_REF="${cfg.source.ref}" + + echo "==> Source: $GIT_URL (ref: $GIT_REF)" + echo "==> Target: $SOURCE_DIR" + + # Clone or update the repository + if [ ! -d "$SOURCE_DIR/.git" ]; then + echo "==> Cloning repository..." + git clone "$GIT_URL" "$SOURCE_DIR" + cd "$SOURCE_DIR" + git checkout "$GIT_REF" + NEEDS_BUILD=1 + else + cd "$SOURCE_DIR" + echo "==> Fetching updates..." + git fetch origin + + # Check if we need to update + LOCAL_REF=$(git rev-parse HEAD) + REMOTE_REF=$(git rev-parse "origin/$GIT_REF" 2>/dev/null || git rev-parse "$GIT_REF") + + if [ "$LOCAL_REF" != "$REMOTE_REF" ]; then + echo "==> Updating to $GIT_REF..." + git checkout "$GIT_REF" + git pull origin "$GIT_REF" 2>/dev/null || true + NEEDS_BUILD=1 + else + echo "==> Already at latest commit: $LOCAL_REF" + NEEDS_BUILD=0 + fi + fi + + # Check if build artifacts exist + if [ ! -d "node_modules" ] || [ ! -d "packages/admin-ui/build" ] || [ ! -L "packages/server/public" ]; then + echo "==> Build artifacts missing, build needed" + NEEDS_BUILD=1 + fi + + if [ "$NEEDS_BUILD" = "0" ]; then + echo "==> Everything up to date, skipping build" + exit 0 + fi + + echo "==> Installing dependencies with pnpm..." + pnpm install + + echo "==> Building project..." + pnpm build + + echo "==> Linking admin UI static files..." + cd packages/server + if [ -L public ]; then + rm public + fi + ln -s ../admin-ui/build public + + echo "==> Build complete!" + ''; + }; + # Main lamassu server service systemd.services.lamassu-server = { description = "Lamassu Bitcoin ATM Server"; wantedBy = [ "multi-user.target" ]; - after = [ "network.target" "postgresql.service" "lamassu-postgres-setup.service" "nix-bitcoin-secrets.target" ]; - wants = [ "postgresql.service" "lamassu-postgres-setup.service" ]; + after = [ "network.target" "postgresql.service" "lamassu-postgres-setup.service" "lamassu-build.service" "nix-bitcoin-secrets.target" ]; + wants = [ "postgresql.service" "lamassu-postgres-setup.service" "lamassu-build.service" ]; environment = { NODE_ENV = "production"; @@ -381,8 +479,8 @@ in systemd.services.lamassu-admin-server = { description = "Lamassu Admin Server"; wantedBy = [ "multi-user.target" ]; - after = [ "network.target" "lamassu-server.service" ]; - wants = [ "lamassu-server.service" ]; + after = [ "network.target" "lamassu-server.service" "lamassu-build.service" ]; + wants = [ "lamassu-server.service" "lamassu-build.service" ]; environment = { NODE_ENV = "production";