main
  1{
  2  description = "System Config";
  3
  4  nixConfig = {
  5    extra-substituters = [
  6      "https://nixos-raspberrypi.cachix.org"
  7    ];
  8    extra-trusted-public-keys = [
  9      "nixos-raspberrypi.cachix.org-1:4iMO9LXa8BqhU+Rpg6LQKiGa2lsNh/j2oiYLNOQ5sPI="
 10    ];
 11  };
 12
 13  outputs =
 14    { self, ... }@inputs:
 15    let
 16      inherit (self) outputs;
 17      stateVersion = "24.11";
 18
 19      libx = import ./lib {
 20        inherit
 21          self
 22          inputs
 23          outputs
 24          stateVersion
 25          ;
 26      };
 27
 28      supportedSystems = [
 29        "x86_64-linux"
 30        "aarch64-linux"
 31      ];
 32      forAllSystems = inputs.nixpkgs.lib.genAttrs supportedSystems;
 33    in
 34    {
 35      githubActions = inputs.nix-github-actions.lib.mkGithubMatrix {
 36        checks = inputs.nixpkgs.lib.getAttrs [ "x86_64-linux" ] self.packages;
 37      };
 38      githubActionsMatrix = builtins.toJSON (
 39        inputs.nixpkgs.lib.mapAttrsToList
 40          (name: value: {
 41            inherit name;
 42            arch = value._module.specialArgs.system;
 43          })
 44          (
 45            inputs.nixpkgs.lib.attrsets.filterAttrs (
 46              _: config:
 47              (
 48                builtins.hasAttr "system" config._module.specialArgs && config._module.specialArgs.hostname != "foo"
 49              )
 50            ) self.nixosConfigurations
 51          )
 52      );
 53      # Standalone home configurations
 54      # FIXME set this up
 55      homeConfigurations = {
 56        # Fedora CSB workstations
 57        "vdemeest@aomi" = libx.mkHome {
 58          username = "vdemeest";
 59          hostname = "aomi";
 60          desktop = "niri";
 61        };
 62        "vdemeest@kyushu" = libx.mkHome {
 63          username = "vdemeest";
 64          hostname = "kyushu";
 65          desktop = "niri";
 66        };
 67        # headless machine
 68        "vincent@aion" = libx.mkHome {
 69          username = "vincent";
 70          hostname = "aion";
 71          system = "aarch64-linux";
 72        };
 73        "houbeb@aion" = libx.mkHome {
 74          username = "houbeb";
 75          hostname = "aion";
 76          system = "aarch64-linux";
 77        };
 78      };
 79      nixosConfigurations = {
 80        # Laptop for LLM workloads (unstable)
 81        okinawa = libx.mkHost {
 82          hostname = "okinawa";
 83          desktop = "niri"; # or "sway"
 84        };
 85        # Servers (unstable)
 86        sakhalin = libx.mkHost {
 87          hostname = "sakhalin";
 88        };
 89        # shikoku = libx.mkHost {
 90        #   hostname = "shikoku";
 91        # };
 92        # Servers (stable)
 93        aix = libx.mkHost {
 94          hostname = "aix";
 95          system = "aarch64-linux";
 96          hardwareType = "rpi4";
 97          pkgsInput = inputs.nixpkgs-26_05;
 98          homeInput = inputs.home-manager-26_05;
 99          agenixInput = inputs.agenix-26_05;
100        };
101        aion = libx.mkHost {
102          hostname = "aion";
103          system = "aarch64-linux";
104          pkgsInput = inputs.nixpkgs-26_05;
105          homeInput = inputs.home-manager-26_05;
106          agenixInput = inputs.agenix-26_05;
107        };
108        rhea = libx.mkHost {
109          hostname = "rhea";
110          system = "aarch64-linux";
111          pkgsInput = inputs.nixpkgs-26_05;
112          homeInput = inputs.home-manager-26_05;
113          agenixInput = inputs.agenix-26_05;
114        };
115        carthage = libx.mkHost {
116          hostname = "carthage";
117          pkgsInput = inputs.nixpkgs-26_05;
118          homeInput = inputs.home-manager-26_05;
119          agenixInput = inputs.agenix-26_05;
120        };
121      };
122
123      nixosModules = {
124        # provided modules (to be upstreamed)
125        wireguard-client = ./modules/wireguard/client.nix;
126        wireguard-server = ./modules/wireguard/server.nix;
127        govanityurl = ./modules/govanityurl;
128        gosmee = ./modules/gosmee;
129        rsync-replica = ./modules/rsync-replica;
130        microshift = ./modules/microshift;
131        harmonia = ./modules/harmonia;
132        praetorian = inputs.praetorian.nixosModules.praetorian;
133      };
134
135      # Fedora config files (no system-manager, just the useful files)
136      fedoraConfigs =
137        let
138          mkFedoraConfigs =
139            hostname:
140            let
141              pkgs = import inputs.nixpkgs { system = "x86_64-linux"; };
142              globals = import ./globals.nix {
143                inherit (inputs.nixpkgs) lib;
144                inherit hostname;
145              };
146              fedoraLibx = import ./lib/functions.nix { inherit (inputs.nixpkgs) lib; };
147            in
148            import ./systems/common/fedora-work/gen-configs.nix {
149              inherit (inputs.nixpkgs) lib;
150              inherit pkgs globals hostname;
151              libx = fedoraLibx;
152            };
153        in
154        {
155          kyushu = mkFedoraConfigs "kyushu";
156          aomi = mkFedoraConfigs "aomi";
157        };
158
159      # system-manager configurations
160      systemConfigs = {
161        nagoya = libx.mkSystemManager {
162          hostname = "nagoya";
163          system = "aarch64-linux";
164        };
165      };
166
167      images = {
168        # sdimages
169        aix =
170          (self.nixosConfigurations.aix.extendModules {
171            modules = [
172              "${inputs.nixpkgs-26_05}/nixos/modules/installer/sd-card/sd-image-aarch64.nix"
173            ];
174          }).config.system.build.sdImage;
175      };
176
177      overlays = import ./overlays { inherit inputs; };
178
179      packages = forAllSystems (
180        system:
181        let
182          pkgs = import inputs.nixpkgs {
183            system = system;
184            config.allowAliases = false;
185            overlays = [
186              self.overlays.additions
187            ];
188          };
189          skipDarwinPackages =
190            system: n:
191            if lib.strings.hasSuffix "darwin" system then !(lib.strings.hasPrefix "koff" n) else true;
192          inherit (inputs.nixpkgs) lib;
193          drvAttrs = builtins.filter (n: lib.isDerivation pkgs.${n} && skipDarwinPackages system n) (
194            builtins.attrNames (self.overlays.additions pkgs pkgs)
195          );
196        in
197        lib.listToAttrs (map (n: lib.nameValuePair n pkgs.${n}) drvAttrs)
198        // {
199          dns-zones =
200            let
201              globals = import ./globals.nix { };
202              dns = inputs.dns;
203              mkZoneFile =
204                zoneName: zoneFile:
205                pkgs.writeText "db.${zoneName}" (
206                  dns.lib.toString zoneName (import zoneFile { inherit dns globals; })
207                );
208            in
209            pkgs.runCommand "dns-zones" { } ''
210              mkdir -p $out
211              cp ${mkZoneFile "sbr.pm" ./systems/common/services/dns/sbr.pm.nix} $out/db.sbr.pm
212              cp ${mkZoneFile "home" ./systems/common/services/dns/home.nix} $out/db.home
213              cp ${mkZoneFile "vpn" ./systems/common/services/dns/vpn.nix} $out/db.vpn
214              cp ${mkZoneFile "demeester.fr" ./systems/common/services/dns/demeester.fr.nix} $out/db.demeester.fr
215              cp ${mkZoneFile "192.168.1.in-addr.arpa" ./systems/common/services/dns/192.168.1.nix} $out/db.192.168.1
216              cp ${mkZoneFile "10.100.0.in-addr.arpa" ./systems/common/services/dns/10.100.0.nix} $out/db.10.100.0
217            '';
218
219          wg-configs =
220            let
221              globals = import ./globals.nix { };
222              serverPubkey = globals.machines.carthage.net.vpn.pubkey;
223              endpoint = globals.net.vpn.endpoint;
224              mkWgConfig =
225                hostname:
226                let
227                  machine = globals.machines.${hostname};
228                  vpnIp = builtins.head machine.net.vpn.ips;
229                in
230                pkgs.writeText "wg0-${hostname}.conf" ''
231                  [Interface]
232                  Address = ${vpnIp}/32
233                  PostUp = test -f /persist/wireguard/private.key && wg set %i private-key /persist/wireguard/private.key || true
234
235                  [Peer]
236                  PublicKey = ${serverPubkey}
237                  Endpoint = ${endpoint}:51820
238                  AllowedIPs = 10.100.0.0/24
239                  PersistentKeepalive = 25
240                '';
241            in
242            pkgs.runCommand "wg-configs" { } ''
243              mkdir -p $out
244              cp ${mkWgConfig "aix"} $out/wg0-aix.conf
245            '';
246        }
247      );
248
249      checks = forAllSystems (system: {
250        pre-commit-check = inputs.pre-commit-hooks.lib.${system}.run {
251          src = ./.;
252          # Run hooks on pre-push instead of pre-commit for less intrusive workflow
253          default_stages = [
254            "manual"
255            "pre-push"
256          ];
257          hooks = {
258            # go
259            gofmt.enable = true;
260            # golangci-lint.enable = true;
261            # nix
262            deadnix.enable = true;
263            nixfmt.enable = true;
264            # statix.enable = true;
265            # python
266            ruff.enable = true;
267            # shell
268            shellcheck = {
269              enable = true;
270              excludes = [ "dots/config/zsh/.*" ]; # zsh files use zsh-specific syntax
271            };
272            # emacs lisp - basic syntax checking
273            elisp-byte-compile = {
274              enable = false; # Disabled - causes issues with missing packages in pre-push hook
275              name = "Emacs Lisp byte-compile";
276              entry =
277                let
278                  pkgs = import inputs.nixpkgs { system = system; };
279                  # Create a wrapper that runs Emacs byte-compilation
280                  elisp-check = pkgs.writeShellScript "elisp-check" ''
281                    ${pkgs.emacs}/bin/emacs --batch \
282                      --eval "(setq byte-compile-error-on-warn t)" \
283                      -f batch-byte-compile "$@"
284                  '';
285                in
286                toString elisp-check;
287              files = "\\.el$";
288              excludes = [
289                "dots/\\.config/emacs/old/.*"
290                "dots/\\.config/emacs/elpa/.*"
291                "dots/\\.config/emacs/transient/.*"
292                "dots/\\.config/emacs/eshell/.*"
293                "dots/\\.config/emacs/custom\\.el"
294                "dots/\\.config/emacs/\\.chatgpt-shell\\.el"
295                "dots/\\.config/emacs/site-lisp/.*"
296                "\\.dir-locals\\.el"
297              ];
298            };
299          };
300        };
301      });
302
303      devShells = forAllSystems (system: {
304        default =
305          let
306            pkgs = import inputs.nixpkgs {
307              system = system;
308              config.allowUnfree = true;
309            };
310          in
311          inputs.nixpkgs.legacyPackages.${system}.mkShell {
312            inherit (self.checks.${system}.pre-commit-check) shellHook;
313            buildInputs = self.checks.${system}.pre-commit-check.enabledPackages;
314            packages = [
315              pkgs.git
316              pkgs.prettier
317              pkgs.deadnix
318              pkgs.nixfmt
319              inputs.agenix.packages.${system}.default
320            ];
321            name = "home";
322            DIRENV_LOG_FORMAT = "";
323          };
324      });
325    };
326
327  inputs = {
328    # Flake for compatibility with non-flake commands
329    flake-compat = {
330      type = "github";
331      owner = "edolstra";
332      repo = "flake-compat";
333      flake = false;
334    };
335
336    buildkit-tekton = {
337      url = "github:vdemeester/buildkit-tekton";
338      inputs.nixpkgs.follows = "nixpkgs";
339    };
340    flake-parts.url = "github:hercules-ci/flake-parts";
341    go-org-readwise = {
342      url = "git+https://codeberg.org/vdemeester/go-org-readwise";
343      inputs.nixpkgs.follows = "nixpkgs";
344      inputs.flake-parts.follows = "flake-parts";
345    };
346    pass-run = {
347      url = "github:vdemeester/pass-run/v0.1.0";
348      inputs.nixpkgs.follows = "nixpkgs";
349    };
350    radian = {
351      url = "github:vdemeester/radian";
352      inputs.nixpkgs.follows = "nixpkgs";
353      inputs.flake-parts.follows = "flake-parts";
354    };
355
356    # nixpkgs
357    nixpkgs = {
358      type = "github";
359      owner = "NixOS";
360      repo = "nixpkgs";
361      ref = "nixos-unstable";
362    };
363    nixpkgs-26_05 = {
364      type = "github";
365      owner = "NixOS";
366      repo = "nixpkgs";
367      ref = "nixos-26.05";
368    };
369    nixpkgs-master.url = "github:nixos/nixpkgs/master";
370    nixpkgs-wip-consolidated = {
371      type = "github";
372      owner = "vdemeester";
373      repo = "nixpkgs";
374      ref = "wip-consolidated";
375    };
376    pre-commit-hooks.url = "github:cachix/git-hooks.nix";
377    pre-commit-hooks.inputs.nixpkgs.follows = "nixpkgs";
378    pre-commit-hooks.inputs.flake-compat.follows = "flake-compat";
379    # Home Manager
380    home-manager = {
381      type = "github";
382      owner = "nix-community";
383      repo = "home-manager";
384      inputs.nixpkgs.follows = "nixpkgs";
385    };
386    dns = {
387      url = "github:nix-community/dns.nix";
388      inputs.nixpkgs.follows = "nixpkgs";
389    };
390    home-manager-26_05 = {
391      type = "github";
392      owner = "nix-community";
393      repo = "home-manager";
394      ref = "release-26.05";
395      inputs.nixpkgs.follows = "nixpkgs-26_05";
396    };
397
398    emacs-overlay = {
399      url = "github:nix-community/emacs-overlay";
400      inputs.nixpkgs.follows = "nixpkgs";
401      inputs.nixpkgs-stable.follows = "nixpkgs-26_05";
402    };
403
404    nixos-hardware = {
405      type = "github";
406      owner = "NixOS";
407      "repo" = "nixos-hardware";
408    };
409
410    # Me :D
411    chick-group = {
412      type = "github";
413      owner = "vdemeester";
414      repo = "chick-group";
415      inputs.nixpkgs.follows = "nixpkgs";
416      inputs.flake-parts.follows = "flake-parts";
417      inputs.pre-commit-hooks.follows = "pre-commit-hooks";
418    };
419    # Red Hat
420    chapeau-rouge = {
421      type = "github";
422      owner = "vdemeester";
423      repo = "chapeau-rouge";
424      inputs.nixpkgs.follows = "nixpkgs";
425      inputs.flake-parts.follows = "flake-parts";
426      inputs.pre-commit-hooks.follows = "pre-commit-hooks";
427    };
428    agenix.url = "github:ryantm/agenix";
429    agenix.inputs.nixpkgs.follows = "nixpkgs";
430    agenix.inputs.home-manager.follows = "home-manager";
431    agenix-26_05.url = "github:ryantm/agenix";
432    agenix-26_05.inputs.nixpkgs.follows = "nixpkgs-26_05";
433    agenix-26_05.inputs.home-manager.follows = "home-manager-26_05";
434
435    nix-cachyos-kernel = {
436      url = "github:xddxdd/nix-cachyos-kernel";
437      inputs.nixpkgs.follows = "nixpkgs";
438    };
439
440    lanzaboote.url = "github:nix-community/lanzaboote";
441    lanzaboote.inputs.nixpkgs.follows = "nixpkgs";
442
443    disko.url = "github:nix-community/disko";
444    disko.inputs.nixpkgs.follows = "nixpkgs";
445
446    harmonia.url = "github:nix-community/harmonia";
447    harmonia.inputs.nixpkgs.follows = "nixpkgs";
448
449    system-manager.url = "github:numtide/system-manager";
450    system-manager.inputs.nixpkgs.follows = "nixpkgs";
451
452    nix-github-actions.url = "github:nix-community/nix-github-actions";
453    nix-github-actions.inputs.nixpkgs.follows = "nixpkgs";
454
455    nixos-raspberrypi.url = "github:nvmd/nixos-raspberrypi/develop";
456    nixos-raspberrypi.inputs.nixpkgs.follows = "nixpkgs";
457    nixos-raspberrypi.inputs.flake-compat.follows = "flake-compat";
458
459    llm-agents.url = "github:numtide/llm-agents.nix";
460    llm-agents.inputs.nixpkgs.follows = "nixpkgs";
461    llm-agents.inputs.flake-parts.follows = "flake-parts";
462
463    voxtype.url = "github:peteonrails/voxtype/main";
464    voxtype.inputs.nixpkgs.follows = "nixpkgs";
465
466    praetorian.url = "github:vdemeester/praetorian/v2.0.0-rc2";
467    praetorian.inputs.nixpkgs.follows = "nixpkgs";
468  };
469}