From db2d540b3c78e60b3ac0398e78e164f6088751c3 Mon Sep 17 00:00:00 2001 From: Hermes Date: Sat, 20 Jun 2026 20:59:38 -0400 Subject: [PATCH] feat: server-side remote builder config (lazyworkhorse dispatches aarch64 to uConsole) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Server only — uConsole-side config will be added in uconsole-cm5-incremental branch. Includes reusable module, builder system user, and SSH key placeholder. --- assets/dotfiles | 1 + flake.nix | 2 + hosts/lazyworkhorse/configuration.nix | 18 ++++++ lib/keys.nix | 7 +++ modules/nixos/services/remote-builder.nix | 74 +++++++++++++++++++++++ users/builder.nix | 13 ++++ 6 files changed, 115 insertions(+) create mode 160000 assets/dotfiles create mode 100644 modules/nixos/services/remote-builder.nix create mode 100644 users/builder.nix diff --git a/assets/dotfiles b/assets/dotfiles new file mode 160000 index 0000000..504daea --- /dev/null +++ b/assets/dotfiles @@ -0,0 +1 @@ +Subproject commit 504daea61eadfbc84853b83508cc7a9b9ddddd48 diff --git a/flake.nix b/flake.nix index ea2a6b6..250c46b 100644 --- a/flake.nix +++ b/flake.nix @@ -69,9 +69,11 @@ ./modules/nixos/services/open_code_server.nix ./modules/nixos/services/ollama_init_custom_models.nix ./modules/nixos/services/openclaw_node.nix + ./modules/nixos/services/remote-builder.nix ./modules/nixos/security/ai-worker-restricted.nix ./users/gortium.nix ./users/ai-worker.nix + ./users/builder.nix ]; }; diff --git a/hosts/lazyworkhorse/configuration.nix b/hosts/lazyworkhorse/configuration.nix index 6f02a2b..9167552 100644 --- a/hosts/lazyworkhorse/configuration.nix +++ b/hosts/lazyworkhorse/configuration.nix @@ -573,5 +573,23 @@ # For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion . system.stateVersion = "25.05"; # Did you read the comment? + + # ============================================================ + # Remote builder — dispatches aarch64-linux builds to uConsole + # ============================================================ + services.remoteBuilder = { + enable = true; + machines = [ + { + hostName = "192.168.1.120"; + port = 22; + sshUser = "builder"; + sshKey = "/etc/ssh/builder_key"; + systems = [ "aarch64-linux" ]; + maxJobs = 4; + } + ]; + }; + } diff --git a/lib/keys.nix b/lib/keys.nix index ab287d6..39a646a 100644 --- a/lib/keys.nix +++ b/lib/keys.nix @@ -9,6 +9,13 @@ ai-worker = { main = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAXeGtPPcsP2IYRQNvII41NVWhJsarEk8c4qxs/a5sXf"; }; + + builder = { + # Same key on both hosts for bidirectional remote building. + # Generate with: ssh-keygen -t ed25519 -f /etc/ssh/builder_key -N "" + # Replace the placeholder below with the public key (builder_key.pub). + main = "PLACEHOLDER_ADD_BUILDER_PUBKEY_HERE"; + }; }; hosts = { diff --git a/modules/nixos/services/remote-builder.nix b/modules/nixos/services/remote-builder.nix new file mode 100644 index 0000000..8162303 --- /dev/null +++ b/modules/nixos/services/remote-builder.nix @@ -0,0 +1,74 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.services.remoteBuilder; +in { + options.services.remoteBuilder = { + enable = lib.mkEnableOption "remote Nix build machine"; + + machines = lib.mkOption { + type = lib.types.listOf (lib.types.submodule { + options = { + hostName = lib.mkOption { + type = lib.types.str; + description = "Hostname or IP of the remote build machine."; + }; + port = lib.mkOption { + type = lib.types.port; + default = 22; + description = "SSH port."; + }; + sshUser = lib.mkOption { + type = lib.types.str; + default = "builder"; + description = "SSH user on the remote build machine."; + }; + sshKey = lib.mkOption { + type = lib.types.str; + description = "Path to SSH private key for the builder."; + }; + systems = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ "aarch64-linux" ]; + description = "System types the remote builder can build for."; + }; + maxJobs = lib.mkOption { + type = lib.types.int; + default = 4; + description = "Max parallel jobs on the remote builder."; + }; + supportedFeatures = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ "benchmark" "big-parallel" "nixos-test" ]; + description = "Features the remote builder supports."; + }; + }; + }); + default = []; + description = "List of remote Nix build machines."; + }; + }; + + config = lib.mkIf cfg.enable { + nix.distributedBuilds = true; + nix.buildMachines = map (m: { + hostName = m.hostName; + sshUser = m.sshUser; + sshKey = m.sshKey; + systems = m.systems; + maxJobs = m.maxJobs; + supportedFeatures = m.supportedFeatures; + }) cfg.machines; + + # SSH config for port + key (nix.buildMachines has no port option) + programs.ssh.extraConfig = lib.concatStringsSep "\n" (map (m: '' + Host ${m.hostName} + HostName ${m.hostName} + Port ${toString m.port} + User ${m.sshUser} + IdentityFile ${m.sshKey} + StrictHostKeyChecking no + UserKnownHostsFile /dev/null + '') cfg.machines); + }; +} diff --git a/users/builder.nix b/users/builder.nix new file mode 100644 index 0000000..3c23987 --- /dev/null +++ b/users/builder.nix @@ -0,0 +1,13 @@ +{ config, lib, pkgs, keys, ... }: { + users.users.builder = { + isSystemUser = true; + group = "builder"; + home = "/var/empty"; + createHome = false; + shell = pkgs.nologin; + openssh.authorizedKeys.keys = with keys; [ + users.builder.main + ]; + }; + users.groups.builder = {}; +}