refactor: make nanuqsaurus module-based; keep btrfs install profile

This commit is contained in:
randogoth 2026-02-04 20:53:05 +02:00
parent e640b43b2f
commit bb138278f1
13 changed files with 218 additions and 173 deletions

View file

@ -1,13 +1,19 @@
> under heavy development > under heavy development
## Install in place ## Adopt on an existing NixOS install (recommended)
Use a small local wrapper flake that imports this repos profile module and keeps
your machines `hardware-configuration.nix` for mounts/boot:
- `docs/adopt.md`
## Fresh install (wipes disk, uses disko)
``` ```
sudo nixos-rebuild switch --flake "git+https://codeberg.org/randogoth/nanuqsaurus.git#nanuqsaurus" sudo nix --experimental-features "nix-command flakes" \
run github:nix-community/disko/latest#disko-install -- \
--mode format \
--flake "git+https://codeberg.org/randogoth/nanuqsaurus.git#nanuqsaurus-btrfs" \
--disk main /dev/disk/by-id/<your-disk> \
--mount-point /mnt
``` ```
## Install to a mounted target root (/mnt)
```
sudo nixos-install --root /mnt --flake "git+https://codeberg.org/randogoth/nanuqsaurus.git#nanuqsaurus"
```

64
docs/adopt.md Normal file
View file

@ -0,0 +1,64 @@
# Adopt Nanuqsaurus on an existing NixOS install (no repartitioning)
This repo intentionally does **not** ship a “one size fits all” `nixosConfiguration` for installed systems.
Disk layouts, filesystems, initrd modules, and bootloader details are machine-specific and live in your
local `hardware-configuration.nix`.
The recommended workflow is to create a **small local wrapper flake** that:
- keeps your machines `hardware-configuration.nix` as the source of truth for mounts/boot,
- imports `nanuqsaurus` as a feature/profile module from its URL,
- keeps your personal changes in your own repo (or `/etc/nixos`).
## 1) Create a wrapper flake in `/etc/nixos`
On the target machine:
1. Ensure you have a `hardware-configuration.nix` (generated by `nixos-generate-config`).
2. Create `/etc/nixos/flake.nix` like this (adjust `hostName` and `stateVersion`):
```nix
{
description = "Local wrapper for the nanuqsaurus profile";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
nanuqsaurus.url = "git+https://codeberg.org/randogoth/nanuqsaurus.git";
nanuqsaurus.inputs.nixpkgs.follows = "nixpkgs";
};
outputs =
{ self, nixpkgs, nanuqsaurus, ... }:
{
nixosConfigurations.my-host = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
./hardware-configuration.nix
nanuqsaurus.nixosModules.nanuqsaurus
# Your local overrides/customizations:
({ ... }: {
# Optional: change the default admin username ("admin")
nanuqsaurus.admin.username = "admin";
networking.hostName = "my-host";
system.stateVersion = "25.11";
})
];
};
};
}
```
## 2) Switch to it
```bash
sudo nixos-rebuild switch --flake /etc/nixos#my-host
```
## Updating later
- If you keep `nanuqsaurus.url` pointing at the repo, you can update with:
- `nix flake update` (in `/etc/nixos`), then
- `sudo nixos-rebuild switch --flake /etc/nixos#my-host`
- Keep all your machine-specific changes in the wrapper flake (additional modules, packages, services, etc.).

View file

@ -13,20 +13,28 @@ Pick a stable disk path (prefer /dev/disk/by-id/*) and run:
--disk main /dev/disk/by-id/<your-disk> \ --disk main /dev/disk/by-id/<your-disk> \
--mount-point /mnt --mount-point /mnt
Adopt an existing NixOS install (no repartition)
-----------------------------------------------
Create a small local wrapper flake that imports this repo as a module and keeps
your machines `hardware-configuration.nix` for mounts/boot.
See: docs/adopt.md (on the custom ISO: `/etc/nixos/docs/adopt.md`)
ISO shortcut ISO shortcut
------------ ------------
If you are using the custom ISO from this repo, it embeds the flake at /etc/nixos. If you are using the custom ISO from this repo, it embeds the flake at /etc/nixos.
You can run the wrapper script (defaults: DISK=/dev/vda, TARGET_HOST=nanuqsaurus): You can run the wrapper script (defaults: DISK=/dev/vda, TARGET_HOST=nanuqsaurus-btrfs):
sudo /etc/nixos/scripts/install-btrfs.sh sudo /etc/nixos/scripts/install-btrfs.sh
Optionally set DISK, TARGET_HOST, and FLAKE: Optionally set DISK, TARGET_HOST, and FLAKE:
sudo DISK=/dev/disk/by-id/<your-disk> TARGET_HOST=nanuqsaurus \ sudo DISK=/dev/disk/by-id/<your-disk> TARGET_HOST=nanuqsaurus-btrfs \
FLAKE="github:<owner>/<repo>" \ FLAKE="git+https://codeberg.org/<owner>/<repo>.git" \
/etc/nixos/scripts/install-btrfs.sh /etc/nixos/scripts/install-btrfs.sh

View file

@ -23,25 +23,24 @@
inputs@{ self, nixpkgs, ... }: inputs@{ self, nixpkgs, ... }:
let let
lib = nixpkgs.lib; lib = nixpkgs.lib;
hostFiles = builtins.attrNames (builtins.readDir ./hosts);
hostNames = lib.filter (
name: lib.hasSuffix ".nix" name && !(lib.hasSuffix "-hardware.nix" name) && name != "iso.nix"
) hostFiles;
mkHost =
name:
lib.nixosSystem {
system = "x86_64-linux";
specialArgs = { inherit inputs; };
modules = [ (./hosts + "/${name}.nix") ];
};
in in
{ {
nixosConfigurations = lib.genAttrs (map (lib.removeSuffix ".nix") hostNames) mkHost // { nixosModules.nanuqsaurus = import ./modules/profile/nanuqsaurus.nix { inherit inputs; };
nixosConfigurations = {
# Live installer ISO (used to bootstrap installs).
installer = nixpkgs.lib.nixosSystem { installer = nixpkgs.lib.nixosSystem {
system = "x86_64-linux"; system = "x86_64-linux";
specialArgs = { inherit inputs; }; specialArgs = { inherit inputs; };
modules = [ ./hosts/iso.nix ]; modules = [ ./hosts/iso.nix ];
}; };
# Fresh-install profile that includes disko partitioning/layout.
nanuqsaurus-btrfs = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
specialArgs = { inherit inputs; };
modules = [ ./hosts/nanuqsaurus-btrfs.nix ];
};
}; };
packages.x86_64-linux.install-iso = self.nixosConfigurations.installer.config.system.build.isoImage; packages.x86_64-linux.install-iso = self.nixosConfigurations.installer.config.system.build.isoImage;

View file

@ -9,23 +9,8 @@
{ {
imports = [ imports = [
inputs.disko.nixosModules.disko inputs.disko.nixosModules.disko
inputs.lix-module.nixosModules.lixFromNixpkgs (import ../modules/profile/nanuqsaurus.nix { inherit inputs; })
inputs.nix-index-database.nixosModules.nix-index
inputs.nix-flatpak.nixosModules.nix-flatpak
../modules/system/flatpak.nix
../modules/system/base.nix
../modules/system/disko-btrfs.nix ../modules/system/disko-btrfs.nix
../modules/system/packages.nix
../modules/system/shell.nix
../modules/system/home-manager-skel.nix
../modules/system/fonts.nix
../modules/system/printer.nix
../modules/desktop/desktop-entries.nix
../modules/desktop/file-manager.nix
../modules/desktop/gnome-minimal.nix
../modules/development/flox.nix
../modules/users/admin.nix
./nanuqsaurus-hardware.nix
]; ];
networking.hostName = "nanuqsaurus"; networking.hostName = "nanuqsaurus";

View file

@ -1,74 +0,0 @@
{
config,
pkgs,
lib,
inputs,
...
}:
{
imports = [
inputs.lix-module.nixosModules.lixFromNixpkgs
inputs.nix-index-database.nixosModules.nix-index
inputs.nix-flatpak.nixosModules.nix-flatpak
../modules/system/flatpak.nix
../modules/system/base.nix
../modules/system/packages.nix
../modules/system/shell.nix
../modules/system/home-manager-skel.nix
../modules/system/fonts.nix
../modules/system/printer.nix
../modules/desktop/desktop-entries.nix
../modules/desktop/file-manager.nix
../modules/desktop/gnome-minimal.nix
../modules/development/flox.nix
../modules/users/admin.nix
];
networking.hostName = "nanuqsaurus";
# Minimal defaults for adopting an existing disk layout.
# Override these in a site-local host module if your layout differs.
boot.initrd.availableKernelModules = lib.mkDefault [ "ahci" "xhci_pci" "virtio_pci" "sr_mod" "virtio_blk" ];
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
fileSystems."/" = lib.mkDefault {
device = "/dev/disk/by-partlabel/disk-main-nixos";
fsType = "btrfs";
options = [
"x-initrd.mount"
"compress=zstd"
"subvol=root"
];
};
fileSystems."/home" = lib.mkDefault {
device = "/dev/disk/by-partlabel/disk-main-nixos";
fsType = "btrfs";
options = [
"compress=zstd"
"subvol=home"
];
};
fileSystems."/nix" = lib.mkDefault {
device = "/dev/disk/by-partlabel/disk-main-nixos";
fsType = "btrfs";
options = [
"x-initrd.mount"
"compress=zstd"
"subvol=nix"
];
};
fileSystems."/boot" = lib.mkDefault {
device = "/dev/disk/by-partlabel/disk-main-ESP";
fsType = "vfat";
options = [
"fmask=0022"
"dmask=0022"
];
};
system.stateVersion = "25.11";
}

View file

@ -0,0 +1,21 @@
{ inputs }:
{ ... }:
{
imports = [
inputs.lix-module.nixosModules.lixFromNixpkgs
inputs.nix-index-database.nixosModules.nix-index
inputs.nix-flatpak.nixosModules.nix-flatpak
../system/flatpak.nix
../system/base.nix
../system/packages.nix
../system/shell.nix
../system/home-manager-skel.nix
../system/fonts.nix
../system/printer.nix
../desktop/desktop-entries.nix
../desktop/file-manager.nix
../desktop/gnome-minimal.nix
../development/flox.nix
../users/admin.nix
];
}

View file

@ -1,8 +1,15 @@
{ ... }: {
config,
lib,
...
}:
let let
flakeText = (builtins.readFile ../../templates/home-flake.nix); adminUser = lib.attrByPath [ "nanuqsaurus" "admin" "username" ] "admin" config;
homeText = (builtins.readFile ../../templates/home-home.nix); substitute = text: lib.replaceStrings [ "@ADMIN_USER@" ] [ adminUser ] text;
flakeText = substitute (builtins.readFile ../../templates/home-flake.nix);
homeText = substitute (builtins.readFile ../../templates/home-home.nix);
in in
{ {
environment.etc = { environment.etc = {

View file

@ -1,57 +1,79 @@
{ lib, pkgs, ... }:
{ {
users.groups = { config,
docker = { }; lib,
podman = { }; pkgs,
...
}:
let
cfg = config.nanuqsaurus.admin;
in
{
options.nanuqsaurus.admin = {
username = lib.mkOption {
type = lib.types.str;
default = "admin";
description = "Primary admin user account name.";
};
}; };
users.users.admin = { config = {
isNormalUser = true; users.groups = {
extraGroups = [ docker = { };
"wheel" podman = { };
"networkmanager"
"podman"
"docker"
"libvirtd"
"lpadmin"
];
hashedPassword = "$6$HrwFoHtYRwiTZsYo$gKNOvkQhjalczOLgoTXvVu1MaihYP4BdBnVpWkdoAf.5MAiV2mMPRibYyGv9ti1Q63AhGK7n4wOPjAU0O74mK0";
subGidRanges = [
{
count = 65536;
startGid = 100000;
}
];
subUidRanges = [
{
count = 65536;
startUid = 100000;
}
];
};
security.sudo.wheelNeedsPassword = lib.mkDefault true;
# Bootstrap Home Manager for admin on first login (per-user, standalone)
systemd.user.services.hm-bootstrap = {
description = "One-time Home Manager bootstrap for admin";
unitConfig = {
ConditionPathExists = "!%h/.config/home-manager/.hm_bootstrap_done";
After = [ "graphical-session.target" ];
Wants = [ "graphical-session.target" ];
PartOf = [ "graphical-session.target" ];
}; };
serviceConfig = {
Type = "simple"; users.users.${cfg.username} = {
TimeoutStartSec = "30min"; isNormalUser = true;
Environment = [ "PATH=/run/current-system/sw/bin:/etc/profiles/per-user/%u/bin" ]; extraGroups = [
StandardOutput = "journal"; "wheel"
StandardError = "journal"; "networkmanager"
ExecStart = pkgs.writeShellScript "hm-bootstrap.sh" ( "podman"
builtins.readFile ../../scripts/hm-bootstrap.sh "docker"
); "libvirtd"
"lpadmin"
];
hashedPassword = "$6$HrwFoHtYRwiTZsYo$gKNOvkQhjalczOLgoTXvVu1MaihYP4BdBnVpWkdoAf.5MAiV2mMPRibYyGv9ti1Q63AhGK7n4wOPjAU0O74mK0";
subGidRanges = [
{
count = 65536;
startGid = 100000;
}
];
subUidRanges = [
{
count = 65536;
startUid = 100000;
}
];
};
security.sudo.wheelNeedsPassword = lib.mkDefault true;
# Bootstrap Home Manager for the primary admin user on first login (per-user, standalone)
systemd.user.services.hm-bootstrap = {
description = "One-time Home Manager bootstrap";
unitConfig = {
ConditionPathExists = "!%h/.config/home-manager/.hm_bootstrap_done";
After = [ "graphical-session.target" ];
Wants = [ "graphical-session.target" ];
PartOf = [ "graphical-session.target" ];
};
serviceConfig = {
Type = "simple";
TimeoutStartSec = "30min";
Environment = [
"PATH=/run/current-system/sw/bin:/etc/profiles/per-user/%u/bin"
"NANUQSAURUS_ADMIN_USER=${cfg.username}"
"NANUQSAURUS_HM_TARGET=${cfg.username}"
];
StandardOutput = "journal";
StandardError = "journal";
ExecStart = pkgs.writeShellScript "hm-bootstrap.sh" (
builtins.readFile ../../scripts/hm-bootstrap.sh
);
};
wantedBy = [ "graphical-session.target" ];
}; };
wantedBy = [ "graphical-session.target" ];
}; };
} }

View file

@ -2,9 +2,12 @@
set -euo pipefail set -euo pipefail
UID="$(id -u)" UID="$(id -u)"
USER_NAME="$(id -un)"
USER_BUS="/run/user/$UID/bus" USER_BUS="/run/user/$UID/bus"
HM_DIR="$HOME/.config/home-manager" HM_DIR="$HOME/.config/home-manager"
SKEL_DIR="/etc/skel/.config/home-manager" SKEL_DIR="/etc/skel/.config/home-manager"
EXPECTED_USER="${NANUQSAURUS_ADMIN_USER:-}"
HM_TARGET="${NANUQSAURUS_HM_TARGET:-$USER_NAME}"
# Ensure basic PATH for user units # Ensure basic PATH for user units
export PATH="/run/current-system/sw/bin:${PATH:-}" export PATH="/run/current-system/sw/bin:${PATH:-}"
@ -79,6 +82,10 @@ trap 'notify "Bootstrap finished" "Your system is fully hydrated. It is recommen
# ---- Home Manager bootstrap ------------------------------------------------- # ---- Home Manager bootstrap -------------------------------------------------
if [[ -n "$EXPECTED_USER" && "$USER_NAME" != "$EXPECTED_USER" ]]; then
exit 0
fi
mkdir -p "$HM_DIR" mkdir -p "$HM_DIR"
for f in flake.nix home.nix; do for f in flake.nix home.nix; do
@ -88,5 +95,5 @@ for f in flake.nix home.nix; do
install -m 600 "$src" "$dst" install -m 600 "$src" "$dst"
done done
home-manager switch --flake "$HM_DIR#admin" home-manager switch --flake "$HM_DIR#$HM_TARGET"
touch "$HM_DIR/.hm_bootstrap_done" touch "$HM_DIR/.hm_bootstrap_done"

View file

@ -2,7 +2,7 @@
set -euo pipefail set -euo pipefail
# Non-interactive Btrfs installer using disko-install. # Non-interactive Btrfs installer using disko-install.
# Defaults: DISK=/dev/vda TARGET_HOST=nanuqsaurus # Defaults: DISK=/dev/vda TARGET_HOST=nanuqsaurus-btrfs
# If FLAKE is unset and /etc/nixos/flake.nix exists, it uses /etc/nixos. # If FLAKE is unset and /etc/nixos/flake.nix exists, it uses /etc/nixos.
# Otherwise, set FLAKE to a flake URI like: # Otherwise, set FLAKE to a flake URI like:
# - git+https://codeberg.org/<owner>/<repo>.git # - git+https://codeberg.org/<owner>/<repo>.git

View file

@ -1,5 +1,5 @@
{ {
description = "Home Manager configuration of admin"; description = "Home Manager configuration of @ADMIN_USER@";
inputs = { inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
@ -13,7 +13,7 @@
}; };
outputs = { nixpkgs, home-manager, nix-flatpak, ... }: { outputs = { nixpkgs, home-manager, nix-flatpak, ... }: {
homeConfigurations."admin" = home-manager.lib.homeManagerConfiguration { homeConfigurations."@ADMIN_USER@" = home-manager.lib.homeManagerConfiguration {
pkgs = nixpkgs.legacyPackages.x86_64-linux; pkgs = nixpkgs.legacyPackages.x86_64-linux;
modules = [ modules = [
nix-flatpak.homeManagerModules.nix-flatpak nix-flatpak.homeManagerModules.nix-flatpak

View file

@ -6,8 +6,8 @@
}: }:
{ {
home.username = "admin"; home.username = "@ADMIN_USER@";
home.homeDirectory = "/home/admin"; home.homeDirectory = "/home/@ADMIN_USER@";
home.stateVersion = "25.05"; home.stateVersion = "25.05";
nixpkgs.config.allowUnfree = true; nixpkgs.config.allowUnfree = true;
@ -97,7 +97,7 @@
[no-cd] [no-cd]
switch: switch:
home-manager switch --flake ~/.config/home-manager#$USER home-manager switch --flake ~/.config/home-manager#$USER
[no-cd] [no-cd]
rebuild: rebuild: