# Migrating an existing NixOS machine to Nomarchy (no reinstall)

If your machine already runs NixOS, you do **not** need the installer or a
reformat to adopt Nomarchy. Nomarchy is a flake; "installing" it onto an
existing NixOS box means pointing `nixos-rebuild` at a Nomarchy‑based flake
that reuses your current `hardware-configuration.nix`. Nothing repartitions,
and your `/home` is never written to by an activation.

This guide is written generically, with **TuringMachine** — a Lenovo AMD
Ryzen 7840U / Radeon 780M laptop, LUKS + btrfs, systemd‑boot — as the
concrete worked example. Substitute your own values where called out.

> **The promise:** every step below is reversible. You keep three
> independent rollback nets (NixOS generations, a btrfs snapshot, and the
> fact that `nixos-rebuild test` never changes the boot default), and your
> files live on a separate subvolume that no config switch touches.

---

## 0. Is your machine a good candidate?

Migration is cleanest when your machine already matches Nomarchy's
assumptions. Check each:

| Nomarchy expects | Check it | If it differs |
|---|---|---|
| **systemd‑boot** | `bootctl status` → "Product: systemd‑boot" | GRUB works too; keep your loader config in `system.nix` |
| **btrfs** with `@`/`@home` subvolumes | `findmnt -t btrfs` | ext4/xfs boot fine — you just don't get snapshots |
| `@snapshots` + `@home-snapshots` subvols | in `findmnt` output | snapper features need them; create them or skip snapshots |
| **LUKS** (optional, themed prompt) | `lsblk -f` shows `crypto_LUKS` | none — LUKS is optional |
| Already a **flake** config | `test -f /etc/nixos/flake.nix` | fine either way; you'll write a fresh flake regardless |

**Installer vs migration snapshot layout.** A fresh Nomarchy install
(disko) creates a top-level `@snapshots` subvolume mounted at
`/.snapshots`, then a first-boot oneshot makes a *nested*
`/home/.snapshots` under `@home` for snapper's home timeline — it does
**not** create a separate top-level `@home-snapshots`. Migration machines
(e.g. TuringMachine) may already use top-level `@snapshots` **and**
`@home-snapshots`; that is fine. Snapper only needs a `.snapshots` path
under each tracked subvolume (`/` and `/home`), so either layout works —
reuse what you have, or create the missing pieces if you want snapper
without reformatting.

TuringMachine matches all of these, including the `@snapshots` /
`@home-snapshots` subvolumes — so snapper works with zero disk work.

**Version note.** Nomarchy pins `nixos-26.05`. If you're on an older release
(TuringMachine is on **25.11**), the migration folds a one‑release upgrade
into the switch. That's normal and supported — read the
[NixOS 26.05 release notes](https://nixos.org/manual/nixos/stable/release-notes)
for option/package renames, and lean on generations if something regresses.

---

## 1. The two rules that protect your data

1. **Never bump `system.stateVersion`.** It is an on‑disk/service
   compatibility marker tied to when the machine was *first installed* — not
   the nixpkgs version. Nomarchy's template ships `26.05`; you **must** change
   it back to your machine's original value. Find yours:

   ```console
   $ nixos-option system.stateVersion   # or: nix eval .#nixosConfigurations.<host>.config.system.stateVersion
   "24.11"
   ```

   *(TuringMachine: `24.11`.)*

2. **`/home` is never touched by an activation.** A `nixos-rebuild switch`
   swaps the system generation; your data subvolume is untouched. The Phase 0
   snapshot is belt‑and‑suspenders, not a necessity for file safety.

---

## Phase 0 — Safety net (nothing changes yet)

```bash
# Read-only btrfs snapshots of root and home — instant rollback targets.
sudo btrfs subvolume snapshot -r /       /.snapshots/pre-nomarchy-root
sudo btrfs subvolume snapshot -r /home   /home/.snapshots/pre-nomarchy-home

# Freeze your current config as a clean git baseline.
cd /etc/nixos && git add -A && git commit -m "pre-nomarchy baseline" || true
```

You are currently booted in a known‑good generation; it remains in the
systemd‑boot menu throughout. Worst case at any later step: reboot and pick
it.

---

## Phase 1 — Build the Nomarchy flake alongside (no switch)

Stand the new config up in a working directory and **build** it without
activating. This is the real safety line: iterate here until it builds green
before anything touches the running system.

```bash
git clone https://git.bemagri.xyz/bernardo/nomarchy.git ~/nomarchy-migrate
cd ~/nomarchy-migrate
# Or start from the downstream template:
#   nix flake init -t "git+https://git.bemagri.xyz/bernardo/nomarchy.git?ref=v1"
#   (produces flake.nix/system.nix/home.nix/…)
```

A Nomarchy downstream flake owns exactly five files. Assemble them:

### `hardware-configuration.nix` — reuse yours unchanged

Copy your **existing** hardware config in verbatim. This is what preserves
your disks, LUKS, btrfs subvolumes and swap — the reason no reinstall is
needed.

```bash
cp /etc/nixos/hosts/TuringMachine/hardware-configuration.nix ./hardware-configuration.nix
```

### `flake.nix` — one `mkFlake` call (from the template)

```nix
{
  description = "TuringMachine — Nomarchy";
  inputs.nomarchy.url = "git+https://git.bemagri.xyz/bernardo/nomarchy.git?ref=v1";

  outputs = { nomarchy, ... }:
    nomarchy.lib.mkFlake {
      src = ./.;
      username = "bernardo";                 # <- your login name
      # Optional nixos-hardware profile(s) for your model. For an AMD laptop:
      #   hardwareProfile = [ "common-cpu-amd-pstate" "common-gpu-amd" "common-pc-laptop-ssd" ];
      # Names: https://github.com/NixOS/nixos-hardware  (verify before use)
      # Full hardware story (firmware, fingerprint, unsupported machines):
      #   docs/HARDWARE.md in the Nomarchy repo
    };
}
```

### `system.nix` — machine specifics + your decisions

This is where your three migration decisions land: **PPD power (no
ryzenadj)**, **no Secure Boot**, and the **stateVersion override**.

```nix
{ pkgs, username, ... }:

{
  # Plain systemd-boot — no lanzaboote / Secure Boot.
  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;

  networking.hostName = "TuringMachine";
  time.timeZone = "Europe/London";           # your zone
  i18n.defaultLocale = "en_US.UTF-8";

  users.users.${username} = {
    isNormalUser = true;
    extraGroups = [ "wheel" "networkmanager" "video" "input" ];
  };

  # ── Power: Nomarchy's PPD (drops all custom ryzenadj/TLP tuning) ──────
  nomarchy.system.power = {
    enable = true;
    backend = "ppd";                         # power-profiles-daemon
    laptop = true;
    batteryChargeLimit = 80;                 # optional longevity cap
  };

  # ── AMD 7840U / Radeon 780M ──────────────────────────────────────────
  nomarchy.hardware.amd.enable = true;       # amd-pstate + radeonsi VA-API
  # nomarchy.hardware.amd.rocm.enable = true; # opt-in GPU compute (multi-GB)

  # CRITICAL: keep your ORIGINAL install's value — never Nomarchy's 26.05.
  system.stateVersion = "24.11";
}
```

> **Dropped on purpose (decisions 1 & 2):** your old
> `modules/services/power-management.nix` ryzenadj stack, the `lanzaboote`
> input, and the `power-max`/`power-stealth` scripts. PPD's
> performance/balanced/power‑saver profiles (switchable from the Waybar
> battery/profile icons and `nomarchy-menu`) replace them.

### `home.nix` — your apps on top of Nomarchy's desktop

Start from the template's `home.nix` (it ships the default app set) and add
your personal packages/config. Carry over anything you still want (e.g. your
emacs setup).

```nix
{ pkgs, lib, ... }:

{
  # Nomarchy hardcodes home.stateVersion = "26.05". Moving home-manager's
  # stateVersion is low-risk, but if you want to pin your original:
  home.stateVersion = lib.mkForce "24.11";

  home.packages = with pkgs; [
    # your extras — e.g. emacs, language toolchains, …
  ];
}
```

### `theme-state.json`

Copy the template's `theme-state.json` (or let `nomarchy-menu theme` write
it after the switch). Your old `nomarchy-state.nix` prototype (schema
`nomarchy.theme = "nord"` …) is **retired** — the current distro uses this
JSON. `nord` is a shipped Nomarchy theme, so you lose nothing.

### The build gate

```bash
nixos-rebuild build --flake ~/nomarchy-migrate#default
```

Zero activation — this only evaluates and builds the system closure. Fix any
eval/build error here, in isolation, before touching the running machine.
Expect to resolve a few 25.11→26.05 option renames.

---

## Phase 2 — Reversible activation

```bash
# Activates now, but does NOT become the boot default. If the session
# breaks, REBOOT and you are back in your old generation, untouched.
sudo nixos-rebuild test --flake ~/nomarchy-migrate#default

# Bring the desktop (home-manager) up:
home-manager switch --flake ~/nomarchy-migrate#bernardo
```

Log into Hyprland and sanity‑check: Waybar renders, `SUPER+M` opens the
menu, theming is coherent, `SUPER+?` shows the cheatsheet. Confirm the
machine‑specific things you care about still work — suspend/hibernate, the
AMD GPU (`vainfo` → radeonsi), display brightness.

If anything is wrong: **reboot → old generation.** Nothing is committed as
default yet.

---

## Phase 3 — Reconcile

- **Power:** verify `powerprofilesctl get` works and the Waybar battery /
  power‑profile icons open the power menu. Your ryzenadj scripts are gone;
  if you miss a specific TDP behaviour, that's a follow‑up, not a blocker.
- **Theme:** `nomarchy-menu theme` → pick **nord** (writes
  `theme-state.json`).
- **Snapshots:** `nomarchy-menu` → System → Snapshots should see your
  existing `@snapshots` subvolume.
- **Secrets/services:** if you relied on agenix‑managed secrets for a
  service, layer `agenix` back into `system.nix` as a machine‑specific
  import (Nomarchy doesn't manage secrets). If you don't need them, leave
  them out — this is a full cutover.

---

## Phase 4 — Cutover

Once a test boot is solid:

```bash
# Move the flake to its canonical home and make it the boot default.
mv ~/nomarchy-migrate ~/.nomarchy
sudo nixos-rebuild switch --flake ~/.nomarchy#default
home-manager switch --flake ~/.nomarchy#bernardo

# Point /etc/nixos at the flake (optional but conventional).
sudo mv /etc/nixos /etc/nixos.pre-nomarchy
sudo ln -s ~/.nomarchy /etc/nixos
```

From here you're on the standard Nomarchy update flow: `sys-update` (lock +
system) then `home-update` (desktop) — always in that order (a lock bump
before the home switch, or desktop changes are skipped against the old
lock).

---

## Rollback, at any point

| Net | How |
|---|---|
| **NixOS generation** | Reboot → pick the previous entry in the systemd‑boot menu. |
| **`nixos-rebuild test`** | Never sets the boot default; a reboot reverts it. |
| **btrfs snapshot** | Restore `/.snapshots/pre-nomarchy-root` (see `docs/RECOVERY.md`). |
| **git baseline** | `/etc/nixos.pre-nomarchy` (and the pre‑nomarchy commit) is your old config verbatim. |

`/home` is untouched by all of the above.

---

## Post‑migration cleanup (once you're confident)

- Delete the safety snapshots: `sudo btrfs subvolume delete /.snapshots/pre-nomarchy-root` (and the home one).
- Remove `/etc/nixos.pre-nomarchy` and the old per‑host modules you cut
  (ryzenadj power‑management, lanzaboote, the `nomarchy-state.nix`
  prototype).
- Prune old generations: `sudo nix-collect-garbage -d`.

---

## TuringMachine — the decisions, at a glance

| Item | Choice |
|---|---|
| Power | Nomarchy **PPD** (`backend = "ppd"`); **all ryzenadj/TLP tuning dropped** |
| Secure Boot | **Off** — plain systemd‑boot, `lanzaboote` dropped |
| Scope | **Full cutover** to Nomarchy's structure |
| `system.stateVersion` | **`24.11`** (preserved from original install) |
| Hardware | `nomarchy.hardware.amd.enable = true` (7840U / Radeon 780M) |
| Bootloader | systemd‑boot (unchanged — already matched) |
| Filesystem | LUKS + btrfs, existing subvolumes reused (incl. snapshot subvols) |
