Skip to content

Instantly share code, notes, and snippets.

@danielres
Last active July 18, 2025 23:20
Show Gist options
  • Save danielres/bda04ddf1ed6c540afc3d8501efc6d40 to your computer and use it in GitHub Desktop.
Save danielres/bda04ddf1ed6c540afc3d8501efc6d40 to your computer and use it in GitHub Desktop.
tuxedo-nixos-dual
# Shrink Tuxedo / and add isolated NixOS (UEFI boot-menu dual boot)
0 Backup & snapshot (Live USB)
--------------------------------
sudo cryptsetup luksOpen /dev/nvme0n1p3 cryptroot
sudo vgchange -ay
sudo lvcreate -s -n root-pre-shrink -L 10G /dev/system/root
sudo lvs
1 Shrink Tuxedo root to 250 G
------------------------------
sudo e2fsck -f /dev/mapper/system-root
sudo resize2fs /dev/mapper/system-root 245G
sudo lvreduce -L 250G /dev/system/root
sudo pvresize --setphysicalvolumesize 250G /dev/mapper/cryptroot
pvs && lvs
2 Partition table
------------------
sudo partprobe /dev/nvme0n1
sudo parted /dev/nvme0n1 unit MiB print free # note gaps
# create 512 MiB ESP at end (example)
sudo parted /dev/nvme0n1 -- mkpart ESP fat32 -550MiB -1MiB
sudo parted /dev/nvme0n1 -- set 5 esp on
# create LUKS slice in remaining gap
START=<first_free_MiB_before_p5>
sudo parted /dev/nvme0n1 -- mkpart primary ${START}MiB -551MiB
sudo parted /dev/nvme0n1 -- set 4 lvm on
sudo partprobe /dev/nvme0n1
sudo parted /dev/nvme0n1 unit MiB print
3 New LUKS + LVM for NixOS
---------------------------
sudo cryptsetup luksFormat /dev/nvme0n1p4
sudo cryptsetup open /dev/nvme0n1p4 nixoscrypt
sudo pvcreate /dev/mapper/nixoscrypt
sudo vgcreate nixos /dev/mapper/nixoscrypt
sudo lvcreate -L 200G -n root nixos
sudo lvcreate -L 34G -n swap nixos
4 Filesystems & mounts
-----------------------
sudo mkfs.ext4 /dev/nixos/root
sudo mkswap /dev/nixos/swap
sudo swapon /dev/nixos/swap
sudo mkfs.vfat -n NIXOS_EFI /dev/nvme0n1p5
sudo mount /dev/nixos/root /mnt
sudo mkdir -p /mnt/boot/efi
sudo mount /dev/nvme0n1p5 /mnt/boot/efi
5 Minimal NixOS install
------------------------
sudo nixos-generate-config --root /mnt
# Edit /mnt/etc/nixos/configuration.nix:
# boot.loader.systemd-boot.enable = true;
# boot.loader.efi.canTouchEfiVariables = true;
# boot.initrd.luks.devices."nixoscrypt".device = "/dev/nvme0n1p4";
# boot.resumeDevice = "/dev/disk/by-uuid/<swap-uuid>";
# swapDevices = [ { device = "/dev/nixos/swap"; } ];
# system.stateVersion = "24.05";
sudo nixos-install
6 First boot tests
-------------------
- Select **NixOS** in firmware boot menu (F12).
- lsblk -f → verify separate volumes.
- systemctl hibernate → resume OK, kernel cmdline has resume=UUID.
7 Cleanup after success
------------------------
sudo lvremove /dev/system/root-pre-shrink

Personal Procedure – Shrink Tuxedo OS / and Add Isolated NixOS (UEFI‑menu dual boot)

Audience: Me only. One‑off checklist; terse by design.


0  Backup & Snapshot

(Ambiguity killers: device names may differ; adjust accordingly.)

  • External backup first (rsync or Timeshift‑BTRFS snapshot).

  • Create LV snapshot before shrinking:

    sudo lvcreate -s -n root-pre-shrink -L 10G /dev/system/root

    (Gives rollback if resize2fs fails.)


1  Shrink Tuxedo root to 250 G (NixOS Live USB)

# unlock & activate existing LUKS/LVM
sudo cryptsetup luksOpen /dev/nvme0n1p3 cryptroot
sudo vgchange -ay

# fsck + shrink fs → 245 G margin
sudo e2fsck -f /dev/mapper/system-root
sudo resize2fs /dev/mapper/system-root 245G

# shrink LV to 250 G
sudo lvreduce -L 250G /dev/system/root

# shrink PV so space becomes truly free on disk
sudo pvresize --setphysicalvolumesize 250G /dev/mapper/cryptroot   # name might be cryptroot or luks‑<UUID>; check with ls /dev/mapper

# optional: verify new sizes
pvs   # PV size/free
lvs   # LV sizes

2  Partition table – carve ESP first, then LUKS slice

Goal: leave ~512 MiB at end of disk for the ESP, remainder for the new LUKS partition.

  1. Rescan disk (after pvresize):

    sudo partprobe /dev/nvme0n1
    sudo parted /dev/nvme0n1 unit MiB print free   # note last‑free region size / start
  2. Create 512 MiB ESP at end (example with negative offsets ‑550 MiB to ‑1 MiB):

    sudo parted /dev/nvme0n1 -- mkpart ESP fat32 -550MiB -1MiB
    sudo parted /dev/nvme0n1 -- set 5 esp on   # p5 if it becomes the 5th partition

    If -550MiB complains, use explicit numbers from print free: start = (disk‑size‑550), end = (disk‑size‑1). Verify with parted print, ensure p5 size ~512 MiB.

  3. Create primary p4 for LUKS in remaining gap:

    • Identify the new first‑free start (shown by print free) after existing partitions and before p5.
    • Substitute that numeric value (MiB) as <START-MiB>:
    START=<numeric_first_free_MiB>
    sudo parted /dev/nvme0n1 -- mkpart primary ${START}MiB -551MiB
    sudo parted /dev/nvme0n1 -- set 4 lvm on    # optional flag
  4. Re‑read table again & confirm:

    sudo partprobe /dev/nvme0n1
    sudo parted /dev/nvme0n1 unit MiB print

Now p4 (LUKS) sits immediately before p5 (ESP).

3  Create isolated LUKS + LVM for NixOS (on /dev/nvme0n1p4)

sudo cryptsetup luksFormat /dev/nvme0n1p4
sudo cryptsetup open /dev/nvme0n1p4 nixoscrypt

sudo pvcreate /dev/mapper/nixoscrypt
sudo vgcreate nixos /dev/mapper/nixoscrypt

# root 200 G, swap 34 G (≥ RAM 32 G + buffer)
sudo lvcreate -L 200G -n root nixos
sudo lvcreate -L 34G  -n swap nixos

4  Filesystems & mounts

sudo mkfs.ext4 /dev/nixos/root
sudo mkswap    /dev/nixos/swap
sudo swapon    /dev/nixos/swap

sudo mkfs.vfat -n NIXOS_EFI /dev/nvme0n1p5

sudo mount /dev/nixos/root /mnt
sudo mkdir -p /mnt/boot/efi
sudo mount /dev/nvme0n1p5 /mnt/boot/efi

5  Minimal NixOS install (enough to nixos-rebuild later)

sudo nixos-generate-config --root /mnt

In /mnt/etc/nixos/configuration.nix:

boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;   # requires firmware write

# LUKS mapping
boot.initrd.luks.devices."nixoscrypt".device = "/dev/nvme0n1p4";

# Hibernate support
boot.resumeDevice = "/dev/disk/by-uuid/<swap-uuid>";

swapDevices = [{ device = "/dev/nixos/swap"; }];

Then:

sudo nixos-install

(Skip user config; will import flake later.)


6  First Boot & Verification

  1. Firmware boot menu (F12) → choose NixOS.

  2. Verify mounts: lsblk -f – NixOS volumes should be separate.

  3. Test hibernate:

    systemctl hibernate

    Resume should work; confirm cat /proc/cmdline | grep resume.

Secure Boot: if enabled, sign systemd‑boot with sbctl or disable SB in firmware.


7  Cleanup

# after confirming success
sudo lvremove /dev/system/root-pre-shrink   # delete snapshot

Done.


Glossary & Command Cheatsheet

Term / Command Meaning / Purpose
ESP (EFI System Partition) FAT32 partition flagged esp; UEFI firmware reads bootloaders here. Created with parted … mkpart ESP fat32 … + set esp on.
UEFI firmware boot menu Firmware UI (often F12, F10, Esc) letting you pick ESP entries without GRUB chaining.
LUKS Linux Unified Key Setup – disk encryption layer (cryptsetup luksFormat, luksOpen).
PV Physical Volume: LVM wrapper around a block device (e.g., /dev/mapper/nixoscrypt). Created with pvcreate.
VG Volume Group: pool of space made of PVs (vgcreate nixos …).
LV Logical Volume: flexible “partition” cut from a VG (lvcreate -L 200G -n root nixos).
snapshot LV Copy‑on‑write snapshot for rollback (lvcreate -s).
e2fsck Ext4 filesystem check & repair (e2fsck -f /dev/mapper/system-root).
resize2fs Shrink/grow ext4 filesystem after fsck.
lvreduce / lvextend Shrink/grow LV size. Always resize FS first when shrinking.
pvresize Shrink/grow PV size to free or reclaim disk space.
parted CLI partition editor; unit MiB print free shows gaps; mkpart, set, negative offsets (-550MiB) relative to disk end.
partprobe Ask kernel to reload partition table after edits.
mkfs.ext4 / mkfs.vfat Format LV/partition with ext4 or FAT32.
blkid Display UUIDs (blkid /dev/nixos/swap).
systemd‑boot Simple UEFI bootloader used by NixOS (boot.loader.systemd-boot.enable = true).
resume=UUID=… Kernel parameter telling initrd where the hibernation image resides; set via boot.resumeDevice.
sbctl Utility to manage Secure Boot keys and sign systemd‑boot.
pvs, vgs, lvs Quick LVM status overviews (Physical/Volume/Logical).

Tuxedo OS (GRUB entry TUXEDO/ubuntu) and NixOS (new ESP) coexist; neither touches the other.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment