diff --git a/README.md b/README.md index a385861..85563bc 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,19 @@ > under heavy development -## Install in place +## Adopt on an existing NixOS install (recommended) + +Use a small local wrapper flake that imports this repo’s profile module and keeps +your machine’s `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/ \ + --mount-point /mnt ``` - -## Install to a mounted target root (/mnt) - -``` -sudo nixos-install --root /mnt --flake "git+https://codeberg.org/randogoth/nanuqsaurus.git#nanuqsaurus" -``` \ No newline at end of file diff --git a/docs/adopt.md b/docs/adopt.md new file mode 100644 index 0000000..90b4703 --- /dev/null +++ b/docs/adopt.md @@ -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 machine’s `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.). diff --git a/docs/install-help.txt b/docs/install-help.txt index 11500db..b2280a6 100644 --- a/docs/install-help.txt +++ b/docs/install-help.txt @@ -13,20 +13,28 @@ Pick a stable disk path (prefer /dev/disk/by-id/*) and run: --disk main /dev/disk/by-id/ \ --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 machine’s `hardware-configuration.nix` for mounts/boot. + +See: docs/adopt.md (on the custom ISO: `/etc/nixos/docs/adopt.md`) + ISO shortcut ------------ 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 Optionally set DISK, TARGET_HOST, and FLAKE: - sudo DISK=/dev/disk/by-id/ TARGET_HOST=nanuqsaurus \ - FLAKE="github:/" \ + sudo DISK=/dev/disk/by-id/ TARGET_HOST=nanuqsaurus-btrfs \ + FLAKE="git+https://codeberg.org//.git" \ /etc/nixos/scripts/install-btrfs.sh diff --git a/flake.nix b/flake.nix index 313eded..9a974d4 100644 --- a/flake.nix +++ b/flake.nix @@ -23,25 +23,24 @@ inputs@{ self, nixpkgs, ... }: let 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 { - 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 { system = "x86_64-linux"; specialArgs = { inherit inputs; }; 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; diff --git a/hosts/nanuqsaurus-btrfs.nix b/hosts/nanuqsaurus-btrfs.nix index 58edbff..941d58d 100644 --- a/hosts/nanuqsaurus-btrfs.nix +++ b/hosts/nanuqsaurus-btrfs.nix @@ -9,23 +9,8 @@ { imports = [ inputs.disko.nixosModules.disko - 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 + (import ../modules/profile/nanuqsaurus.nix { inherit inputs; }) ../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"; diff --git a/hosts/nanuqsaurus.nix b/hosts/nanuqsaurus.nix deleted file mode 100644 index ce9fe73..0000000 --- a/hosts/nanuqsaurus.nix +++ /dev/null @@ -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"; -} diff --git a/modules/profile/nanuqsaurus.nix b/modules/profile/nanuqsaurus.nix new file mode 100644 index 0000000..ee1f9a9 --- /dev/null +++ b/modules/profile/nanuqsaurus.nix @@ -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 + ]; +} diff --git a/modules/system/home-manager-skel.nix b/modules/system/home-manager-skel.nix index b3142c7..0a11841 100644 --- a/modules/system/home-manager-skel.nix +++ b/modules/system/home-manager-skel.nix @@ -1,8 +1,15 @@ -{ ... }: +{ + config, + lib, + ... +}: let - flakeText = (builtins.readFile ../../templates/home-flake.nix); - homeText = (builtins.readFile ../../templates/home-home.nix); + adminUser = lib.attrByPath [ "nanuqsaurus" "admin" "username" ] "admin" config; + 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 { environment.etc = { diff --git a/modules/users/admin.nix b/modules/users/admin.nix index 653af78..e3cbb03 100644 --- a/modules/users/admin.nix +++ b/modules/users/admin.nix @@ -1,57 +1,79 @@ -{ lib, pkgs, ... }: - { - users.groups = { - docker = { }; - podman = { }; + config, + lib, + 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 = { - isNormalUser = true; - extraGroups = [ - "wheel" - "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" ]; + config = { + users.groups = { + docker = { }; + podman = { }; }; - serviceConfig = { - Type = "simple"; - TimeoutStartSec = "30min"; - Environment = [ "PATH=/run/current-system/sw/bin:/etc/profiles/per-user/%u/bin" ]; - StandardOutput = "journal"; - StandardError = "journal"; - ExecStart = pkgs.writeShellScript "hm-bootstrap.sh" ( - builtins.readFile ../../scripts/hm-bootstrap.sh - ); + + users.users.${cfg.username} = { + isNormalUser = true; + extraGroups = [ + "wheel" + "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 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" ]; }; } diff --git a/scripts/hm-bootstrap.sh b/scripts/hm-bootstrap.sh index f4b2c51..8131681 100644 --- a/scripts/hm-bootstrap.sh +++ b/scripts/hm-bootstrap.sh @@ -2,9 +2,12 @@ set -euo pipefail UID="$(id -u)" +USER_NAME="$(id -un)" USER_BUS="/run/user/$UID/bus" HM_DIR="$HOME/.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 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 ------------------------------------------------- +if [[ -n "$EXPECTED_USER" && "$USER_NAME" != "$EXPECTED_USER" ]]; then + exit 0 +fi + mkdir -p "$HM_DIR" 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" done -home-manager switch --flake "$HM_DIR#admin" +home-manager switch --flake "$HM_DIR#$HM_TARGET" touch "$HM_DIR/.hm_bootstrap_done" diff --git a/scripts/install-btrfs.sh b/scripts/install-btrfs.sh index 57ce204..13cf921 100755 --- a/scripts/install-btrfs.sh +++ b/scripts/install-btrfs.sh @@ -2,7 +2,7 @@ set -euo pipefail # 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. # Otherwise, set FLAKE to a flake URI like: # - git+https://codeberg.org//.git diff --git a/templates/home-flake.nix b/templates/home-flake.nix index e7c7362..4ddf415 100644 --- a/templates/home-flake.nix +++ b/templates/home-flake.nix @@ -1,5 +1,5 @@ { - description = "Home Manager configuration of admin"; + description = "Home Manager configuration of @ADMIN_USER@"; inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; @@ -13,7 +13,7 @@ }; 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; modules = [ nix-flatpak.homeManagerModules.nix-flatpak diff --git a/templates/home-home.nix b/templates/home-home.nix index 88dc63c..bbab79d 100644 --- a/templates/home-home.nix +++ b/templates/home-home.nix @@ -6,8 +6,8 @@ }: { - home.username = "admin"; - home.homeDirectory = "/home/admin"; + home.username = "@ADMIN_USER@"; + home.homeDirectory = "/home/@ADMIN_USER@"; home.stateVersion = "25.05"; nixpkgs.config.allowUnfree = true; @@ -97,7 +97,7 @@ [no-cd] switch: - home-manager switch --flake ~/.config/home-manager#$USER +home-manager switch --flake ~/.config/home-manager#$USER [no-cd] rebuild: