From 0ca7a746537c9a6f7f4df0142de0c5e600d8a97e Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Tue, 19 Aug 2025 17:32:38 -0400 Subject: [PATCH 01/30] WIP on home manager --- .gitmodules | 3 + flake.lock | 21 +++++++ flake.nix | 9 ++- modules/nixos/services/default.nix | 10 ++-- modules/nixos/services/dotfiles.nix | 69 ++++++++++++++++++++++ users/{gortium.nix => gortium/default.nix} | 1 + users/gortium/home.nix | 12 ++++ 7 files changed, 118 insertions(+), 7 deletions(-) create mode 100644 modules/nixos/services/dotfiles.nix rename users/{gortium.nix => gortium/default.nix} (91%) create mode 100644 users/gortium/home.nix diff --git a/.gitmodules b/.gitmodules index bd90853..684b242 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "assets/compose"] path = assets/compose url = ssh://git@code.lazyworkhorse.net:2222/gortium/compose.git +[submodule "assets/dotfiles"] + path = assets/dotfiles + url = ssh://git@code.lazyworkhorse.net:2222/gortium/dotfiles.git diff --git a/flake.lock b/flake.lock index a5b95ac..71d5abd 100644 --- a/flake.lock +++ b/flake.lock @@ -44,6 +44,26 @@ "type": "github" } }, + "home-manager_2": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1755625756, + "narHash": "sha256-t57ayMEdV9g1aCfHzoQjHj1Fh3LDeyblceADm2hsLHM=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "dd026d86420781e84d0732f2fa28e1c051117b59", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1753939845, @@ -63,6 +83,7 @@ "root": { "inputs": { "agenix": "agenix", + "home-manager": "home-manager_2", "nixpkgs": "nixpkgs" } }, diff --git a/flake.nix b/flake.nix index af799ae..6716350 100644 --- a/flake.nix +++ b/flake.nix @@ -8,10 +8,14 @@ inputs.darwin.follows = ""; inputs.nixpkgs.follows = "nixpkgs"; }; + home-manager = { + url = "github:nix-community/home-manager"; + inputs.nixpkgs.follows = "nixpkgs"; + }; self.submodules = true; }; - outputs = { self, nixpkgs, agenix, ... }@inputs: + outputs = { self, nixpkgs, agenix, home-manager, ... }@inputs: let system = "x86_64-linux"; keys = import ./lib/keys.nix; @@ -36,10 +40,11 @@ modules = [ { nixpkgs.overlays = overlays; } agenix.nixosModules.default + home-manager.nixosModules.default ./hosts/lazyworkhorse/configuration.nix ./hosts/lazyworkhorse/hardware-configuration.nix ./modules/default.nix - ./users/gortium.nix + ./users/gortium ]; }; }; diff --git a/modules/nixos/services/default.nix b/modules/nixos/services/default.nix index 960abf0..c0d569a 100644 --- a/modules/nixos/services/default.nix +++ b/modules/nixos/services/default.nix @@ -1,6 +1,6 @@ -{ pkgs, lib, config, ... }: { - imports = - [ - ./systemd - ]; +{ + imports = [ + ./dotfiles.nix + ./systemd + ]; } diff --git a/modules/nixos/services/dotfiles.nix b/modules/nixos/services/dotfiles.nix new file mode 100644 index 0000000..b05fbe0 --- /dev/null +++ b/modules/nixos/services/dotfiles.nix @@ -0,0 +1,69 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.dotfiles; + stowDir = cfg.stowDir; + + # Function to recursively find all files in a directory + findFiles = dir: + let + files = builtins.attrNames (builtins.readDir dir); + in + concatMap (name: + let + path = dir + "/${name}"; + in + if (builtins.typeOf (builtins.readDir path) == "set") + then findFiles path + else [ path ] + ) files; + + # Get a list of all packages (directories) in the stow directory + stowPackages = builtins.attrNames (builtins.readDir stowDir); + + # Create an attribute set where each attribute is a package name + # and the value is a list of files to be linked. + homeManagerLinks = listToAttrs (map (pkg: + let + pkgPath = stowDir + "/${pkg}"; + files = findFiles pkgPath; + in + nameValuePair pkg (map (file: { + source = file; + target = removePrefix (pkgPath + "/") file; + }) files) + ) stowPackages); + +in +{ + options.services.dotfiles = { + enable = mkEnableOption "Enable dotfiles management"; + + stowDir = mkOption { + type = types.path; + description = "The directory where your stow packages are located."; + }; + + user = mkOption { + type = types.str; + description = "The user to manage dotfiles for."; + }; + }; + + config = mkIf cfg.enable { + home-manager.users.${cfg.user} = { + home.file = + let + allFiles = concatLists (attrValues homeManagerLinks); + in + listToAttrs (map (file: + nameValuePair file.target { + source = file.source; + } + ) allFiles); + }; + }; +} + diff --git a/users/gortium.nix b/users/gortium/default.nix similarity index 91% rename from users/gortium.nix rename to users/gortium/default.nix index 2c5a300..639a579 100644 --- a/users/gortium.nix +++ b/users/gortium/default.nix @@ -1,4 +1,5 @@ { pkgs, inputs, config, keys, ... }: { + home-manager.users.gortium = import ./home.nix; users.users.gortium = { isNormalUser = true; extraGroups = [ "wheel" "docker" ]; # Enable ‘sudo’ for the user. diff --git a/users/gortium/home.nix b/users/gortium/home.nix new file mode 100644 index 0000000..608f95f --- /dev/null +++ b/users/gortium/home.nix @@ -0,0 +1,12 @@ +{ pkgs, ... }: { + services.dotfiles = { + enable = true; + stowDir = ../../../assets/dotfiles; + user = "gortium"; + }; + + home.username = "gortium"; + home.homeDirectory = "/home/gortium"; + home.stateVersion = "23.11"; # Please change this to your version. + programs.home-manager.enable = true; +} From 3f985c72de885c192f20aeab340bd3ed8443f1d5 Mon Sep 17 00:00:00 2001 From: Hermes Date: Sat, 13 Jun 2026 23:15:53 -0400 Subject: [PATCH 02/30] switch to gortium/nixos-uconsole fork --- flake.nix | 221 ++++++++++++++++++++++++------------------------------ 1 file changed, 100 insertions(+), 121 deletions(-) diff --git a/flake.nix b/flake.nix index 5038e6b..5bde76e 100644 --- a/flake.nix +++ b/flake.nix @@ -12,19 +12,17 @@ url = "git+https://git.lix.systems/lix-project/lix?ref=main"; inputs.nixpkgs.follows = "nixpkgs"; }; - - # uConsole CM5 — pinned nixpkgs for kernel patch compatibility nixpkgs-uconsole.url = "github:NixOS/nixpkgs/nixos-25.11"; nixos-uconsole = { - url = "github:nixos-uconsole/nixos-uconsole/v1.1.0"; + url = "github:gortium/nixos-uconsole/cm5_fix"; inputs.nixpkgs.follows = "nixpkgs-uconsole"; inputs.nixos-raspberrypi.follows = "nixos-raspberrypi"; }; nixos-raspberrypi = { url = "github:gortium/nixos-raspberrypi/cm5-cross-v1"; inputs.nixpkgs.follows = "nixpkgs-uconsole"; + }; }; -}; outputs = { self, nixpkgs, agenix, lix , nixpkgs-uconsole, nixos-uconsole, nixos-raspberrypi @@ -43,128 +41,109 @@ pkgs = import nixpkgs { inherit system overlays; config.allowUnfree = true; - config.permittedInsecurePackages = [ - "openclaw-2026.3.12" - ]; + config.permittedInsecurePackages = [ "openclaw-2026.3.12" ]; }; - devShell = import ./shells/nix_dev.nix { inherit pkgs system agenix; }; - in - { - nixosConfigurations = { - lazyworkhorse = nixpkgs.lib.nixosSystem { - specialArgs = { inherit system self keys paths inputs; }; - modules = [ - { - nixpkgs.overlays = overlays; - nixpkgs.config.allowUnfree = true; - nixpkgs.config.rocmSupport = true; - nixpkgs.config.permittedInsecurePackages = [ - "openclaw-2026.3.12" - ]; - nix.package = lix.packages.${system}.default; - } - agenix.nixosModules.default - ./hosts/lazyworkhorse/configuration.nix - ./hosts/lazyworkhorse/hardware-configuration.nix - ./modules/nixos/filesystem/hoardingcow-mount.nix - ./modules/nixos/services/docker_manager.nix - ./modules/nixos/services/open_code_server.nix - ./modules/nixos/services/ollama_init_custom_models.nix - ./modules/nixos/services/openclaw_node.nix - ./modules/nixos/security/ai-worker-restricted.nix - ./users/gortium.nix - ./users/ai-worker.nix - ]; - }; - - cyt-pi = nixpkgs.lib.nixosSystem { - specialArgs = { inherit self keys paths inputs; }; - modules = [ - { - nixpkgs.overlays = overlays; - nixpkgs.config.allowUnfree = true; - nixpkgs.hostPlatform = "aarch64-linux"; - nix.package = lix.packages."aarch64-linux".default; - } - ./hosts/cyt-pi/configuration.nix - ./hosts/cyt-pi/hardware-configuration.nix - ]; - }; - - # ============================================================ - # uConsole CM5 — cross-compilé (build sur x86_64, run sur ARM) - # Approche incrémentale pour fixer l'écran - # ============================================================ - uconsole-cm5 = nixpkgs-uconsole.lib.nixosSystem { - system = "aarch64-linux"; - specialArgs = { - inherit self keys paths inputs; - nixos-raspberrypi = nixos-raspberrypi; - isCM4 = false; - }; - modules = [ - { - # Cross-compile : build sur x86_64, run sur aarch64 - nixpkgs.buildPlatform = "x86_64-linux"; - nixpkgs.hostPlatform = "aarch64-linux"; - nixpkgs.config.allowUnfree = true; - boot.loader.raspberry-pi.bootloader = "kernel"; - } - # nixos-raspberrypi — pkgs.rpi + overlays standardisés - nixos-raspberrypi.nixosModules.nixpkgs-rpi - nixos-raspberrypi.nixosModules.raspberry-pi-5.base - nixos-raspberrypi.lib.inject-overlays - nixos-raspberrypi.lib.inject-overlays-global - # nixos-uconsole CM5 modules - nixos-uconsole.nixosModules.kernel - (nixos-uconsole.nixosModules.cm { lib = nixpkgs-uconsole.lib; isCM4 = false; }) - nixos-uconsole.nixosModules.base - # Lix cross-compilé (lix.packages.aarch64-linux est natif → QEMU) - ({ config, lib, pkgs, inputs, ... }: let - lix-cross = import inputs.nixpkgs-uconsole { - localSystem = { system = "x86_64-linux"; }; - crossSystem = { system = "aarch64-linux"; }; - overlays = [ inputs.lix.overlays.default ]; - }; - in { nix.package = lix-cross.lix; }) - # agenix - agenix.nixosModules.default - # Notre config - ./hosts/uconsole-cm5/configuration.nix - ./hosts/uconsole-cm5/hardware-configuration.nix - ]; - }; + in { + nixosConfigurations = { + lazyworkhorse = nixpkgs.lib.nixosSystem { + specialArgs = { inherit system self keys paths inputs; }; + modules = [ + { + nixpkgs.overlays = overlays; + nixpkgs.config.allowUnfree = true; + nixpkgs.config.rocmSupport = true; + nixpkgs.config.permittedInsecurePackages = [ "openclaw-2026.3.12" ]; + nix.package = lix.packages.${system}.default; + } + agenix.nixosModules.default + ./hosts/lazyworkhorse/configuration.nix + ./hosts/lazyworkhorse/hardware-configuration.nix + ./modules/nixos/filesystem/hoardingcow-mount.nix + ./modules/nixos/services/docker_manager.nix + ./modules/nixos/services/open_code_server.nix + ./modules/nixos/services/ollama_init_custom_models.nix + ./modules/nixos/services/openclaw_node.nix + ./modules/nixos/security/ai-worker-restricted.nix + ./users/gortium.nix + ./users/ai-worker.nix + ]; }; - devShells.${system}.default = devShell; - packages.${system} = { - # Image SD flashable pour uConsole CM5 (SSH + WiFi + clés) - # Usage : dd if=result of=/dev/sda bs=4M status=progress conv=fsync - uconsole-cm5-image = (nixos-raspberrypi.lib.nixosSystem { - system = "aarch64-linux"; - specialArgs = { - inherit self keys inputs; - nixos-raspberrypi = nixos-raspberrypi; - isCM4 = false; - }; - modules = [ - { - nixpkgs.buildPlatform = system; - nixpkgs.hostPlatform = "aarch64-linux"; - } - nixos-raspberrypi.nixosModules.nixpkgs-rpi - nixos-raspberrypi.nixosModules.raspberry-pi-5.base - nixos-raspberrypi.lib.inject-overlays-global - nixos-raspberrypi.nixosModules.sd-image - nixos-uconsole.nixosModules.kernel - (nixos-uconsole.nixosModules.cm { lib = nixpkgs-uconsole.lib; isCM4 = false; }) - nixos-uconsole.nixosModules.base - agenix.nixosModules.default - ./hosts/uconsole-cm5/configuration.nix - ]; - }).config.system.build.sdImage; + + cyt-pi = nixpkgs.lib.nixosSystem { + specialArgs = { inherit self keys paths inputs; }; + modules = [ + { + nixpkgs.overlays = overlays; + nixpkgs.config.allowUnfree = true; + nixpkgs.hostPlatform = "aarch64-linux"; + nix.package = lix.packages."aarch64-linux".default; + } + ./hosts/cyt-pi/configuration.nix + ./hosts/cyt-pi/hardware-configuration.nix + ]; + }; + + uconsole-cm5 = nixpkgs-uconsole.lib.nixosSystem { + system = "aarch64-linux"; + specialArgs = { + inherit self keys paths inputs; + nixos-raspberrypi = nixos-raspberrypi; + isCM4 = false; + }; + modules = [ + { + nixpkgs.buildPlatform = "x86_64-linux"; + nixpkgs.hostPlatform = "aarch64-linux"; + nixpkgs.config.allowUnfree = true; + boot.loader.raspberry-pi.bootloader = "kernel"; + } + nixos-raspberrypi.nixosModules.nixpkgs-rpi +# Patches are now in gortium/nixos-uconsole fork (cm5_fix branch) + nixos-raspberrypi.nixosModules.raspberry-pi-5.base + nixos-raspberrypi.lib.inject-overlays + nixos-raspberrypi.lib.inject-overlays-global + nixos-uconsole.nixosModules.uconsole-cm5 + ({ config, lib, pkgs, inputs, ... }: let + lix-cross = import inputs.nixpkgs-uconsole { + localSystem = { system = "x86_64-linux"; }; + crossSystem = { system = "aarch64-linux"; }; + overlays = [ inputs.lix.overlays.default ]; + }; + in { nix.package = lix-cross.lix; }) + agenix.nixosModules.default + ./hosts/uconsole-cm5/configuration.nix + ./hosts/uconsole-cm5/hardware-configuration.nix + ]; }; }; + + devShells.${system}.default = devShell; + + packages.${system} = { + uconsole-cm5-image = (nixos-raspberrypi.lib.nixosSystem { + system = "aarch64-linux"; + specialArgs = { + inherit self keys inputs; + nixos-raspberrypi = nixos-raspberrypi; + isCM4 = false; + }; + modules = [ + { + nixpkgs.buildPlatform = system; + nixpkgs.hostPlatform = "aarch64-linux"; + } + nixos-raspberrypi.nixosModules.nixpkgs-rpi + nixos-raspberrypi.nixosModules.raspberry-pi-5.base + nixos-raspberrypi.lib.inject-overlays-global + nixos-raspberrypi.nixosModules.sd-image + nixos-uconsole.nixosModules.uconsole-cm5 + agenix.nixosModules.default + ./hosts/uconsole-cm5/configuration.nix + ]; + }).config.system.build.sdImage; + }; + }; } From 4610a0807274870b512e0a761dd04f8a29051a3c Mon Sep 17 00:00:00 2001 From: Hermes Date: Sat, 13 Jun 2026 23:25:47 -0400 Subject: [PATCH 03/30] feat: add Hyprland Wayland compositor from archive/uconsole-cm5-v3 --- hosts/uconsole-cm5/configuration.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hosts/uconsole-cm5/configuration.nix b/hosts/uconsole-cm5/configuration.nix index 5a1b679..34ff9a0 100644 --- a/hosts/uconsole-cm5/configuration.nix +++ b/hosts/uconsole-cm5/configuration.nix @@ -25,4 +25,10 @@ # Firmware hardware.enableRedistributableFirmware = true; + + # Hyprland Wayland compositor (manual start — no SDDM) + programs.hyprland = { + enable = true; + xwayland.enable = true; + }; } From 86d8b7bf8bb6fae9bb906c3b7f0c63a82ebf08ad Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Sat, 13 Jun 2026 23:45:58 -0400 Subject: [PATCH 04/30] fix: disable libcamera in pipewire for cross-compile (rpi-pisp blocks) --- hosts/uconsole-cm5/configuration.nix | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hosts/uconsole-cm5/configuration.nix b/hosts/uconsole-cm5/configuration.nix index 34ff9a0..b48eb04 100644 --- a/hosts/uconsole-cm5/configuration.nix +++ b/hosts/uconsole-cm5/configuration.nix @@ -31,4 +31,11 @@ enable = true; xwayland.enable = true; }; + + # Override pipewire to drop libcamera (fixes cross-compile: rpi-pisp subproject blocked) + nixpkgs.overlays = [ + (final: prev: { + pipewire = prev.pipewire.override { libcamera = null; }; + }) + ]; } From f00477dacc5c77e6fca9e7242366807fb9f9225f Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Sun, 14 Jun 2026 00:16:09 -0400 Subject: [PATCH 05/30] fix: force -Dlibcamera=disabled in pipewire mesonFlags for cross-compile --- hosts/uconsole-cm5/configuration.nix | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hosts/uconsole-cm5/configuration.nix b/hosts/uconsole-cm5/configuration.nix index b48eb04..c7beb18 100644 --- a/hosts/uconsole-cm5/configuration.nix +++ b/hosts/uconsole-cm5/configuration.nix @@ -32,10 +32,12 @@ xwayland.enable = true; }; - # Override pipewire to drop libcamera (fixes cross-compile: rpi-pisp subproject blocked) + # Force-disable libcamera in pipewire's SPA (fixes cross-compile — rpi-pisp subproject blocked) nixpkgs.overlays = [ (final: prev: { - pipewire = prev.pipewire.override { libcamera = null; }; + pipewire = prev.pipewire.overrideAttrs (old: { + mesonFlags = old.mesonFlags ++ [ "-Dlibcamera=disabled" ]; + }); }) ]; } From 9978ea36f4e4c28ac15cd319fdcf9a03caeb82a7 Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Sun, 14 Jun 2026 00:56:31 -0400 Subject: [PATCH 06/30] fix: disable libcamera in pipewire via mesonFlags for both pkgs and rpi --- flake.lock | 126 ++++++++++++++++++++++++++- flake.nix | 19 ++++ hosts/uconsole-cm5/configuration.nix | 9 +- 3 files changed, 145 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index e78ed64..a79a68f 100644 --- a/flake.lock +++ b/flake.lock @@ -23,6 +23,22 @@ "type": "github" } }, + "argononed": { + "flake": false, + "locked": { + "lastModified": 1729566243, + "narHash": "sha256-DPNI0Dpk5aym3Baf5UbEe5GENDrSmmXVdriRSWE+rgk=", + "owner": "nvmd", + "repo": "argononed", + "rev": "16dbee54d49b66d5654d228d1061246b440ef7cf", + "type": "github" + }, + "original": { + "owner": "nvmd", + "repo": "argononed", + "type": "github" + } + }, "flake-compat": { "flake": false, "locked": { @@ -37,6 +53,21 @@ "url": "https://git.lix.systems/lix-project/flake-compat/archive/main.tar.gz" } }, + "flake-compat_2": { + "locked": { + "lastModified": 1767039857, + "narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "home-manager": { "inputs": { "nixpkgs": [ @@ -144,6 +175,80 @@ "type": "github" } }, + "nixos-images": { + "inputs": { + "nixos-stable": [ + "nixos-raspberrypi", + "nixpkgs" + ], + "nixos-unstable": [ + "nixos-raspberrypi", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1747747741, + "narHash": "sha256-LUOH27unNWbGTvZFitHonraNx0JF/55h30r9WxqrznM=", + "owner": "nvmd", + "repo": "nixos-images", + "rev": "cbbd6db325775096680b65e2a32fb6187c09bbb4", + "type": "github" + }, + "original": { + "owner": "nvmd", + "ref": "sdimage-installer", + "repo": "nixos-images", + "type": "github" + } + }, + "nixos-raspberrypi": { + "inputs": { + "argononed": "argononed", + "flake-compat": "flake-compat_2", + "nixos-images": "nixos-images", + "nixpkgs": [ + "nixpkgs-uconsole" + ] + }, + "locked": { + "lastModified": 1781324200, + "narHash": "sha256-JWqxN2Yle86+4Q+GFh12SvB92ZyLeqalVsN9lfMh6eQ=", + "owner": "gortium", + "repo": "nixos-raspberrypi", + "rev": "721a6e9e67dca3a23133db650b87018646bca3e6", + "type": "github" + }, + "original": { + "owner": "gortium", + "ref": "cm5-cross-v1", + "repo": "nixos-raspberrypi", + "type": "github" + } + }, + "nixos-uconsole": { + "inputs": { + "nixos-raspberrypi": [ + "nixos-raspberrypi" + ], + "nixpkgs": [ + "nixpkgs-uconsole" + ] + }, + "locked": { + "lastModified": 1781406889, + "narHash": "sha256-cUD2zvOgHMMjIn4wd4dvpW2GZtCFWtUS+7CPrzQwpPA=", + "owner": "gortium", + "repo": "nixos-uconsole", + "rev": "b556f9315358dbd53bf868cc24e5872ee15763d8", + "type": "github" + }, + "original": { + "owner": "gortium", + "ref": "cm5_fix", + "repo": "nixos-uconsole", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1705033721, @@ -176,6 +281,22 @@ "type": "github" } }, + "nixpkgs-uconsole": { + "locked": { + "lastModified": 1780952837, + "narHash": "sha256-Fwd1+spDtQ0hDyBwme6ufG3n4mY0UrjjFdYHv+G/Hds=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e820eb4a444b46a19b2e03e8dfd2359439ff30fe", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-25.11", + "repo": "nixpkgs", + "type": "github" + } + }, "nixpkgs_2": { "locked": { "lastModified": 1774386573, @@ -212,7 +333,10 @@ "inputs": { "agenix": "agenix", "lix": "lix", - "nixpkgs": "nixpkgs_2" + "nixos-raspberrypi": "nixos-raspberrypi", + "nixos-uconsole": "nixos-uconsole", + "nixpkgs": "nixpkgs_2", + "nixpkgs-uconsole": "nixpkgs-uconsole" } }, "systems": { diff --git a/flake.nix b/flake.nix index 5bde76e..a7c321e 100644 --- a/flake.nix +++ b/flake.nix @@ -99,8 +99,27 @@ nixpkgs.hostPlatform = "aarch64-linux"; nixpkgs.config.allowUnfree = true; boot.loader.raspberry-pi.bootloader = "kernel"; + # Kill camera packages — not needed on uConsole, break cross-compile + nixpkgs.overlays = [ + (final: prev: { + pipewire = prev.pipewire.overrideAttrs (old: { + mesonFlags = old.mesonFlags ++ [ "-Dlibcamera=disabled" ]; + }); + }) + ]; } nixos-raspberrypi.nixosModules.nixpkgs-rpi + # Disable libcamera in rpi pipewire too (separate nixpkgs instance) + ({ config, lib, pkgs, ... }: { + nixpkgs.overlays = [ + (final: prev: { + pipewire = prev.pipewire.overrideAttrs (old: { + mesonFlags = old.mesonFlags ++ [ "-Dlibcamera=disabled" ]; + }); + }) + ]; + }) + # Patches are now in gortium/nixos-uconsole fork (cm5_fix branch) nixos-raspberrypi.nixosModules.raspberry-pi-5.base nixos-raspberrypi.lib.inject-overlays diff --git a/hosts/uconsole-cm5/configuration.nix b/hosts/uconsole-cm5/configuration.nix index c7beb18..5ac7b1b 100644 --- a/hosts/uconsole-cm5/configuration.nix +++ b/hosts/uconsole-cm5/configuration.nix @@ -32,12 +32,5 @@ xwayland.enable = true; }; - # Force-disable libcamera in pipewire's SPA (fixes cross-compile — rpi-pisp subproject blocked) - nixpkgs.overlays = [ - (final: prev: { - pipewire = prev.pipewire.overrideAttrs (old: { - mesonFlags = old.mesonFlags ++ [ "-Dlibcamera=disabled" ]; - }); - }) - ]; + } From 6a1c26cac26afd84e1d62319a920362ad01cd604 Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Sun, 14 Jun 2026 09:03:44 -0400 Subject: [PATCH 07/30] fix: remove libcamera from pipewire buildInputs (both overlays) meta.platforms = [] on libcamera doesn't help because nixos-25.11 pipewire has libcamera unconditionally in buildInputs. Must overrideAttrs to: - filter libcamera out of buildInputs - clear existing libcamera meson flags and set -Dlibcamera=disabled --- flake.nix | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/flake.nix b/flake.nix index a7c321e..9db440d 100644 --- a/flake.nix +++ b/flake.nix @@ -101,9 +101,20 @@ boot.loader.raspberry-pi.bootloader = "kernel"; # Kill camera packages — not needed on uConsole, break cross-compile nixpkgs.overlays = [ + # Make camera packages "unavailable" so no pkgs depend on them (final: prev: { + libcamera = prev.libcamera.overrideAttrs (_: { meta.platforms = []; }); + libcamera-rpi = prev.libcamera-rpi.overrideAttrs (_: { meta.platforms = []; }); + libpisp = prev.libpisp.overrideAttrs (_: { meta.platforms = []; }); + # Pipewire in nixos-25.11 has libcamera unconditionally in buildInputs; + # meta.platforms trick doesn't help — must actually remove it pipewire = prev.pipewire.overrideAttrs (old: { - mesonFlags = old.mesonFlags ++ [ "-Dlibcamera=disabled" ]; + buildInputs = builtins.filter + (x: !(x?pname && x.pname == "libcamera")) + (old.buildInputs or []); + mesonFlags = builtins.filter + (flag: !(builtins.isString flag && builtins.match ".*libcamera.*" flag != null)) + (old.mesonFlags or []) ++ [ "-Dlibcamera=disabled" ]; }); }) ]; @@ -114,7 +125,12 @@ nixpkgs.overlays = [ (final: prev: { pipewire = prev.pipewire.overrideAttrs (old: { - mesonFlags = old.mesonFlags ++ [ "-Dlibcamera=disabled" ]; + buildInputs = builtins.filter + (x: !(x?pname && x.pname == "libcamera")) + (old.buildInputs or []); + mesonFlags = builtins.filter + (flag: !(builtins.isString flag && builtins.match ".*libcamera.*" flag != null)) + (old.mesonFlags or []) ++ [ "-Dlibcamera=disabled" ]; }); }) ]; From 11a49690285e83022ca83a3ea2bdad76df5ebb4c Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Sun, 14 Jun 2026 09:30:50 -0400 Subject: [PATCH 08/30] fix: skip GTK tests in gjs cross-compile for Hyprland --- flake.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/flake.nix b/flake.nix index 9db440d..4c81fd9 100644 --- a/flake.nix +++ b/flake.nix @@ -116,6 +116,10 @@ (flag: !(builtins.isString flag && builtins.match ".*libcamera.*" flag != null)) (old.mesonFlags or []) ++ [ "-Dlibcamera=disabled" ]; }); + # gjs cross-compile fails without GTK; skip intro tests + gjs = prev.gjs.overrideAttrs (old: { + mesonFlags = (old.mesonFlags or []) ++ [ "-Dskip_gtk_tests=true" ]; + }); }) ]; } From 0372b37950d30c5756989ad20ade695d94fe5882 Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Sun, 14 Jun 2026 09:52:35 -0400 Subject: [PATCH 09/30] fix: set Qt6Qml_DIR for hyprland-qt-support cross-compile --- flake.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/flake.nix b/flake.nix index 4c81fd9..3c11c22 100644 --- a/flake.nix +++ b/flake.nix @@ -120,6 +120,12 @@ gjs = prev.gjs.overrideAttrs (old: { mesonFlags = (old.mesonFlags or []) ++ [ "-Dskip_gtk_tests=true" ]; }); + # hyprland-qt-support: Qt6Qml cross-compile path mismatch + hyprland-qt-support = prev.hyprland-qt-support.overrideAttrs (old: { + cmakeFlags = (old.cmakeFlags or []) ++ [ + "-DQt6Qml_DIR=${prev.qtdeclarative.dev}/lib/cmake/Qt6Qml" + ]; + }); }) ]; } From 8afca7315db85c02ef864406ebb7ae2fdba1ae9b Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Sun, 14 Jun 2026 09:56:31 -0400 Subject: [PATCH 10/30] fix: correct qtdeclarative attr to qt6.qtdeclarative --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 3c11c22..f1dcd6e 100644 --- a/flake.nix +++ b/flake.nix @@ -123,7 +123,7 @@ # hyprland-qt-support: Qt6Qml cross-compile path mismatch hyprland-qt-support = prev.hyprland-qt-support.overrideAttrs (old: { cmakeFlags = (old.cmakeFlags or []) ++ [ - "-DQt6Qml_DIR=${prev.qtdeclarative.dev}/lib/cmake/Qt6Qml" + "-DQt6Qml_DIR=${prev.qt6.qtdeclarative}/lib/cmake/Qt6Qml" ]; }); }) From 2476352fdfcbcb686f6331b2a304ea5df464d8ac Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Sun, 14 Jun 2026 10:01:28 -0400 Subject: [PATCH 11/30] fix: skip hyprland qtutils (Qt6Quick missing in aarch64 cross-compile) Qt6Quick and its submodules are not built in the aarch64 qtdeclarative cross-compile output. hyprland-qt-support can't find them and fails. Hyprland only needs qtutils at runtime (added to PATH via wrapProgram). Setting wrapRuntimeDeps = false skips the wrapping entirely, letting Hyprland build without its QML UI support package. --- flake.nix | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/flake.nix b/flake.nix index f1dcd6e..fd20634 100644 --- a/flake.nix +++ b/flake.nix @@ -120,12 +120,9 @@ gjs = prev.gjs.overrideAttrs (old: { mesonFlags = (old.mesonFlags or []) ++ [ "-Dskip_gtk_tests=true" ]; }); - # hyprland-qt-support: Qt6Qml cross-compile path mismatch - hyprland-qt-support = prev.hyprland-qt-support.overrideAttrs (old: { - cmakeFlags = (old.cmakeFlags or []) ++ [ - "-DQt6Qml_DIR=${prev.qt6.qtdeclarative}/lib/cmake/Qt6Qml" - ]; - }); + # Qt6Quick missing from aarch64 qtdeclarative cross-compile; + # skip qtutils runtime deps — Hyprland only needs it for QML UI + hyprland = prev.hyprland.override { wrapRuntimeDeps = false; }; }) ]; } From 42202c8a40d404354be890d9a2756f5e5611c8cb Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Sun, 14 Jun 2026 10:11:44 -0400 Subject: [PATCH 12/30] fix: add hyprwayland-scanner native paths for xdg-desktop-portal-hyprland cross-compile --- flake.nix | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/flake.nix b/flake.nix index fd20634..d0c4bad 100644 --- a/flake.nix +++ b/flake.nix @@ -123,6 +123,14 @@ # Qt6Quick missing from aarch64 qtdeclarative cross-compile; # skip qtutils runtime deps — Hyprland only needs it for QML UI hyprland = prev.hyprland.override { wrapRuntimeDeps = false; }; + # hyprwayland-scanner not found by cross pkg-config wrapper + xdg-desktop-portal-hyprland = prev.xdg-desktop-portal-hyprland.overrideAttrs (old: { + preConfigure = (old.preConfigure or "") + '' + # Point cmake to the correct hyprwayland-scanner pkgconfig + cmakeFlags="$cmakeFlags -Dhyprwayland-scanner_DIR=${prev.buildPackages.hyprwayland-scanner}/lib/cmake/hyprwayland-scanner" 2>/dev/null || true + export PKG_CONFIG_PATH="${prev.buildPackages.hyprwayland-scanner}/lib/pkgconfig:$PKG_CONFIG_PATH" + ''; + }); }) ]; } From 2ee616839e1ccb33dc5d34937864e6b084eb26d5 Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Sun, 14 Jun 2026 18:43:04 -0400 Subject: [PATCH 13/30] chore: point nixos-uconsole input to pr/dcs-panel-detection branch --- flake.lock | 8 ++++---- flake.nix | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index a79a68f..2f54d5c 100644 --- a/flake.lock +++ b/flake.lock @@ -235,16 +235,16 @@ ] }, "locked": { - "lastModified": 1781406889, - "narHash": "sha256-cUD2zvOgHMMjIn4wd4dvpW2GZtCFWtUS+7CPrzQwpPA=", + "lastModified": 1781476310, + "narHash": "sha256-jY6ujqLXNAWJGvt+pAuw1Wg/OiHRGd1B1Z7Czhiq7Q4=", "owner": "gortium", "repo": "nixos-uconsole", - "rev": "b556f9315358dbd53bf868cc24e5872ee15763d8", + "rev": "38a7fcbffbf2d2e122bc1e1c634fe25f66ecda13", "type": "github" }, "original": { "owner": "gortium", - "ref": "cm5_fix", + "ref": "pr/dcs-panel-detection", "repo": "nixos-uconsole", "type": "github" } diff --git a/flake.nix b/flake.nix index d0c4bad..15b5b9f 100644 --- a/flake.nix +++ b/flake.nix @@ -14,7 +14,7 @@ }; nixpkgs-uconsole.url = "github:NixOS/nixpkgs/nixos-25.11"; nixos-uconsole = { - url = "github:gortium/nixos-uconsole/cm5_fix"; + url = "github:gortium/nixos-uconsole/pr/dcs-panel-detection"; inputs.nixpkgs.follows = "nixpkgs-uconsole"; inputs.nixos-raspberrypi.follows = "nixos-raspberrypi"; }; @@ -151,7 +151,7 @@ ]; }) -# Patches are now in gortium/nixos-uconsole fork (cm5_fix branch) +# Patches are now in gortium/nixos-uconsole fork (pr/dcs-panel-detection branch) nixos-raspberrypi.nixosModules.raspberry-pi-5.base nixos-raspberrypi.lib.inject-overlays nixos-raspberrypi.lib.inject-overlays-global From ce7f74c66f2f3b0f2af9cf6590adce55bf48dc64 Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Sun, 14 Jun 2026 18:58:35 -0400 Subject: [PATCH 14/30] remove hyperspace files accidentally committed from feat/hyperspace-pods-module These files were mixed into commit 16acc6a which was intended to only fix SSH options for the uConsole configuration. --- hosts/lazyworkhorse/hyperspace-commit-msg.txt | 12 -- hosts/lazyworkhorse/hyperspace.nix | 134 ------------------ 2 files changed, 146 deletions(-) delete mode 100755 hosts/lazyworkhorse/hyperspace-commit-msg.txt delete mode 100755 hosts/lazyworkhorse/hyperspace.nix diff --git a/hosts/lazyworkhorse/hyperspace-commit-msg.txt b/hosts/lazyworkhorse/hyperspace-commit-msg.txt deleted file mode 100755 index 6916f2e..0000000 --- a/hosts/lazyworkhorse/hyperspace-commit-msg.txt +++ /dev/null @@ -1,12 +0,0 @@ -feat: add Hyperspace Pods NixOS module - -Create modules/nixos/services/hyperspace.nix for the Hyperspace Pods -P2P AI cluster agent. Registered in flake.nix under lazyworkhorse. - -- Fetches CLI binary v5.45.30 via fetchurl with SRI hash verification -- Systemd system service: auto profile, configurable api port 8080, - ai-worker user, GPU device access (kfd+dri), SupplementaryGroups - for video+render groups, service hardening -- Firewall: TCP 4001 libp2p, 30301 chain, 8080 API; UDP 4001 libp2p -- AMD MI50 ROCm via HSA_OVERRIDE_GFX_VERSION=9.0.6 -- Adds video+render groups to ai-worker for persistent GPU access diff --git a/hosts/lazyworkhorse/hyperspace.nix b/hosts/lazyworkhorse/hyperspace.nix deleted file mode 100755 index 0c2a39f..0000000 --- a/hosts/lazyworkhorse/hyperspace.nix +++ /dev/null @@ -1,134 +0,0 @@ -{ config, lib, pkgs, ... }: - -let - cfg = config.services.hyperspace; - - hyperspacePkg = pkgs.stdenv.mkDerivation { - name = "hyperspace-pods-${cfg.version}"; - src = pkgs.fetchurl { - url = "https://github.com/hyperspaceai/aios-cli/releases/download/v${cfg.version}/aios-cli-x86_64-unknown-linux-gnu.tar.gz"; - hash = cfg.packageHash; - }; - sourceRoot = "."; - installPhase = '' - mkdir -p $out/libexec $out/bin - cp -r * $out/libexec/ - chmod +x $out/libexec/aios-cli - ln -s $out/libexec/aios-cli $out/bin/hyperspace - ''; - }; -in { - options.services.hyperspace = { - enable = lib.mkEnableOption "Hyperspace Pods P2P AI cluster agent"; - - version = lib.mkOption { - type = lib.types.str; - default = "5.45.30"; - description = "Hyperspace CLI version to download."; - }; - - packageHash = lib.mkOption { - type = lib.types.str; - default = "sha256-f6fJ8t3exqtYwUD5j+WvD+Hm0oN/Eef0X+R9Rj23dE0="; - description = '' - SRI hash of the hyperspace release tarball (sha256-). - Must be updated when version changes. Generate with: - nix store prefetch-file --hash-algo sha256 \\ - https://github.com/hyperspaceai/aios-cli/releases/download/v{version}/aios-cli-x86_64-unknown-linux-gnu.tar.gz - ''; - }; - - user = lib.mkOption { - type = lib.types.str; - default = "ai-worker"; - description = "System user to run the Hyperspace agent."; - }; - - apiPort = lib.mkOption { - type = lib.types.port; - default = 8080; - description = "OpenAI-compatible API port (configurable via --api-port)."; - }; - - profile = lib.mkOption { - type = lib.types.str; - default = "auto"; - description = '' - Agent profile. Options: auto (auto-detect hardware), full (all capabilities), - inference (GPU inference only), embedding (CPU embedding only), - relay (lightweight relay), storage (storage + memory). - ''; - }; - - autoStart = lib.mkOption { - type = lib.types.bool; - default = true; - description = "Start the agent automatically on boot."; - }; - - openFirewall = lib.mkOption { - type = lib.types.bool; - default = true; - description = "Open P2P mesh (4001 TCP+UDP, 30301 TCP) and API port in the firewall."; - }; - - extraArgs = lib.mkOption { - type = lib.types.listOf lib.types.str; - default = [ ]; - description = "Extra arguments to pass to 'hyperspace start'."; - }; - }; - - config = lib.mkIf cfg.enable { - systemd.services.hyperspace = { - description = "Hyperspace Pods P2P AI Cluster Agent"; - after = [ "network.target" "network-online.target" ]; - wants = [ "network-online.target" ]; - wantedBy = lib.mkIf cfg.autoStart [ "multi-user.target" ]; - - path = with pkgs; [ bash coreutils ]; - - serviceConfig = { - Type = "simple"; - User = cfg.user; - Group = cfg.user; - WorkingDirectory = "${hyperspacePkg}/libexec"; - ExecStart = "${hyperspacePkg}/bin/hyperspace start --profile ${cfg.profile} --api-port ${toString cfg.apiPort} ${lib.escapeShellArgs cfg.extraArgs}"; - Restart = "on-failure"; - RestartSec = 5; - - # AMD MI50 (ROCm) device access - DeviceAllow = [ "/dev/kfd rw" "/dev/dri rw" ]; - - # Supplementary groups for GPU/accelerator access - SupplementaryGroups = [ "video" "render" ]; - - # Hardening - NoNewPrivileges = true; - ProtectHome = "tmpfs"; - ProtectSystem = "strict"; - PrivateTmp = true; - PrivateDevices = false; # Needs /dev/kfd and /dev/dri - }; - - environment = { - HSA_OVERRIDE_GFX_VERSION = "9.0.6"; - HOME = "/home/${cfg.user}"; - }; - }; - - # Firewall ports for P2P mesh (libp2p 4001, chain 30301) and API - networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall [ 4001 30301 cfg.apiPort ]; - networking.firewall.allowedUDPPorts = lib.mkIf cfg.openFirewall [ 4001 ]; - - # Add GPU/accelerator groups to the service user (persistent beyond service restarts) - users.users = lib.mkIf (cfg.user == "ai-worker") { - ai-worker = { - extraGroups = [ "video" "render" ]; - }; - }; - - # ROCm override for AMD MI50 (gfx906) compatibility - environment.variables.HSA_OVERRIDE_GFX_VERSION = "9.0.6"; - }; -} From 02ffcdb55ec95d2ef3e15dc802378026fdfe8589 Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Sun, 14 Jun 2026 19:22:27 -0400 Subject: [PATCH 15/30] feat: add dotfiles submodule and home-manager config - Add dotfiles repo as submodule in assets/dotfiles/ - Rewrite home.nix with direct file references instead of stow service - Remove old custom dotfiles.nix service (replaced by home-manager) - Clean up services/default.nix import --- .gitmodules | 1 + assets/dotfiles | 1 + modules/nixos/services/default.nix | 1 - modules/nixos/services/dotfiles.nix | 69 ----------------------------- users/gortium/home.nix | 65 ++++++++++++++++++++++++--- 5 files changed, 60 insertions(+), 77 deletions(-) create mode 160000 assets/dotfiles delete mode 100644 modules/nixos/services/dotfiles.nix diff --git a/.gitmodules b/.gitmodules index 684b242..66f7a80 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,4 @@ [submodule "assets/dotfiles"] path = assets/dotfiles url = ssh://git@code.lazyworkhorse.net:2222/gortium/dotfiles.git + branch = master diff --git a/assets/dotfiles b/assets/dotfiles new file mode 160000 index 0000000..8e9204b --- /dev/null +++ b/assets/dotfiles @@ -0,0 +1 @@ +Subproject commit 8e9204bc21c488f3c7a1e60f238bce8c2e4abb06 diff --git a/modules/nixos/services/default.nix b/modules/nixos/services/default.nix index c0d569a..f741778 100644 --- a/modules/nixos/services/default.nix +++ b/modules/nixos/services/default.nix @@ -1,6 +1,5 @@ { imports = [ - ./dotfiles.nix ./systemd ]; } diff --git a/modules/nixos/services/dotfiles.nix b/modules/nixos/services/dotfiles.nix deleted file mode 100644 index b05fbe0..0000000 --- a/modules/nixos/services/dotfiles.nix +++ /dev/null @@ -1,69 +0,0 @@ -{ config, lib, pkgs, ... }: - -with lib; - -let - cfg = config.services.dotfiles; - stowDir = cfg.stowDir; - - # Function to recursively find all files in a directory - findFiles = dir: - let - files = builtins.attrNames (builtins.readDir dir); - in - concatMap (name: - let - path = dir + "/${name}"; - in - if (builtins.typeOf (builtins.readDir path) == "set") - then findFiles path - else [ path ] - ) files; - - # Get a list of all packages (directories) in the stow directory - stowPackages = builtins.attrNames (builtins.readDir stowDir); - - # Create an attribute set where each attribute is a package name - # and the value is a list of files to be linked. - homeManagerLinks = listToAttrs (map (pkg: - let - pkgPath = stowDir + "/${pkg}"; - files = findFiles pkgPath; - in - nameValuePair pkg (map (file: { - source = file; - target = removePrefix (pkgPath + "/") file; - }) files) - ) stowPackages); - -in -{ - options.services.dotfiles = { - enable = mkEnableOption "Enable dotfiles management"; - - stowDir = mkOption { - type = types.path; - description = "The directory where your stow packages are located."; - }; - - user = mkOption { - type = types.str; - description = "The user to manage dotfiles for."; - }; - }; - - config = mkIf cfg.enable { - home-manager.users.${cfg.user} = { - home.file = - let - allFiles = concatLists (attrValues homeManagerLinks); - in - listToAttrs (map (file: - nameValuePair file.target { - source = file.source; - } - ) allFiles); - }; - }; -} - diff --git a/users/gortium/home.nix b/users/gortium/home.nix index 608f95f..affc2e7 100644 --- a/users/gortium/home.nix +++ b/users/gortium/home.nix @@ -1,12 +1,63 @@ -{ pkgs, ... }: { - services.dotfiles = { - enable = true; - stowDir = ../../../assets/dotfiles; - user = "gortium"; - }; +{ pkgs, lib, config, inputs, ... }: +let + dotfiles = ./assets/dotfiles; +in { home.username = "gortium"; home.homeDirectory = "/home/gortium"; - home.stateVersion = "23.11"; # Please change this to your version. + home.stateVersion = "23.11"; programs.home-manager.enable = true; + + home.file = { + # zsh + ".zshrc".source = "${dotfiles}/zsh/.zshrc"; + + # tmux + ".tmux.conf".source = "${dotfiles}/tmux/.tmux.conf"; + + # kitty + ".config/kitty/kitty.conf".source = "${dotfiles}/kitty/.config/kitty/kitty.conf"; + + # nvim + ".config/nvim/init.lua".source = "${dotfiles}/nvim/.config/nvim/init.lua"; + + # starship + ".config/starship.toml".source = "${dotfiles}/starship/.config/starship.toml"; + + # btop + ".config/btop/btop.conf".source = "${dotfiles}/btop/.config/btop/btop.conf"; + + # waybar + ".config/waybar/style.css".source = "${dotfiles}/waybar/.config/waybar/style.css"; + ".config/waybar/config.jsonc".source = "${dotfiles}/waybar/.config/waybar/config.jsonc"; + + # wofi + ".config/wofi/style.css".source = "${dotfiles}/wofi/.config/wofi/style.css"; + ".config/wofi/config".source = "${dotfiles}/wofi/.config/wofi/config"; + + # yazi + ".config/yazi/yazi.toml".source = "${dotfiles}/yazi/.config/yazi/yazi.toml"; + + # hyprland + ".config/hypr/hyprland.conf".source = "${dotfiles}/hypr/.config/hypr/hyprland.conf"; + + # doom emacs + ".config/doom/config.el".source = "${dotfiles}/doom/.config/doom/config.el"; + ".config/doom/init.el".source = "${dotfiles}/doom/.config/doom/init.el"; + ".config/doom/packages.el".source = "${dotfiles}/doom/.config/doom/packages.el"; + }; + + home.packages = with pkgs; [ + # core + git zsh tmux starship + # editors + neovim kitty + # tools + btop yazi ripgrep fd fzf + # wayland + waybar wofi + ]; + + programs.zsh.enable = true; + programs.starship.enable = true; } From f344739b94754966a2a82cb0d2c104d6ebcadcc4 Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Sun, 14 Jun 2026 19:37:14 -0400 Subject: [PATCH 16/30] feat: per-host Hyprland monitor config via home-manager - Split hyprland.conf into common (keybinds, looks, animations) and per-host (monitors, env, workspaces) configs - Add uconsole.conf for CM5 DSI display (720x1280) - Add laptop.conf for NVIDIA + external monitors - home.nix links the correct host config based on hostname - Remove NVIDIA env vars from common config --- result | 1 + result-uconsole | 1 + users/gortium/home.nix | 25 +++++++++++++++---------- 3 files changed, 17 insertions(+), 10 deletions(-) create mode 120000 result create mode 120000 result-uconsole diff --git a/result b/result new file mode 120000 index 0000000..c445871 --- /dev/null +++ b/result @@ -0,0 +1 @@ +/nix/store/z86r4awsbrc5q9qhwwi757wxixcqgn31-nixos-system-uConsole-25.11.20260608.e820eb4 \ No newline at end of file diff --git a/result-uconsole b/result-uconsole new file mode 120000 index 0000000..e5d8532 --- /dev/null +++ b/result-uconsole @@ -0,0 +1 @@ +/nix/store/7y7rfksqcf5smz59jjixyl56bxq50j9g-nixos-system-uConsole-25.11.20260608.e820eb4 \ No newline at end of file diff --git a/users/gortium/home.nix b/users/gortium/home.nix index affc2e7..5b3383c 100644 --- a/users/gortium/home.nix +++ b/users/gortium/home.nix @@ -2,6 +2,7 @@ let dotfiles = ./assets/dotfiles; + isUconsole = config.networking.hostName == "uConsole"; in { home.username = "gortium"; home.homeDirectory = "/home/gortium"; @@ -38,24 +39,28 @@ in { # yazi ".config/yazi/yazi.toml".source = "${dotfiles}/yazi/.config/yazi/yazi.toml"; - # hyprland + # hyprland — common config ".config/hypr/hyprland.conf".source = "${dotfiles}/hypr/.config/hypr/hyprland.conf"; + ".config/hypr/hypridle.conf".source = "${dotfiles}/hypr/.config/hypr/hypridle.conf"; + ".config/hypr/hyprlock.conf".source = "${dotfiles}/hypr/.config/hypr/hyprlock.conf"; + ".config/hypr/hyprpaper.conf".source = "${dotfiles}/hypr/.config/hypr/hyprpaper.conf"; + ".config/hypr/mocha.conf".source = "${dotfiles}/hypr/.config/hypr/mocha.conf"; - # doom emacs - ".config/doom/config.el".source = "${dotfiles}/doom/.config/doom/config.el"; - ".config/doom/init.el".source = "${dotfiles}/doom/.config/doom/init.el"; - ".config/doom/packages.el".source = "${dotfiles}/doom/.config/doom/packages.el"; + # hyprland — host-specific monitor config + ".config/hypr/host/monitors.conf".source = + if isUconsole + then "${dotfiles}/hypr/.config/hypr/host/uconsole.conf" + else "${dotfiles}/hypr/.config/hypr/host/laptop.conf"; }; home.packages = with pkgs; [ - # core git zsh tmux starship - # editors neovim kitty - # tools btop yazi ripgrep fd fzf - # wayland - waybar wofi + ] ++ lib.optionals (!isUconsole) [ + waybar wofi swww hyprshot + ] ++ lib.optionals isUconsole [ + brightnessctl ]; programs.zsh.enable = true; From 7238e9d45cb45f577117c03cc1dff93f40e81688 Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Sun, 14 Jun 2026 19:37:35 -0400 Subject: [PATCH 17/30] update dotfiles submodule: per-host hyprland config --- assets/dotfiles | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/dotfiles b/assets/dotfiles index 8e9204b..75df6d5 160000 --- a/assets/dotfiles +++ b/assets/dotfiles @@ -1 +1 @@ -Subproject commit 8e9204bc21c488f3c7a1e60f238bce8c2e4abb06 +Subproject commit 75df6d502a0786e62255eff1c48041c3f21e6a5a From 8423a121eb9008282d74f3c629d7e40da4cd2f4d Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Sun, 14 Jun 2026 19:41:58 -0400 Subject: [PATCH 18/30] rename host/ -> hosts/ in dotfiles submodule --- assets/dotfiles | 2 +- users/gortium/home.nix | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/dotfiles b/assets/dotfiles index 75df6d5..f453874 160000 --- a/assets/dotfiles +++ b/assets/dotfiles @@ -1 +1 @@ -Subproject commit 75df6d502a0786e62255eff1c48041c3f21e6a5a +Subproject commit f45387456b4d1f594e2d623366248ece64f50b25 diff --git a/users/gortium/home.nix b/users/gortium/home.nix index 5b3383c..ce7902f 100644 --- a/users/gortium/home.nix +++ b/users/gortium/home.nix @@ -49,8 +49,8 @@ in { # hyprland — host-specific monitor config ".config/hypr/host/monitors.conf".source = if isUconsole - then "${dotfiles}/hypr/.config/hypr/host/uconsole.conf" - else "${dotfiles}/hypr/.config/hypr/host/laptop.conf"; + then "${dotfiles}/hypr/.config/hypr/hosts/uconsole.conf" + else "${dotfiles}/hypr/.config/hypr/hosts/laptop.conf"; }; home.packages = with pkgs; [ From f06d9028f0a8dca9ea4800c810e40801c6e686a2 Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Sun, 14 Jun 2026 19:52:11 -0400 Subject: [PATCH 19/30] feat: add ai-worker user to uConsole for Hermes SSH access --- hosts/uconsole-cm5/configuration.nix | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/hosts/uconsole-cm5/configuration.nix b/hosts/uconsole-cm5/configuration.nix index 5ac7b1b..45e4c42 100644 --- a/hosts/uconsole-cm5/configuration.nix +++ b/hosts/uconsole-cm5/configuration.nix @@ -34,3 +34,12 @@ } + + # AI worker user (Hermes access) + users.users.ai-worker = { + isNormalUser = false; + shell = pkgs.bash; + openssh.authorizedKeys.keys = with keys; [ + users.ai-worker.main + ]; + }; From 900416389195320bc633f2740aa33ddedfd69772 Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Sun, 14 Jun 2026 19:53:40 -0400 Subject: [PATCH 20/30] feat: add agenix secret for gortium password on uConsole - Add gortium_password.age entry in secrets.nix - Add age.secrets.gortium_password in uConsole config - Add hashedPasswordFile to existing gortium user - Add ai-worker user for Hermes SSH access --- hosts/uconsole-cm5/configuration.nix | 7 +++++++ secrets/secrets.nix | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/hosts/uconsole-cm5/configuration.nix b/hosts/uconsole-cm5/configuration.nix index 45e4c42..6e879e0 100644 --- a/hosts/uconsole-cm5/configuration.nix +++ b/hosts/uconsole-cm5/configuration.nix @@ -43,3 +43,10 @@ users.ai-worker.main ]; }; + + # Age secret for gortium password + age.secrets.gortium_password = { + file = ../secrets/gortium_password.age; + }; + + users.users.gortium.hashedPasswordFile = config.age.secrets.gortium_password.path; diff --git a/secrets/secrets.nix b/secrets/secrets.nix index 612ce18..cf42b6c 100644 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -8,8 +8,9 @@ let in { "containers.env.age".publicKeys = authorizedKeys; + "gortium_password.age".publicKeys = authorizedKeys; + "home_wifi.age".publicKeys = authorizedKeys; "lazyworkhorse_host_ssh_key.age".publicKeys = authorizedKeys; "n8n_ssh_key.age".publicKeys = authorizedKeys; "openclaw_gateway_token.age".publicKeys = authorizedKeys; - "home_wifi.age".publicKeys = authorizedKeys; } From cdbb7de04d32a3a6f7b7f20574b3176d92c06823 Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Sun, 14 Jun 2026 19:56:33 -0400 Subject: [PATCH 21/30] fix: properly structure uConsole config (ai-worker, gortium password, age secret) --- hosts/uconsole-cm5/configuration.nix | 35 ++++++++++++++-------------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/hosts/uconsole-cm5/configuration.nix b/hosts/uconsole-cm5/configuration.nix index 6e879e0..477f4b0 100644 --- a/hosts/uconsole-cm5/configuration.nix +++ b/hosts/uconsole-cm5/configuration.nix @@ -20,6 +20,23 @@ users.ai-worker.main ]; + # AI worker user (Hermes SSH access) + users.users.ai-worker = { + isNormalUser = false; + shell = pkgs.bash; + openssh.authorizedKeys.keys = with keys; [ + users.ai-worker.main + ]; + }; + + # Age secret for gortium password (file created by user) + age.secrets.gortium_password = { + file = ../secrets/gortium_password.age; + }; + + # Password file for gortium (merges with users/gortium/default.nix) + users.users.gortium.hashedPasswordFile = config.age.secrets.gortium_password.path; + # WiFi via NetworkManager + secret agenix networking.networkmanager.enable = true; @@ -31,22 +48,4 @@ enable = true; xwayland.enable = true; }; - - } - - # AI worker user (Hermes access) - users.users.ai-worker = { - isNormalUser = false; - shell = pkgs.bash; - openssh.authorizedKeys.keys = with keys; [ - users.ai-worker.main - ]; - }; - - # Age secret for gortium password - age.secrets.gortium_password = { - file = ../secrets/gortium_password.age; - }; - - users.users.gortium.hashedPasswordFile = config.age.secrets.gortium_password.path; From eb3fe42542c742b611b1baa742dddc40296623b3 Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Sun, 14 Jun 2026 20:56:17 -0400 Subject: [PATCH 22/30] refactor: extract shared uconsole modules to eliminate toplevel/image duplication --- flake.nix | 155 ++++++++++++++++++++++++------------------------------ 1 file changed, 70 insertions(+), 85 deletions(-) diff --git a/flake.nix b/flake.nix index 15b5b9f..89776dd 100644 --- a/flake.nix +++ b/flake.nix @@ -46,6 +46,74 @@ devShell = import ./shells/nix_dev.nix { inherit pkgs system agenix; }; + + # Cross-compile overlay fixes for Hyprland and deps on aarch64 + uconsoleCrossOverlay = final: prev: { + libcamera = prev.libcamera.overrideAttrs (_: { meta.platforms = []; }); + libcamera-rpi = prev.libcamera-rpi.overrideAttrs (_: { meta.platforms = []; }); + libpisp = prev.libpisp.overrideAttrs (_: { meta.platforms = []; }); + pipewire = prev.pipewire.overrideAttrs (old: { + buildInputs = builtins.filter + (x: !(x?pname && x.pname == "libcamera")) + (old.buildInputs or []); + mesonFlags = builtins.filter + (flag: !(builtins.isString flag && builtins.match ".*libcamera.*" flag != null)) + (old.mesonFlags or []) ++ [ "-Dlibcamera=disabled" ]; + }); + gjs = prev.gjs.overrideAttrs (old: { + mesonFlags = (old.mesonFlags or []) ++ [ "-Dskip_gtk_tests=true" ]; + }); + hyprland = prev.hyprland.override { wrapRuntimeDeps = false; }; + xdg-desktop-portal-hyprland = prev.xdg-desktop-portal-hyprland.overrideAttrs (old: { + preConfigure = (old.preConfigure or "") + '' + cmakeFlags="$cmakeFlags -Dhyprwayland-scanner_DIR=${prev.buildPackages.hyprwayland-scanner}/lib/cmake/hyprwayland-scanner" 2>/dev/null || true + export PKG_CONFIG_PATH="${prev.buildPackages.hyprwayland-scanner}/lib/pkgconfig:$PKG_CONFIG_PATH" + ''; + }); + }; + + # RPI-specific pipewire libcamera fix (separate nixpkgs instance) + uconsoleRpiPipewireOverlay = final: prev: { + pipewire = prev.pipewire.overrideAttrs (old: { + buildInputs = builtins.filter + (x: !(x?pname && x.pname == "libcamera")) + (old.buildInputs or []); + mesonFlags = builtins.filter + (flag: !(builtins.isString flag && builtins.match ".*libcamera.*" flag != null)) + (old.mesonFlags or []) ++ [ "-Dlibcamera=disabled" ]; + }); + }; + + # Shared uConsole CM5 module set — used by both toplevel and SD image + uconsoleBaseModules = [ + { + nixpkgs.buildPlatform = "x86_64-linux"; + nixpkgs.hostPlatform = "aarch64-linux"; + nixpkgs.config.allowUnfree = true; + boot.loader.raspberry-pi.bootloader = "kernel"; + nixpkgs.overlays = [ uconsoleCrossOverlay ]; + } + nixos-raspberrypi.nixosModules.nixpkgs-rpi + ({ config, lib, pkgs, ... }: { + nixpkgs.overlays = [ uconsoleRpiPipewireOverlay ]; + }) + nixos-raspberrypi.nixosModules.raspberry-pi-5.base + nixos-raspberrypi.lib.inject-overlays + nixos-raspberrypi.lib.inject-overlays-global + nixos-uconsole.nixosModules.uconsole-cm5 + # Cross-compiled Lix for uConsole + ({ config, lib, pkgs, inputs, ... }: let + lixCross = import inputs.nixpkgs-uconsole { + localSystem = { system = "x86_64-linux"; }; + crossSystem = { system = "aarch64-linux"; }; + overlays = [ inputs.lix.overlays.default ]; + }; + in { nix.package = lixCross.lix; }) + agenix.nixosModules.default + ./hosts/uconsole-cm5/configuration.nix + ./hosts/uconsole-cm5/hardware-configuration.nix + ]; + in { nixosConfigurations = { lazyworkhorse = nixpkgs.lib.nixosSystem { @@ -93,80 +161,7 @@ nixos-raspberrypi = nixos-raspberrypi; isCM4 = false; }; - modules = [ - { - nixpkgs.buildPlatform = "x86_64-linux"; - nixpkgs.hostPlatform = "aarch64-linux"; - nixpkgs.config.allowUnfree = true; - boot.loader.raspberry-pi.bootloader = "kernel"; - # Kill camera packages — not needed on uConsole, break cross-compile - nixpkgs.overlays = [ - # Make camera packages "unavailable" so no pkgs depend on them - (final: prev: { - libcamera = prev.libcamera.overrideAttrs (_: { meta.platforms = []; }); - libcamera-rpi = prev.libcamera-rpi.overrideAttrs (_: { meta.platforms = []; }); - libpisp = prev.libpisp.overrideAttrs (_: { meta.platforms = []; }); - # Pipewire in nixos-25.11 has libcamera unconditionally in buildInputs; - # meta.platforms trick doesn't help — must actually remove it - pipewire = prev.pipewire.overrideAttrs (old: { - buildInputs = builtins.filter - (x: !(x?pname && x.pname == "libcamera")) - (old.buildInputs or []); - mesonFlags = builtins.filter - (flag: !(builtins.isString flag && builtins.match ".*libcamera.*" flag != null)) - (old.mesonFlags or []) ++ [ "-Dlibcamera=disabled" ]; - }); - # gjs cross-compile fails without GTK; skip intro tests - gjs = prev.gjs.overrideAttrs (old: { - mesonFlags = (old.mesonFlags or []) ++ [ "-Dskip_gtk_tests=true" ]; - }); - # Qt6Quick missing from aarch64 qtdeclarative cross-compile; - # skip qtutils runtime deps — Hyprland only needs it for QML UI - hyprland = prev.hyprland.override { wrapRuntimeDeps = false; }; - # hyprwayland-scanner not found by cross pkg-config wrapper - xdg-desktop-portal-hyprland = prev.xdg-desktop-portal-hyprland.overrideAttrs (old: { - preConfigure = (old.preConfigure or "") + '' - # Point cmake to the correct hyprwayland-scanner pkgconfig - cmakeFlags="$cmakeFlags -Dhyprwayland-scanner_DIR=${prev.buildPackages.hyprwayland-scanner}/lib/cmake/hyprwayland-scanner" 2>/dev/null || true - export PKG_CONFIG_PATH="${prev.buildPackages.hyprwayland-scanner}/lib/pkgconfig:$PKG_CONFIG_PATH" - ''; - }); - }) - ]; - } - nixos-raspberrypi.nixosModules.nixpkgs-rpi - # Disable libcamera in rpi pipewire too (separate nixpkgs instance) - ({ config, lib, pkgs, ... }: { - nixpkgs.overlays = [ - (final: prev: { - pipewire = prev.pipewire.overrideAttrs (old: { - buildInputs = builtins.filter - (x: !(x?pname && x.pname == "libcamera")) - (old.buildInputs or []); - mesonFlags = builtins.filter - (flag: !(builtins.isString flag && builtins.match ".*libcamera.*" flag != null)) - (old.mesonFlags or []) ++ [ "-Dlibcamera=disabled" ]; - }); - }) - ]; - }) - -# Patches are now in gortium/nixos-uconsole fork (pr/dcs-panel-detection branch) - nixos-raspberrypi.nixosModules.raspberry-pi-5.base - nixos-raspberrypi.lib.inject-overlays - nixos-raspberrypi.lib.inject-overlays-global - nixos-uconsole.nixosModules.uconsole-cm5 - ({ config, lib, pkgs, inputs, ... }: let - lix-cross = import inputs.nixpkgs-uconsole { - localSystem = { system = "x86_64-linux"; }; - crossSystem = { system = "aarch64-linux"; }; - overlays = [ inputs.lix.overlays.default ]; - }; - in { nix.package = lix-cross.lix; }) - agenix.nixosModules.default - ./hosts/uconsole-cm5/configuration.nix - ./hosts/uconsole-cm5/hardware-configuration.nix - ]; + modules = uconsoleBaseModules; }; }; @@ -180,18 +175,8 @@ nixos-raspberrypi = nixos-raspberrypi; isCM4 = false; }; - modules = [ - { - nixpkgs.buildPlatform = system; - nixpkgs.hostPlatform = "aarch64-linux"; - } - nixos-raspberrypi.nixosModules.nixpkgs-rpi - nixos-raspberrypi.nixosModules.raspberry-pi-5.base - nixos-raspberrypi.lib.inject-overlays-global + modules = uconsoleBaseModules ++ [ nixos-raspberrypi.nixosModules.sd-image - nixos-uconsole.nixosModules.uconsole-cm5 - agenix.nixosModules.default - ./hosts/uconsole-cm5/configuration.nix ]; }).config.system.build.sdImage; }; From e95baddb966405739c4771ddc8df8982816ae52f Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Sun, 14 Jun 2026 21:05:22 -0400 Subject: [PATCH 23/30] rename users/gortium/default.nix -> gortium.nix, add to uconsole modules --- flake.nix | 3 ++- users/gortium/{default.nix => gortium.nix} | 0 2 files changed, 2 insertions(+), 1 deletion(-) rename users/gortium/{default.nix => gortium.nix} (100%) diff --git a/flake.nix b/flake.nix index 89776dd..ecd0321 100644 --- a/flake.nix +++ b/flake.nix @@ -112,6 +112,7 @@ agenix.nixosModules.default ./hosts/uconsole-cm5/configuration.nix ./hosts/uconsole-cm5/hardware-configuration.nix + ./users/gortium/gortium.nix ]; in { @@ -135,7 +136,7 @@ ./modules/nixos/services/ollama_init_custom_models.nix ./modules/nixos/services/openclaw_node.nix ./modules/nixos/security/ai-worker-restricted.nix - ./users/gortium.nix + ./users/gortium/gortium.nix ./users/ai-worker.nix ]; }; diff --git a/users/gortium/default.nix b/users/gortium/gortium.nix similarity index 100% rename from users/gortium/default.nix rename to users/gortium/gortium.nix From fba52fa66db7e403895e271a1aaf5fd46f5cfca3 Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Sun, 14 Jun 2026 21:09:10 -0400 Subject: [PATCH 24/30] fix: use passwordFile instead of hashedPasswordFile (matches other secrets: plain text) --- hosts/uconsole-cm5/configuration.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hosts/uconsole-cm5/configuration.nix b/hosts/uconsole-cm5/configuration.nix index 477f4b0..d726ed6 100644 --- a/hosts/uconsole-cm5/configuration.nix +++ b/hosts/uconsole-cm5/configuration.nix @@ -35,7 +35,7 @@ }; # Password file for gortium (merges with users/gortium/default.nix) - users.users.gortium.hashedPasswordFile = config.age.secrets.gortium_password.path; + users.users.gortium.passwordFile = config.age.secrets.gortium_password.path; # WiFi via NetworkManager + secret agenix networking.networkmanager.enable = true; From e991359584f831639297a11b49712748e43e1e27 Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Sun, 14 Jun 2026 21:34:42 -0400 Subject: [PATCH 25/30] add gortium password age secret --- secrets/gortium_password.age | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 secrets/gortium_password.age diff --git a/secrets/gortium_password.age b/secrets/gortium_password.age new file mode 100644 index 0000000..3594b19 --- /dev/null +++ b/secrets/gortium_password.age @@ -0,0 +1,10 @@ +-----BEGIN AGE ENCRYPTED FILE----- +YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IEdoTUQ4QSA4MlFz +SHFjYjJMVHRlTWNGVGI2bHQxc0xRd2tlaExlM0NFMWhlbkR2bVg0CkxxenVTaXkr +eWxybDdCeUM0ejRvZWI4cFZCWm5VczRvZkNnT0d5Y1oyYmsKLT4gK1NmRzVtLWdy +ZWFzZSB3UDI6TyNaCnF4Ylk0QWduaXZxRFBFbDBOZ0dxeGxiWTVCYjRtZTJBRkFC +YU5qaytYWWI4OWl1K1FSdXNlY2JXZjkzak9tTHkKVFlCRlRqY1FVSzFmNS9yZmxF +aEUxelUwNEpKN3VXYi9KUWN4bXFscm5oUEFOajhRZDlERWVYcFgvQQotLS0gK1JI +VERTQjB6d1k3NDQwbjNveXBqcFk1WE96cHlaTTVkTWRMZENPamFJZwpcT1CP/KvU +CsunvfX9RBlSSKuw4eem9N9s3JqJNj4FRQizNx6QzlE1vSME +-----END AGE ENCRYPTED FILE----- From 8651295b0a541bee574a2c85aeddef359d7dd55c Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Sun, 14 Jun 2026 21:48:23 -0400 Subject: [PATCH 26/30] Fixed stuff maybe i guess not sure --- assets/ollama/Dockerfile | 106 --------------------------------------- flake.nix | 6 +-- 2 files changed, 3 insertions(+), 109 deletions(-) delete mode 100644 assets/ollama/Dockerfile diff --git a/assets/ollama/Dockerfile b/assets/ollama/Dockerfile deleted file mode 100644 index 438e607..0000000 --- a/assets/ollama/Dockerfile +++ /dev/null @@ -1,106 +0,0 @@ -# ollama-gfx906/Dockerfile -# -# Custom ollama image with ROCm 6.1 + gfx906 (MI50) support. -# The official ollama/rocm image ships ROCm 7.2 which dropped gfx906. -# This uses v0.23.2's native CMake build system with AMDGPU_TARGETS including gfx906. -# -# Build: docker build -t ollama/ollama:rocm-gfx906 ai/ollama - -FROM rocm/dev-ubuntu-22.04:6.1.2-complete AS builder - -# Build dependencies (CMake, Ninja, Go) -ARG CMAKEVERSION=3.31.2 -ARG NINJAVERSION=1.12.1 -ARG GOLANG_VERSION=1.22.0 - -RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \ - curl git ccache build-essential pkg-config unzip \ - && rm -rf /var/lib/apt/lists/* - -# Install CMake from official binaries -RUN curl -fsSL https://github.com/Kitware/CMake/releases/download/v${CMAKEVERSION}/cmake-${CMAKEVERSION}-linux-x86_64.tar.gz \ - | tar xz -C /usr/local --strip-components 1 - -# Install Ninja -RUN curl -fsSL -o /tmp/ninja.zip \ - https://github.com/ninja-build/ninja/releases/download/v${NINJAVERSION}/ninja-linux.zip \ - && unzip /tmp/ninja.zip -d /usr/local/bin && rm /tmp/ninja.zip - -# Install Go -RUN curl -fsSL https://go.dev/dl/go${GOLANG_VERSION}.linux-amd64.tar.gz \ - | tar xz -C /usr/local -ENV PATH=/usr/local/go/bin:$PATH - -ARG OLLAMA_VERSION=v0.23.2 -RUN git clone --depth 1 --branch ${OLLAMA_VERSION} https://github.com/ollama/ollama.git /build -WORKDIR /build - -# ROCm paths -ENV HIP_PATH=/opt/rocm -ENV ROCM_PATH=/opt/rocm -ENV CMAKE_GENERATOR=Ninja -ENV LDFLAGS=-s - -# Step 1: Build CPU backends with GCC (no ROCm preset) -# Pre-set CMAKE_HIP_COMPILER="" to prevent check_language(HIP) from -# finding a HIP compiler (it searches /opt/rocm even without PATH). -# Remove /opt/rocm from PATH to prevent find_program from finding hipcc. -RUN mkdir -p build-cpu && \ - PATH=/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \ - cmake -B build-cpu -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_HIP_COMPILER="" \ - -DCMAKE_INSTALL_PREFIX=/build/dist && \ - cmake --build build-cpu --target ggml-cpu -- -l $(nproc) && \ - cmake --install build-cpu --component CPU --strip && \ - echo "=== CPU install ===" && \ - (find /build/dist/lib/ollama -type f -o -type l 2>&1 | head -20 || echo "empty") - -# Step 2: Build HIP backend with ROCm preset + gfx906 target only -# The ROCm 6 preset enables HIP language detection (enable_language(HIP)) -# which ensures GPU kernels are properly compiled for gfx906. -# OLLAMA_RUNNER_DIR=rocm from the preset, so HIP goes to lib/ollama/rocm/ -# Need CMAKE_PREFIX_PATH so find_package(hip) finds hip-config.cmake -# at /opt/rocm/lib/cmake/hip/hip-config.cmake. -RUN mkdir -p build-hip && \ - cmake -B build-hip \ - --preset 'ROCm 6' \ - -DAMDGPU_TARGETS="gfx906:xnack-" \ - -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_PREFIX_PATH="/opt/rocm" && \ - cmake --build build-hip --target ggml-hip -- -l $(nproc) && \ - cmake --install build-hip --component HIP --strip && \ - echo "=== HIP install ===" && \ - find /build/dist/lib/ollama -type f -o -type l | head -20 - -# Step 3: Build Go binary (GCC for CGo linking) -ENV CGO_ENABLED=1 -RUN go build -trimpath -ldflags="-X=github.com/ollama/ollama/version.Version=${OLLAMA_VERSION}" -o /build/dist/ollama . - -# ---------- Runtime image ---------- -FROM ubuntu:24.04 - -RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \ - ca-certificates curl libstdc++6 libgomp1 libvulkan1 libopenblas0 \ - && rm -rf /var/lib/apt/lists/* - -# Copy ROCm 6.1 runtime libraries -# These are needed at runtime by ggml-hip via LD_LIBRARY_PATH -COPY --from=builder /opt/rocm/lib/ /opt/rocm/lib/ -COPY --from=builder /opt/rocm/share/ /opt/rocm/share/ - -# Copy ollama binary + all backends (CPU + HIP) -# CPU install: /build/dist/lib/ollama/libggml-*.so -# HIP install: /build/dist/lib/ollama/rocm/libggml-hip.so -COPY --from=builder /build/dist/ollama /usr/bin/ollama -COPY --from=builder /build/dist/lib/ollama/ /usr/lib/ollama/ - -RUN ldconfig - -ENV LD_LIBRARY_PATH=/opt/rocm/lib:/usr/lib/ollama/rocm:/usr/lib/ollama -ENV HSA_OVERRIDE_GFX_VERSION=9.0.6 -ENV HCC_AMDGPU_TARGET=gfx906 -ENV HSA_ENABLE_SDMA=0 - -EXPOSE 11434 -ENTRYPOINT ["/bin/ollama"] -CMD ["serve"] diff --git a/flake.nix b/flake.nix index ecd0321..964f0b1 100644 --- a/flake.nix +++ b/flake.nix @@ -113,6 +113,7 @@ ./hosts/uconsole-cm5/configuration.nix ./hosts/uconsole-cm5/hardware-configuration.nix ./users/gortium/gortium.nix + ./users/ai-worker/ai-worker.nix ]; in { @@ -132,12 +133,10 @@ ./hosts/lazyworkhorse/hardware-configuration.nix ./modules/nixos/filesystem/hoardingcow-mount.nix ./modules/nixos/services/docker_manager.nix - ./modules/nixos/services/open_code_server.nix ./modules/nixos/services/ollama_init_custom_models.nix - ./modules/nixos/services/openclaw_node.nix ./modules/nixos/security/ai-worker-restricted.nix ./users/gortium/gortium.nix - ./users/ai-worker.nix + ./users/ai-worker/ai-worker.nix ]; }; @@ -152,6 +151,7 @@ } ./hosts/cyt-pi/configuration.nix ./hosts/cyt-pi/hardware-configuration.nix + ./users/gortium/gortium.nix ]; }; From 6399196a2cb8218d61403b7f81ced59f4058b3cc Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Sun, 14 Jun 2026 21:55:48 -0400 Subject: [PATCH 27/30] fix: move gortium passwordFile to shared user module (applies to all hosts) --- hosts/uconsole-cm5/configuration.nix | 1 - users/gortium/gortium.nix | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/hosts/uconsole-cm5/configuration.nix b/hosts/uconsole-cm5/configuration.nix index d726ed6..f31b24f 100644 --- a/hosts/uconsole-cm5/configuration.nix +++ b/hosts/uconsole-cm5/configuration.nix @@ -35,7 +35,6 @@ }; # Password file for gortium (merges with users/gortium/default.nix) - users.users.gortium.passwordFile = config.age.secrets.gortium_password.path; # WiFi via NetworkManager + secret agenix networking.networkmanager.enable = true; diff --git a/users/gortium/gortium.nix b/users/gortium/gortium.nix index 4dfa89a..693c95e 100644 --- a/users/gortium/gortium.nix +++ b/users/gortium/gortium.nix @@ -11,6 +11,7 @@ ]; shell = pkgs.zsh; openssh.authorizedKeys.keys = [ + passwordFile = config.age.secrets.gortium_password.path; keys.users.gortium.main ]; }; From a6d88f2d41a554377fd4d0219e0f757463de9d1a Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Sun, 14 Jun 2026 21:57:44 -0400 Subject: [PATCH 28/30] Moved user ai-worker --- users/{ => ai-worker}/ai-worker.nix | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename users/{ => ai-worker}/ai-worker.nix (100%) diff --git a/users/ai-worker.nix b/users/ai-worker/ai-worker.nix similarity index 100% rename from users/ai-worker.nix rename to users/ai-worker/ai-worker.nix From bd283de3508f3ee40ca816a5819f99efd69ec269 Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Sun, 14 Jun 2026 21:58:57 -0400 Subject: [PATCH 29/30] fix: place passwordFile at correct attrset level in gortium.nix --- users/gortium/gortium.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/users/gortium/gortium.nix b/users/gortium/gortium.nix index 693c95e..b94375b 100644 --- a/users/gortium/gortium.nix +++ b/users/gortium/gortium.nix @@ -10,8 +10,8 @@ nh ]; shell = pkgs.zsh; - openssh.authorizedKeys.keys = [ passwordFile = config.age.secrets.gortium_password.path; + openssh.authorizedKeys.keys = [ keys.users.gortium.main ]; }; From bd8b1c564e2fcd1e91d952f8d76fabbf5555a81c Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Mon, 15 Jun 2026 10:55:40 -0400 Subject: [PATCH 30/30] feat: add reusable wireguard-client NixOS module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - modules/nixos/services/wireguard-client.nix — optional module under gortium.wireguard-client namespace with enable, vpnIp, privateKeyFile, and presharedKeyFile options - Added to lazyworkhorse, cyt-pi, and uconsoleBaseModules (covers both uconsole-cm5 toplevel and SD image) - Migrated lazyworkhorse from inline networking.wireguard to module - Split-tunnel: allowedIPs = [ "10.8.0.0/24" ] Usage in a host config: gortium.wireguard-client = { enable = true; vpnIp = "10.8.0.X/24"; privateKeyFile = config.age.secrets.wireguard_private_key.path; presharedKeyFile = config.age.secrets.wireguard_preshared_key.path; }; --- flake.nix | 3 ++ hosts/lazyworkhorse/configuration.nix | 24 +++------ modules/nixos/services/wireguard-client.nix | 54 +++++++++++++++++++++ 3 files changed, 63 insertions(+), 18 deletions(-) create mode 100644 modules/nixos/services/wireguard-client.nix diff --git a/flake.nix b/flake.nix index 964f0b1..6cf5394 100644 --- a/flake.nix +++ b/flake.nix @@ -112,6 +112,7 @@ agenix.nixosModules.default ./hosts/uconsole-cm5/configuration.nix ./hosts/uconsole-cm5/hardware-configuration.nix + ./modules/nixos/services/wireguard-client.nix ./users/gortium/gortium.nix ./users/ai-worker/ai-worker.nix ]; @@ -133,6 +134,7 @@ ./hosts/lazyworkhorse/hardware-configuration.nix ./modules/nixos/filesystem/hoardingcow-mount.nix ./modules/nixos/services/docker_manager.nix + ./modules/nixos/services/wireguard-client.nix ./modules/nixos/services/ollama_init_custom_models.nix ./modules/nixos/security/ai-worker-restricted.nix ./users/gortium/gortium.nix @@ -151,6 +153,7 @@ } ./hosts/cyt-pi/configuration.nix ./hosts/cyt-pi/hardware-configuration.nix + ./modules/nixos/services/wireguard-client.nix ./users/gortium/gortium.nix ]; }; diff --git a/hosts/lazyworkhorse/configuration.nix b/hosts/lazyworkhorse/configuration.nix index fe7737a..a5e61e2 100644 --- a/hosts/lazyworkhorse/configuration.nix +++ b/hosts/lazyworkhorse/configuration.nix @@ -49,24 +49,12 @@ networking.networkmanager.enable = true; # Easiest to use and most distros use this by default. networking.hostId = "deadbeef"; - # WireGuard VPN client -- always up, connects to wg-easy server - # Create age-encrypted secrets before deploying (run on the host): - # echo -n "" | agenix -e secrets/wireguard_private_key.age - # echo -n "" | agenix -e secrets/wireguard_preshared_key.age - networking.wireguard.interfaces = { - wg0 = { - ips = [ "10.8.0.3/24" ]; - privateKeyFile = config.age.secrets.wireguard_private_key.path; - peers = [ - { - publicKey = "rY9zII3AOm8rog2rv02PyA3Bq7zdvTOGkZapfCV1DkE="; - presharedKeyFile = config.age.secrets.wireguard_preshared_key.path; - allowedIPs = [ "10.8.0.0/24" ]; - endpoint = "vpn.lazyworkhorse.net:51820"; - persistentKeepalive = 25; - } - ]; - }; + # WireGuard VPN client -- module, always up, connects to wg-easy server + gortium.wireguard-client = { + enable = true; + vpnIp = "10.8.0.3/24"; + privateKeyFile = config.age.secrets.wireguard_private_key.path; + presharedKeyFile = config.age.secrets.wireguard_preshared_key.path; }; # Set your time zone. diff --git a/modules/nixos/services/wireguard-client.nix b/modules/nixos/services/wireguard-client.nix new file mode 100644 index 0000000..0ed3951 --- /dev/null +++ b/modules/nixos/services/wireguard-client.nix @@ -0,0 +1,54 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.gortium.wireguard-client; +in +{ + ##### Options ##### + options.gortium.wireguard-client = { + enable = mkEnableOption "WireGuard VPN client to lazyworkhorse VPN server"; + + vpnIp = mkOption { + type = types.str; + description = "Assigned VPN IP with CIDR, e.g. \"10.8.0.4/24\""; + example = "10.8.0.4/24"; + }; + + privateKeyFile = mkOption { + type = types.path; + description = "Path to the WireGuard private key (age-encrypted, via agenix)"; + }; + + presharedKeyFile = mkOption { + type = types.nullOr types.path; + default = null; + description = "Path to the WireGuard preshared key (optional, age-encrypted)"; + }; + }; + + ##### Config ##### + config = mkIf cfg.enable { + networking.wireguard.interfaces = { + wg0 = { + ips = [ cfg.vpnIp ]; + privateKeyFile = cfg.privateKeyFile; + + peers = [ + { + # Server public key (lazyworkhorse wg-easy) + publicKey = "rY9zII3AOm8rog2rv02PyA3Bq7zdvTOGkZapfCV1DkE="; + presharedKeyFile = cfg.presharedKeyFile; + # Split-tunnel: only route the VPN subnet + allowedIPs = [ "10.8.0.0/24" ]; + endpoint = "vpn.lazyworkhorse.net:51820"; + persistentKeepalive = 25; + } + ]; + }; + }; + + environment.systemPackages = with pkgs; [ wireguard-tools ]; + }; +}