Compare commits
52 Commits
hermes-bac
...
fix/backup
| Author | SHA1 | Date | |
|---|---|---|---|
| 0f0c7824bc | |||
| f8502d0114 | |||
| 65543e3ce8 | |||
| 5de646d018 | |||
| 24761b58b2 | |||
| 9bf38f1077 | |||
| cbb016d409 | |||
| 7e7bb73b0d | |||
| ea5eac2234 | |||
| c9072e86da | |||
| 3a0fb70d26 | |||
| a0e0b6e78e | |||
| e03f09c247 | |||
| db2d540b3c | |||
| 3778069baf | |||
| 8ec9ffe6a9 | |||
| 16ec40b237 | |||
| 3ec8bab25b | |||
| 2a4856e447 | |||
| 01f8166529 | |||
| 84ce9de5ca | |||
| 14755f1ea6 | |||
| f51155823e | |||
| 73c12abec2 | |||
| a97c68fd81 | |||
| bf2500dce8 | |||
| f0fa8ac942 | |||
| 7899bf28f2 | |||
| 282b4bc229 | |||
| 905998466c | |||
| 6c34b92186 | |||
| 7b3a5802a5 | |||
| 1ab11b76d6 | |||
| 3ce550691c | |||
| 256979e6e5 | |||
| 095fa4c200 | |||
| c430427617 | |||
| eeb10db5ed | |||
| 60a0bcfdd6 | |||
| 7827638c5a | |||
| ceca908457 | |||
| 5aca97e057 | |||
| a51e095717 | |||
| 9ebbb1c0c6 | |||
| 7f11da1878 | |||
| 29cc20bb04 | |||
| 1617ac9149 | |||
| 24f15c98cd | |||
| bdd6d03739 | |||
| a0a6663793 | |||
| b66ffadb79 | |||
| db2bd1d157 |
Submodule assets/compose updated: dab158da0a...4729af5774
Submodule assets/dotfiles updated: f45387456b...3c06c3938c
30
flake.nix
30
flake.nix
@@ -26,18 +26,15 @@
|
||||
url = "github:gortium/nixos-raspberrypi/cm5-cross-v1";
|
||||
inputs.nixpkgs.follows = "nixpkgs-uconsole";
|
||||
};
|
||||
self.submodules = true;
|
||||
home-manager = {
|
||||
url = "github:nix-community/home-manager/release-25.11";
|
||||
inputs.nixpkgs.follows = "nixpkgs-uconsole";
|
||||
};
|
||||
dotfiles = {
|
||||
url = "git+https://code.lazyworkhorse.net/gortium/dotfiles.git";
|
||||
flake = false;
|
||||
};
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, agenix, agenix-rekey, lix
|
||||
, nixpkgs-uconsole, nixos-uconsole, nixos-raspberrypi, dotfiles
|
||||
, nixpkgs-uconsole, nixos-uconsole, nixos-raspberrypi
|
||||
, home-manager
|
||||
, ... }@inputs:
|
||||
let
|
||||
@@ -60,6 +57,7 @@
|
||||
inherit pkgs system agenix;
|
||||
};
|
||||
|
||||
|
||||
##############################################################################
|
||||
# CROSS-COMPILE WORKAROUNDS — packages that fail aarch64 cross-compile
|
||||
#
|
||||
@@ -190,6 +188,12 @@
|
||||
# perl-ldap fails cross-compile (Module::Install needs dynamic loading)
|
||||
# Strip it from john deps -- the perl scripts that need it are not critical
|
||||
john = prev.john.overrideAttrs (old: {
|
||||
nativeBuildInputs = (old.nativeBuildInputs or []) ++ [
|
||||
prev.buildPackages.python3 # python3 for opencl_generate_dynamic_loader.py
|
||||
];
|
||||
configureFlags = (old.configureFlags or []) ++ [
|
||||
"ac_cv_prog_PYTHON=${prev.buildPackages.python3}/bin/python3"
|
||||
];
|
||||
propagatedBuildInputs = builtins.filter
|
||||
(x: x?pname && x.pname != "perl-ldap")
|
||||
(old.propagatedBuildInputs or []);
|
||||
@@ -224,7 +228,7 @@
|
||||
nixos-raspberrypi.lib.inject-overlays
|
||||
nixos-raspberrypi.lib.inject-overlays-global
|
||||
nixos-uconsole.nixosModules.uconsole-cm5
|
||||
./modules/nixos/hardware/uconsole-cm5-aio-v2.nix
|
||||
./modules/nixos/hardware/uConsole-aio-v2.nix
|
||||
({ config, lib, pkgs, inputs, ... }: let
|
||||
lixCross = import inputs.nixpkgs-uconsole {
|
||||
localSystem = { system = "x86_64-linux"; };
|
||||
@@ -235,8 +239,8 @@
|
||||
inputs.home-manager.nixosModules.home-manager
|
||||
agenix.nixosModules.default
|
||||
agenix-rekey.nixosModules.default
|
||||
./hosts/uconsole-cm5/configuration.nix
|
||||
./hosts/uconsole-cm5/hardware-configuration.nix
|
||||
./hosts/uConsole/configuration.nix
|
||||
./hosts/uConsole/hardware-configuration.nix
|
||||
./modules/nixos/services/remote-builder.nix
|
||||
./modules/nixos/services/wireguard-client.nix
|
||||
./modules/nixos/services/clamav.nix
|
||||
@@ -258,6 +262,7 @@
|
||||
}
|
||||
inputs.home-manager.nixosModules.home-manager
|
||||
agenix.nixosModules.default
|
||||
agenix-rekey.nixosModules.default
|
||||
./hosts/lazyworkhorse/configuration.nix
|
||||
./hosts/lazyworkhorse/hardware-configuration.nix
|
||||
./modules/nixos/filesystem/hoardingcow-mount.nix
|
||||
@@ -266,9 +271,12 @@
|
||||
./modules/nixos/services/ollama_init_custom_models.nix
|
||||
./modules/nixos/services/open_code_server.nix
|
||||
./modules/nixos/services/clamav.nix
|
||||
./modules/nixos/services/wireguard-client.nix
|
||||
./modules/nixos/services/remote-builder.nix
|
||||
./modules/nixos/security/ai-worker-restricted.nix
|
||||
./users/gortium/gortium.nix
|
||||
./users/ai-worker/ai-worker.nix
|
||||
./users/builder.nix
|
||||
];
|
||||
};
|
||||
|
||||
@@ -281,6 +289,8 @@
|
||||
nixpkgs.hostPlatform = "aarch64-linux";
|
||||
nix.package = lix.packages."aarch64-linux".default;
|
||||
}
|
||||
inputs.home-manager.nixosModules.home-manager
|
||||
agenix.nixosModules.default
|
||||
./hosts/cyt-pi/configuration.nix
|
||||
./hosts/cyt-pi/hardware-configuration.nix
|
||||
./modules/nixos/services/remote-builder.nix
|
||||
@@ -289,7 +299,7 @@
|
||||
];
|
||||
};
|
||||
|
||||
uconsole-cm5 = nixpkgs-uconsole.lib.nixosSystem {
|
||||
uConsole = nixpkgs-uconsole.lib.nixosSystem {
|
||||
system = "aarch64-linux";
|
||||
specialArgs = {
|
||||
inherit self keys paths inputs;
|
||||
@@ -308,7 +318,7 @@
|
||||
devShells.${system}.default = devShell;
|
||||
|
||||
packages.${system} = {
|
||||
uconsole-cm5-image = (nixos-raspberrypi.lib.nixosSystem {
|
||||
uConsole-image = (nixos-raspberrypi.lib.nixosSystem {
|
||||
system = "aarch64-linux";
|
||||
specialArgs = {
|
||||
inherit self keys inputs;
|
||||
|
||||
@@ -21,14 +21,7 @@
|
||||
settings.PermitRootLogin = "prohibit-password";
|
||||
};
|
||||
|
||||
# User
|
||||
users.users.gortium = {
|
||||
isNormalUser = true;
|
||||
extraGroups = [ "wheel" "networkmanager" "kismet" ];
|
||||
openssh.authorizedKeys.keys = [
|
||||
# Populate with your public key
|
||||
];
|
||||
};
|
||||
# User (defined in users/gortium/gortium.nix)
|
||||
|
||||
# CYT Project Dependencies (Headless)
|
||||
environment.systemPackages = with pkgs; [
|
||||
@@ -77,6 +70,12 @@
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
# Age secrets
|
||||
age.secrets.gortium_password = {
|
||||
file = ../../secrets/gortium_password.age;
|
||||
};
|
||||
|
||||
# CYT Application Service
|
||||
systemd.services.cyt-app = {
|
||||
description = "Chasing Your Tail - Target Detector";
|
||||
|
||||
@@ -9,8 +9,12 @@
|
||||
hoardingcow-mount.enable = true;
|
||||
|
||||
# Flakesss
|
||||
nix.settings.experimental-features = [ "nix-command" "flakes" "flake-self-attrs" "ca-derivations" ];
|
||||
nix.settings.experimental-features = [ "nix-command" "flakes" "flake-self-attrs" ];
|
||||
nix.settings.trusted-users = [ "root" "gortium" ];
|
||||
nix.settings.extra-platforms = [ "aarch64-linux" ];
|
||||
|
||||
# QEMU binfmt for cross-building aarch64 NixOS targets
|
||||
boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
|
||||
|
||||
# Garbage collection
|
||||
nix.gc = {
|
||||
@@ -166,9 +170,8 @@
|
||||
settings = {
|
||||
PasswordAuthentication = false;
|
||||
KbdInteractiveAuthentication = false;
|
||||
# ============================================================
|
||||
# ClamAV antivirus — daemon, hourly updates, daily scan, on-access
|
||||
# ============================================================
|
||||
};
|
||||
hostKeys = [
|
||||
{
|
||||
path = "/etc/ssh/ssh_host_ed25519_key";
|
||||
type = "ed25519";
|
||||
@@ -248,7 +251,9 @@
|
||||
|
||||
# Private host ssh key managed by agenix
|
||||
age = {
|
||||
identityPaths = paths.identities;
|
||||
identityPaths = paths.identities ++ [
|
||||
"/etc/ssh/ssh_host_ed25519_key"
|
||||
];
|
||||
secrets = {
|
||||
containers_env = {
|
||||
file = ../../secrets/containers.env.age;
|
||||
@@ -271,13 +276,6 @@
|
||||
mode = "0600";
|
||||
path = "/home/ai-worker/.ssh/ai_ssh_key";
|
||||
};
|
||||
openclaw_gateway_token = {
|
||||
file = ../../secrets/openclaw_gateway_token.age;
|
||||
owner = "root";
|
||||
group = "ai-worker";
|
||||
mode = "0440";
|
||||
path = "/run/secrets/openclaw_gateway_token";
|
||||
};
|
||||
wireguard_private_key = {
|
||||
file = ../../secrets/wireguard_private_key.age;
|
||||
owner = "root";
|
||||
@@ -291,20 +289,24 @@
|
||||
group = "root";
|
||||
mode = "0400";
|
||||
path = "/run/secrets/wireguard_preshared_key";
|
||||
};
|
||||
builder_key = {
|
||||
file = ../../secrets/builder_key.age;
|
||||
owner = "root";
|
||||
group = "root";
|
||||
mode = "0600";
|
||||
path = "/etc/ssh/builder_key";
|
||||
};
|
||||
gortium_password = {
|
||||
file = ../../secrets/gortium_password.age;
|
||||
owner = "gortium";
|
||||
group = "gortium";
|
||||
mode = "0400";
|
||||
path = "/run/secrets/gortium_password";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# OpenClaw Node service (host-side execution for Docker gateway)
|
||||
services.openclaw-node = {
|
||||
enable = true;
|
||||
user = "ai-worker";
|
||||
gatewayHost = "127.0.0.1";
|
||||
gatewayPort = 18789;
|
||||
gatewayTokenFile = "/run/secrets/openclaw_gateway_token";
|
||||
displayName = "lazyworkhorse-host";
|
||||
};
|
||||
|
||||
# Public host ssh key (kept in sync with the private one)
|
||||
environment.etc."ssh/ssh_host_ed25519_key.pub".text =
|
||||
"${keys.hosts.lazyworkhorse.main}";
|
||||
@@ -567,5 +569,29 @@
|
||||
# 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 = config.age.secrets.builder_key.path;
|
||||
systems = [ "aarch64-linux" ];
|
||||
maxJobs = 4;
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
|
||||
# agenix-rekey — automatic re-encryption for each target host
|
||||
age.rekey = {
|
||||
masterIdentities = [
|
||||
"/home/gortium/.ssh/gortium_ssh_key"
|
||||
];
|
||||
};
|
||||
}
|
||||
|
||||
@@ -26,6 +26,14 @@
|
||||
networking.networkmanager.enable = true;
|
||||
# Firmware
|
||||
hardware.enableRedistributableFirmware = true;
|
||||
# RealtimeKit for PipeWire audio
|
||||
security.rtkit.enable = true;
|
||||
services.pipewire = {
|
||||
enable = true;
|
||||
alsa.enable = true;
|
||||
alsa.support32Bit = true;
|
||||
pulse.enable = true;
|
||||
};
|
||||
# Hyprland Wayland compositor (manual start — no SDDM)
|
||||
programs.hyprland = {
|
||||
enable = true;
|
||||
@@ -98,18 +106,18 @@
|
||||
htop
|
||||
tmux
|
||||
# ===== HAM Radio =====
|
||||
# wsjtx — removed for aarch64 bootstrap (qtbase/Qt5 cross-compile linker fails)
|
||||
# fldigi — removed for aarch64 bootstrap (qtbase/Qt5 cross-compile linker fails)
|
||||
# wsjtx # removed for bootstrap - now native (native-only, needs remote build)
|
||||
# fldigi # removed for bootstrap - now native (native-only, needs remote build)
|
||||
pat # Winlink client
|
||||
direwolf # AX.25 packet modem
|
||||
# chirp # Radio programming tool
|
||||
# chirp # Radio programming tool - now native (native-only, needs remote build)
|
||||
hamlib # Ham radio control libraries
|
||||
# trustedqsl # Logbook of the World (LoTW)
|
||||
# trustedqsl # Logbook of the World (LoTW) - now native (native-only, needs remote build)
|
||||
# ===== SDR / RF =====
|
||||
# sdrpp — removed for aarch64 cross-compile bootstrap (glfw/wxPython fails)
|
||||
# gqrx — removed for aarch64 cross-compile bootstrap (Qt5 cascade fails)
|
||||
# sdrpp # removed for bootstrap - now native (native-only, needs remote build)
|
||||
# gqrx # removed for bootstrap - now native (native-only, needs remote build)
|
||||
rtl-sdr # RTL-SDR drivers & utilities
|
||||
# inspectrum # removed for aarch64 bootstrap (Qt5 cross-compile cascade fails)
|
||||
# inspectrum # removed for bootstrap - now native (native-only, needs remote build)
|
||||
soapysdr-with-plugins # SoapySDR + hardware support plugins
|
||||
# ===== Mesh / LoRa =====
|
||||
reticulumStack # Reticulum Network Stack
|
||||
@@ -121,12 +129,12 @@
|
||||
kismet # Wi-Fi monitor / IDS
|
||||
bettercap # MITM/network attack framework
|
||||
wireshark-cli # Packet analyzer
|
||||
# john # John the Ripper
|
||||
john # John the Ripper - now native
|
||||
sqlmap # SQL injection tool
|
||||
# ===== GPS / Maps =====
|
||||
# foxtrotgps — removed for aarch64 cross-compile bootstrap (GTK2 fails)
|
||||
# viking — removed for aarch64 cross-compile bootstrap (GTK3 fails)
|
||||
# gpsbabel # GPS data conversion
|
||||
#foxtrotgps # removed for bootstrap - now native (native-only, needs remote build)
|
||||
#viking # removed for bootstrap - now native (native-only, needs remote build)
|
||||
#gpsbabel # GPS data conversion - now native (native-only, needs remote build)
|
||||
];
|
||||
# ============================================================
|
||||
# Reticulum Service (rnsd)
|
||||
@@ -184,6 +192,32 @@
|
||||
networking.firewall.allowedTCPPorts = [ 22 ];
|
||||
networking.firewall.allowedUDPPorts = [ ];
|
||||
# ============================================================
|
||||
# Remote builder — dispatches x86_64-linux builds to lazyworkhorse
|
||||
# ============================================================
|
||||
services.remoteBuilder = {
|
||||
enable = true;
|
||||
machines = [
|
||||
{
|
||||
hostName = "lazyworkhorse.net";
|
||||
port = 2424;
|
||||
sshUser = "builder";
|
||||
sshKey = config.age.secrets.builder_key.path;
|
||||
systems = [ "x86_64-linux" ];
|
||||
maxJobs = 36;
|
||||
supportedFeatures = [ "benchmark" "big-parallel" "nixos-test" ];
|
||||
}
|
||||
];
|
||||
};
|
||||
# Age secret for builder SSH key (remote building)
|
||||
age.secrets.builder_key = {
|
||||
file = ../../secrets/builder_key.age;
|
||||
};
|
||||
|
||||
# ============================================================
|
||||
age.identityPaths = [
|
||||
"/etc/ssh/ssh_host_ed25519_key"
|
||||
];
|
||||
|
||||
# agenix-rekey — automatic secret re-encryption at deploy time
|
||||
# ============================================================
|
||||
age.rekey = {
|
||||
@@ -194,7 +228,7 @@
|
||||
# uConsole SSH host pubkey — for automatic rekey at build time
|
||||
# Once uConsole is deployed, replace with actual pubkey from:
|
||||
# ssh-keyscan uConsole.local | ssh-to-age
|
||||
hostPubkey = "age1qyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqs3290gq"; # dummy — replace after bootstrap
|
||||
hostPubkey = "age1un8td4jzkhg5fm4jja7z3aznskc8hlcm8ky0j2f70tv74rulwgaqtpemn2"; # uConsole CM5 SSH host key
|
||||
};
|
||||
|
||||
# Pipewire overlay: drop libcamera (fixes aarch64 cross-compile — rpi-pisp blocks)
|
||||
11
lib/keys.nix
11
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 = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIByG79NM/rk13q3MTow9Ezb8pe3RWoQ76Mv8atASp3Ri";
|
||||
};
|
||||
};
|
||||
|
||||
hosts = {
|
||||
@@ -18,5 +25,9 @@
|
||||
gitea = "";
|
||||
bootstrap = "age1r796v2uldtspawyh863pks74sd2pwcan8j4e4pjzsvkmr3vjja9qpz5ste";
|
||||
};
|
||||
uConsole = {
|
||||
main = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICasvsmaHuNVaWnjwuBfoMXyY/6PIqGL8yxstPBb46u4";
|
||||
bootstrap = "age1un8td4jzkhg5fm4jja7z3aznskc8hlcm8ky0j2f70tv74rulwgaqtpemn2";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ let
|
||||
};
|
||||
|
||||
dontUnpack = true;
|
||||
buildInputs = [ pkgs.python3 ];
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin $out/share/aiov2_ctl/img
|
||||
@@ -1,64 +0,0 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.services.openclaw-node;
|
||||
openclawPkg = pkgs.openclaw;
|
||||
in {
|
||||
options.services.openclaw-node = {
|
||||
enable = lib.mkEnableOption "OpenClaw Node service";
|
||||
|
||||
user = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "ai-worker";
|
||||
description = "User to run the OpenClaw headless node as.";
|
||||
};
|
||||
|
||||
gatewayHost = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "127.0.0.1";
|
||||
description = "Gateway host (IP or hostname).";
|
||||
};
|
||||
|
||||
gatewayPort = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 18789;
|
||||
description = "Gateway WebSocket port.";
|
||||
};
|
||||
|
||||
gatewayTokenFile = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = "Path to file containing the gateway auth token.";
|
||||
};
|
||||
|
||||
displayName = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "lazyworkhorse-host";
|
||||
description = "Display name for this node (shown in pairing).";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
systemd.services.openclaw-node = {
|
||||
description = "OpenClaw Headless Node Service";
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "exec";
|
||||
User = cfg.user;
|
||||
Group = cfg.user;
|
||||
WorkingDirectory = "/home/${cfg.user}";
|
||||
ExecStart = ''
|
||||
${pkgs.bash}/bin/bash -c 'export OPENCLAW_GATEWAY_TOKEN=$(cat ${cfg.gatewayTokenFile}) && exec ${openclawPkg}/bin/openclaw node run --host ${cfg.gatewayHost} --port ${toString cfg.gatewayPort} --display-name "${cfg.displayName}"'
|
||||
'';
|
||||
Restart = "always";
|
||||
RestartSec = 5;
|
||||
};
|
||||
|
||||
environment = {
|
||||
NODE_ENV = "production";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -3,69 +3,71 @@ let
|
||||
cfg = config.services.remoteBuilder;
|
||||
in {
|
||||
options.services.remoteBuilder = {
|
||||
enable = lib.mkEnableOption "remote Nix build machine (lazyworkhorse server)";
|
||||
enable = lib.mkEnableOption "remote Nix build machine";
|
||||
|
||||
buildMachine = {
|
||||
host = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "lazyworkhorse.net";
|
||||
description = "Hostname or IP of the remote build machine.";
|
||||
};
|
||||
sshUser = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "ai-worker";
|
||||
description = "SSH user on the remote build machine.";
|
||||
};
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 2424;
|
||||
description = "SSH port — added via ~root/.ssh/config since nix.buildMachines has no sshPort option.";
|
||||
};
|
||||
systems = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ "aarch64-linux" "x86_64-linux" ];
|
||||
description = "System types the remote builder can build for.";
|
||||
};
|
||||
maxJobs = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 16;
|
||||
description = "Max parallel jobs on the remote builder.";
|
||||
};
|
||||
supportedFeatures = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ "big-parallel" "nixos-test" "benchmark" ];
|
||||
description = "Features the remote builder supports.";
|
||||
};
|
||||
};
|
||||
|
||||
fallbackLocal = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "Fall back to local build when remote builder is unreachable.";
|
||||
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 = [{
|
||||
hostName = cfg.buildMachine.host;
|
||||
sshUser = cfg.buildMachine.sshUser;
|
||||
systems = cfg.buildMachine.systems;
|
||||
maxJobs = cfg.buildMachine.maxJobs;
|
||||
supportedFeatures = cfg.buildMachine.supportedFeatures;
|
||||
}];
|
||||
nix.buildMachines = map (m: {
|
||||
hostName = m.hostName;
|
||||
sshUser = m.sshUser;
|
||||
sshKey = m.sshKey;
|
||||
systems = m.systems;
|
||||
maxJobs = m.maxJobs;
|
||||
supportedFeatures = m.supportedFeatures;
|
||||
}) cfg.machines;
|
||||
|
||||
nix.extraOptions = lib.optionalString cfg.fallbackLocal ''
|
||||
builders-use-substitutes = true
|
||||
fallback = true
|
||||
'';
|
||||
|
||||
# SSH config for the remote builder (since nix.buildMachines has no port option)
|
||||
programs.ssh.extraConfig = ''
|
||||
Host ${cfg.buildMachine.host}
|
||||
HostName ${cfg.buildMachine.host}
|
||||
Port ${toString cfg.buildMachine.port}
|
||||
User ${cfg.buildMachine.sshUser}
|
||||
'';
|
||||
# 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);
|
||||
};
|
||||
}
|
||||
|
||||
BIN
secrets/builder_key.age
Normal file
BIN
secrets/builder_key.age
Normal file
Binary file not shown.
Binary file not shown.
@@ -1,11 +0,0 @@
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IEdoTUQ4QSBCWEpO
|
||||
cG9yNnFpcHFqTkNzTngxU1MxN0NYK0hrZFhUTjVORWFrK3JNd2tZCmtMTGpwQk1E
|
||||
WlUwL3N6SGRWblpnNEkrWkkyU2hQMkRIK0M3R0pOVEREV3MKLT4gY2osLWdyZWFz
|
||||
ZSBacSozVVQgUCAxRS1OQSAuKXxDPCoKbStWNW1BZjBZQzNDaTlDbU5EZkxsRWxM
|
||||
cXJ3dDU1RDNpOXRlV0tzdEp2NUo3S1lhRG5Md0RHTGlJdkFSYmt5YQo4R1hiQWRG
|
||||
V2VxekJKZwotLS0geG1XSi9VbkhXZHQzcEFVS3hKNzVueXFLa2xnZTc3Q2tJTVZ5
|
||||
eXJabWk5Ywp6bJCP3s0xxzjE+eTR+cv7ZUnkoliT/n7uIprq1BTn/LIRLkUTUqs3
|
||||
NiDwrXcoq4/QKd0Dt+8ap3vFAuusjGxRlnYMaRrZie2AGtTV8U7Q7durm9o2K+/4
|
||||
QzRQ/MtumIQm
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
@@ -12,5 +12,7 @@ in
|
||||
"home_wifi.age".publicKeys = authorizedKeys;
|
||||
"lazyworkhorse_host_ssh_key.age".publicKeys = authorizedKeys;
|
||||
"n8n_ssh_key.age".publicKeys = authorizedKeys;
|
||||
"openclaw_gateway_token.age".publicKeys = authorizedKeys;
|
||||
"builder_key.age".publicKeys = authorizedKeys ++ [
|
||||
keys.hosts.uConsole.bootstrap
|
||||
];
|
||||
}
|
||||
|
||||
13
users/builder.nix
Normal file
13
users/builder.nix
Normal file
@@ -0,0 +1,13 @@
|
||||
{ config, lib, pkgs, keys, ... }: {
|
||||
users.users.builder = {
|
||||
isSystemUser = true;
|
||||
group = "builder";
|
||||
home = "/var/empty";
|
||||
createHome = false;
|
||||
shell = "${pkgs.shadow}/bin/nologin";
|
||||
openssh.authorizedKeys.keys = with keys; [
|
||||
users.builder.main
|
||||
];
|
||||
};
|
||||
users.groups.builder = {};
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
{ pkgs, inputs, config, keys, ... }: {
|
||||
home-manager.extraSpecialArgs = { inherit (config.networking) hostName; dotfiles = inputs.dotfiles.outPath # flake input (not submodule); };
|
||||
home-manager.extraSpecialArgs = {
|
||||
inherit (config.networking) hostName;
|
||||
};
|
||||
home-manager.users.gortium = import ./home.nix;
|
||||
users.users.gortium = {
|
||||
isNormalUser = true;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
let
|
||||
isUconsole = hostName == "uConsole";
|
||||
dotfiles = ../../assets/dotfiles;
|
||||
in {
|
||||
home.username = "gortium";
|
||||
home.homeDirectory = "/home/gortium";
|
||||
@@ -33,6 +34,9 @@ in {
|
||||
".config/wofi/config".source = "${dotfiles}/wofi/.config/wofi/config";
|
||||
|
||||
# yazi
|
||||
|
||||
# wallpapers
|
||||
".config/wallpapers".source = "${dotfiles}/wallpapers/.config/wallpapers";
|
||||
".config/yazi/yazi.toml".source = "${dotfiles}/yazi/.config/yazi/yazi.toml";
|
||||
|
||||
# hyprland — common config
|
||||
@@ -43,22 +47,45 @@ in {
|
||||
".config/hypr/mocha.conf".source = "${dotfiles}/hypr/.config/hypr/mocha.conf";
|
||||
|
||||
# hyprland — host-specific monitor config
|
||||
".config/hypr/host/monitors.conf".source =
|
||||
".config/hypr/hosts/monitors.conf".source =
|
||||
if isUconsole
|
||||
then "${dotfiles}/hypr/.config/hypr/hosts/uconsole.conf"
|
||||
else "${dotfiles}/hypr/.config/hypr/hosts/laptop.conf";
|
||||
};
|
||||
|
||||
programs.bash.enable = true;
|
||||
programs.zsh = {
|
||||
enable = true;
|
||||
initExtra = builtins.readFile "${dotfiles}/zsh/.zshrc";
|
||||
};
|
||||
|
||||
home.packages = with pkgs; [
|
||||
git zsh tmux starship
|
||||
neovim kitty
|
||||
btop yazi ripgrep fd fzf
|
||||
] ++ lib.optionals (!isUconsole) [
|
||||
waybar wofi swww hyprshot
|
||||
] ++ lib.optionals isUconsole [
|
||||
brightnessctl
|
||||
htop unzip wget jq
|
||||
hyprland hyprlock hypridle hyprpaper
|
||||
waybar wofi dunst
|
||||
libnotify mako
|
||||
swaynotificationcenter
|
||||
swww
|
||||
emacs
|
||||
udiskie
|
||||
hyprshade
|
||||
networkmanagerapplet
|
||||
pavucontrol
|
||||
];
|
||||
|
||||
programs.zsh.enable = true;
|
||||
programs.starship.enable = true;
|
||||
xdg.userDirs = {
|
||||
enable = true;
|
||||
createDirectories = true;
|
||||
desktop = "$HOME/desktop";
|
||||
documents = "$HOME/documents";
|
||||
download = "$HOME/downloads";
|
||||
music = "$HOME/music";
|
||||
pictures = "$HOME/pictures";
|
||||
publicShare = "$HOME/public";
|
||||
templates = "$HOME/templates";
|
||||
videos = "$HOME/videos";
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user