Round 6 still hit a from-source cascade: every per-machine drv (units, initrd pieces, dbus config, modules-shrunk) needs its own build tools (lndir, builder.pl, kmod-dev, nuke-refs, libxslt-bin, …), one level deeper than targeted inputDerivation pins reach. Use the documented mechanism instead: system.includeBuildDependencies = true on the representative install pin. Bigger ISO, networkless installs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
285 lines
12 KiB
Nix
285 lines
12 KiB
Nix
{
|
|
description = "Nomarchy — the rock-solid reproducibility of NixOS, the polish of an opinionated desktop";
|
|
|
|
inputs = {
|
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05";
|
|
|
|
home-manager = {
|
|
url = "github:nix-community/home-manager/release-26.05";
|
|
inputs.nixpkgs.follows = "nixpkgs";
|
|
};
|
|
|
|
stylix = {
|
|
url = "github:danth/stylix";
|
|
inputs.nixpkgs.follows = "nixpkgs";
|
|
inputs.home-manager.follows = "home-manager";
|
|
};
|
|
|
|
# Pinned by Nomarchy so distro + hardware quirks are tested together
|
|
# (consumed by lib.mkFlake's hardwareProfile). Its nixpkgs input is
|
|
# only used by its own CI — follow ours to keep locks/ISO lean.
|
|
nixos-hardware = {
|
|
url = "github:NixOS/nixos-hardware/master";
|
|
inputs.nixpkgs.follows = "nixpkgs";
|
|
};
|
|
};
|
|
|
|
outputs = { self, nixpkgs, home-manager, stylix, nixos-hardware, ... }:
|
|
let
|
|
system = "x86_64-linux";
|
|
username = "nomarchy"; # reference host only; downstream picks its own
|
|
|
|
pkgs = import nixpkgs {
|
|
inherit system;
|
|
overlays = [ self.overlays.default ];
|
|
};
|
|
|
|
# The guided installer — live-ISO only (not in the overlay): it bakes
|
|
# in the downstream template, this checkout's flake.lock, and the
|
|
# source identity of this very revision so installs work offline.
|
|
gitUrl = "https://git.bemagri.xyz/bernardo/nomarchy.git";
|
|
nomarchyInstall = pkgs.callPackage ./pkgs/nomarchy-install {
|
|
templateDir = ./templates/downstream;
|
|
nomarchyLock = ./flake.lock;
|
|
hardwareModuleNames = pkgs.writeText "nixos-hardware-modules.txt"
|
|
(nixpkgs.lib.concatStringsSep "\n"
|
|
(builtins.attrNames nixos-hardware.nixosModules));
|
|
nixpkgsPath = nixpkgs.outPath;
|
|
flakeUrl = "git+${gitUrl}";
|
|
# Future updates re-resolve from the forge (original); the install
|
|
# itself resolves from the ISO store (locked = path) — fully
|
|
# offline, even from a dirty-tree ISO.
|
|
originalNode = { type = "git"; url = gitUrl; };
|
|
lockedNode = {
|
|
type = "path";
|
|
path = self.outPath;
|
|
narHash = self.narHash;
|
|
lastModified = self.lastModified or 0;
|
|
};
|
|
rev = self.rev or null;
|
|
};
|
|
in
|
|
{
|
|
# ─── Downstream API ────────────────────────────────────────────
|
|
# A user's machine flake imports these and layers its own
|
|
# system.nix / home.nix on top (see templates/downstream).
|
|
# Their theme-state.json lives in THEIR flake and is wired up via
|
|
# the `nomarchy.stateFile` option — reading it stays pure.
|
|
|
|
overlays.default = final: prev: {
|
|
nomarchy-theme-sync = final.callPackage ./pkgs/nomarchy-theme-sync {
|
|
# Presets baked into the package, so `nomarchy-theme-sync list`
|
|
# works on machines that don't check out this repo.
|
|
themesDir = ./themes;
|
|
};
|
|
};
|
|
|
|
nixosModules.nomarchy = {
|
|
imports = [ ./modules/nixos ];
|
|
nixpkgs.overlays = [ self.overlays.default ];
|
|
};
|
|
|
|
homeModules.nomarchy = {
|
|
# stylix's home module is injected here because it needs the
|
|
# flake input; modules/home/stylix.nix only configures it.
|
|
imports = [ stylix.homeModules.stylix ./modules/home ];
|
|
};
|
|
|
|
# One-call downstream wrapper — see templates/downstream/flake.nix.
|
|
# The generated flake is never hand-edited; machines live in
|
|
# system.nix / home.nix.
|
|
lib = import ./lib.nix {
|
|
inherit nixpkgs home-manager nixos-hardware;
|
|
nomarchy = self;
|
|
};
|
|
|
|
templates.default = {
|
|
path = ./templates/downstream;
|
|
description = "Nomarchy machine configuration (downstream flake)";
|
|
};
|
|
|
|
packages.${system} = {
|
|
nomarchy-theme-sync = pkgs.nomarchy-theme-sync;
|
|
nomarchy-install = nomarchyInstall;
|
|
default = pkgs.nomarchy-theme-sync;
|
|
};
|
|
|
|
# ─── Checks ────────────────────────────────────────────────────
|
|
# `nix flake check` never evaluates templates/, so exercise the
|
|
# downstream template through mkFlake directly (this bypasses the
|
|
# template's own three-line flake.nix, which only resolves once
|
|
# instantiated — everything else is covered here, including the
|
|
# hardwareProfile → nixos-hardware mapping).
|
|
checks.${system} =
|
|
let
|
|
downstream = self.lib.mkFlake {
|
|
src = ./templates/downstream;
|
|
username = "me";
|
|
hardwareProfile = "framework-13-7040-amd"; # exercises the mapping
|
|
};
|
|
in
|
|
{
|
|
downstream-template-system =
|
|
downstream.nixosConfigurations.default.config.system.build.toplevel;
|
|
downstream-template-home =
|
|
downstream.homeConfigurations.me.activationPackage;
|
|
};
|
|
|
|
# ─── Reference host ────────────────────────────────────────────
|
|
# Manually wired rather than via lib.mkFlake: the repo-root
|
|
# theme-state.json is load-bearing (live ISO + in-repo CLI dev),
|
|
# which doesn't match mkFlake's src-layout convention.
|
|
# Deliberately split rebuild paths:
|
|
# system → sudo nixos-rebuild switch --flake .#nomarchy (rare)
|
|
# desktop → home-manager switch --flake .#nomarchy (no sudo;
|
|
# this is what `nomarchy-theme-sync apply` runs)
|
|
# Theme changes never touch the system layer, so they never need
|
|
# root and never rebuild the world.
|
|
nixosConfigurations.nomarchy = nixpkgs.lib.nixosSystem {
|
|
inherit system;
|
|
specialArgs = { inherit username; };
|
|
modules = [
|
|
self.nixosModules.nomarchy
|
|
./hosts/default/configuration.nix
|
|
];
|
|
};
|
|
|
|
homeConfigurations.${username} = home-manager.lib.homeManagerConfiguration {
|
|
inherit pkgs;
|
|
modules = [
|
|
self.homeModules.nomarchy
|
|
{
|
|
# The single source of truth — pure read: the file is part
|
|
# of this flake's source.
|
|
nomarchy.stateFile = ./theme-state.json;
|
|
home = {
|
|
inherit username;
|
|
homeDirectory = "/home/${username}";
|
|
};
|
|
}
|
|
];
|
|
};
|
|
|
|
# ─── Live ISO ──────────────────────────────────────────────────
|
|
# Full desktop on a bootable stick, no installation:
|
|
# nix build .#nixosConfigurations.nomarchy-live.config.system.build.isoImage
|
|
# Test in QEMU with tools/test-live-iso.sh. See docs/TESTING.md.
|
|
nixosConfigurations.nomarchy-live = nixpkgs.lib.nixosSystem {
|
|
inherit system;
|
|
specialArgs = { inherit username; nomarchySrc = self; };
|
|
modules = [
|
|
"${nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix"
|
|
self.nixosModules.nomarchy
|
|
./hosts/live.nix
|
|
|
|
# The ISO is a sealed artifact, so the desktop is baked in via
|
|
# the HM NixOS module (the installed-system split into
|
|
# nixos-rebuild vs home-manager switch doesn't apply here —
|
|
# though the seeded ~/.nomarchy flake still allows standalone
|
|
# `home-manager switch` for theme testing).
|
|
home-manager.nixosModules.home-manager
|
|
{
|
|
home-manager = {
|
|
useGlobalPkgs = true;
|
|
useUserPackages = true;
|
|
users.${username} = {
|
|
imports = [ self.homeModules.nomarchy ];
|
|
nomarchy.stateFile = ./theme-state.json;
|
|
};
|
|
};
|
|
|
|
# The standalone CLI that `nomarchy-theme-sync apply` runs for
|
|
# theme switching, from the same pinned input — plus the
|
|
# guided installer.
|
|
environment.systemPackages = [
|
|
home-manager.packages.${system}.home-manager
|
|
nomarchyInstall
|
|
];
|
|
|
|
# Keep the locked flake inputs in the ISO store so theme
|
|
# switching on the live system works without a network: the
|
|
# lockfile's narHashes resolve against these paths instead
|
|
# of fetching from GitHub. Must be *transitive* — evaluating
|
|
# the seeded flake also fetches stylix's own inputs.
|
|
system.extraDependencies =
|
|
let
|
|
collectInputs = input:
|
|
[ input.outPath ] ++ builtins.concatMap collectInputs
|
|
(builtins.attrValues (input.inputs or { }));
|
|
in
|
|
collectInputs self ++ (
|
|
# Pre-build a system shaped like what nomarchy-install
|
|
# GENERATES (snapper, auto-login, LUKS initrd, swapfile +
|
|
# resume — not the bare template!) plus the template
|
|
# desktop, so the offline install never builds packages
|
|
# from source: a custom username/hostname then changes
|
|
# only a handful of derivations. No hardware profile —
|
|
# matches a VM install; profiled installs share most of it.
|
|
let
|
|
template = self.lib.mkFlake {
|
|
src = ./templates/downstream;
|
|
username = username;
|
|
};
|
|
representativeInstall = nixpkgs.lib.nixosSystem {
|
|
inherit system;
|
|
specialArgs = { inherit username; };
|
|
modules = [
|
|
self.nixosModules.nomarchy
|
|
{ environment.systemPackages = [ home-manager.packages.${system}.home-manager ]; }
|
|
(./templates/downstream + "/hardware-configuration.nix")
|
|
(./templates/downstream + "/system.nix")
|
|
({ lib, ... }: {
|
|
# The whole BUILD closure rides along: a real
|
|
# install rebuilds the per-machine drvs (etc,
|
|
# units, initrd, …) whose builders need tools
|
|
# from no runtime closure. This is the documented
|
|
# offline-rebuild mechanism; it is what makes the
|
|
# ISO big and the install networkless.
|
|
system.includeBuildDependencies = true;
|
|
|
|
nomarchy.system.snapper.enable = true;
|
|
nomarchy.system.greeter.autoLogin = username;
|
|
swapDevices = [{ device = "/swap/swapfile"; }];
|
|
boot.resumeDevice = "/dev/disk/by-uuid/00000000-0000-0000-0000-000000000000";
|
|
boot.kernelParams = [ "resume_offset=1" ];
|
|
boot.initrd.luks.devices.crypted.device = "/dev/disk/by-partlabel/disk-main-root";
|
|
# The real install is BTRFS — the placeholder's ext4
|
|
# would leave the btrfs-gated bits (snapper!) out of
|
|
# this pin.
|
|
fileSystems."/" = lib.mkForce {
|
|
device = "/dev/mapper/crypted";
|
|
fsType = "btrfs";
|
|
options = [ "subvol=@" "compress=zstd" "noatime" ];
|
|
};
|
|
})
|
|
];
|
|
};
|
|
in [
|
|
representativeInstall.config.system.build.toplevel
|
|
template.homeConfigurations.${username}.activationPackage
|
|
|
|
# The HM activation is rebuilt per-username in the
|
|
# installer chroot; pin its build inputs too.
|
|
template.homeConfigurations.${username}.activationPackage.inputDerivation
|
|
|
|
# …and one representative disko script: its tool closure
|
|
# (file, which, wrapper hooks, …) isn't otherwise on the
|
|
# ISO, and offline nix would try to build it from source.
|
|
# The user's actual args produce a different script drv,
|
|
# but with identical inputs — built offline in seconds.
|
|
(import "${pkgs.disko}/share/disko/cli.nix" {
|
|
inherit pkgs;
|
|
mode = "destroy,format,mount";
|
|
diskoFile = ./pkgs/nomarchy-install/disko-config.nix;
|
|
mainDrive = "/dev/vda";
|
|
withLuks = true;
|
|
swapSize = "2G";
|
|
})
|
|
]
|
|
);
|
|
}
|
|
];
|
|
};
|
|
};
|
|
}
|