Compare commits

...

9 Commits

Author SHA1 Message Date
a3c8995422 [btrfs] Add role and migrate nix-book 2025-07-29 16:14:29 -07:00
b9bb5d387f [nix-book] Update drive UUID 2025-07-29 15:48:04 -07:00
e3aff80a97 [nix-book] Add beesd 2025-07-29 15:48:04 -07:00
574c8e6482 [nix-book] Update file system type to btrfs 2025-07-29 15:48:04 -07:00
0f59a558cd [nix-book] Add btrfs migration plan 2025-07-29 15:48:04 -07:00
14b7de30f6 [live-usb] Clean up config
Also switched from trying to override the `nixos` user to instead just
installing home-manager _into_ the `nixos` user. It felt a bit like
fighting the tide otherwise.
2025-07-29 15:29:48 -07:00
8b676203e7 [live-usb] Add a build script 2025-07-29 12:15:36 -07:00
beeb7acefd [live-usb] Clean up the configuration 2025-07-29 12:15:25 -07:00
a512d9bc06 [live-usb] Add live-usb machine configuration 2025-07-29 12:01:38 -07:00
8 changed files with 534 additions and 5 deletions

19
build-liveusb.sh Executable file
View File

@@ -0,0 +1,19 @@
#!/usr/bin/env bash
# Build Live USB ISO from flake configuration
# Creates an uncompressed ISO suitable for Ventoy and other USB boot tools
set -e
echo "Building Live USB ISO..."
nix build .#nixosConfigurations.live-usb.config.system.build.isoImage --show-trace
if [ -f "./result/iso/"*.iso ]; then
iso_file=$(ls ./result/iso/*.iso)
echo "✅ Build complete!"
echo "📁 ISO location: $iso_file"
echo "💾 Ready for Ventoy or dd to USB"
else
echo "❌ Build failed - no ISO file found"
exit 1
fi

View File

@@ -74,6 +74,22 @@
];
};
# Live USB ISO configuration
nixosConfigurations.live-usb = nixpkgs.lib.nixosSystem rec {
system = "x86_64-linux";
modules = baseModules ++ [
./machines/live-usb/configuration.nix
{
home-manager.users.nixos = { ... }: {
imports = [ ./home/home.nix ];
home.username = nixpkgs.lib.mkForce "nixos";
home.homeDirectory = nixpkgs.lib.mkForce "/home/nixos";
};
home-manager.extraSpecialArgs = { inherit system; };
}
];
};
homeConfigurations."johno" = inputs.home-manager.lib.homeManagerConfiguration {
pkgs = inputs.nixpkgs.legacyPackages."x86_64-linux";
modules = [

View File

@@ -0,0 +1,89 @@
# Live USB ISO configuration for recovery and installation
{ pkgs, modulesPath, ... }:
{
imports = [
# Use minimal installation CD as base
(modulesPath + "/installer/cd-dvd/installation-cd-minimal.nix")
];
# Use roles structure for consistent configuration
roles = {
audio.enable = true;
bluetooth.enable = true;
desktop = {
enable = true;
kde = true;
x11 = true;
wayland = true;
sddm = true;
};
};
# Allow unfree packages for broader hardware support
nixpkgs.config.allowUnfree = true;
# Essential packages for system recovery and installation
environment.systemPackages = with pkgs; [
# Text editors
neovim
nano
# System tools
git
curl
wget
htop
tree
lsof
strace
# Filesystem tools
btrfs-progs
e2fsprogs
xfsprogs
ntfs3g
dosfstools
# Network tools
networkmanager
wirelesstools
# Hardware tools
pciutils
usbutils
smartmontools
# Archive tools
unzip
p7zip
# Development tools (for quick fixes)
gcc
binutils
];
# Enable NetworkManager for easy wifi setup
networking.networkmanager.enable = true;
# Enable SSH daemon for remote access
services.openssh = {
enable = true;
settings = {
PermitRootLogin = "yes";
PasswordAuthentication = true;
};
};
# ISO customization
isoImage = {
volumeID = "NIXOS-LIVE";
};
# Enable some useful services
services.udisks2.enable = true; # For mounting USB drives
# Hardware support
hardware.enableAllFirmware = true;
hardware.enableRedistributableFirmware = true;
}

View File

@@ -39,6 +39,7 @@
boot.kernelPackages = pkgs.linuxPackages_latest;
# Enable networking
networking.networkmanager.enable = true;

View File

@@ -10,15 +10,27 @@
boot.initrd.availableKernelModules = [ "xhci_pci" "thunderbolt" "vmd" "nvme" "sdhci_pci" ];
boot.initrd.kernelModules = [ ];
boot.initrd.luks.devices."luks-4126fbd4-bd09-4ece-af0d-6fff414c21b3".device = "/dev/disk/by-uuid/4126fbd4-bd09-4ece-af0d-6fff414c21b3";
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "/dev/disk/by-uuid/bd396529-e2c4-47cb-b844-8d6ed841f81a";
fsType = "ext4";
roles.btrfs = {
enable = true;
filesystems."/dev/disk/by-uuid/223a44e5-91e2-4272-830e-129166042a1d" = {
mountpoints = {
"/" = {
compression = "zstd";
extraOptions = [ "noatime" ];
};
};
scrub.enable = true;
deduplication = {
enable = true;
hashTableSizeMB = 32;
verbosity = "err";
};
};
boot.initrd.luks.devices."luks-4126fbd4-bd09-4ece-af0d-6fff414c21b3".device = "/dev/disk/by-uuid/4126fbd4-bd09-4ece-af0d-6fff414c21b3";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/7A0B-CF88";

View File

@@ -0,0 +1,223 @@
# NixBook ext4 to btrfs Migration Guide
## Overview
This guide converts your nixbook machine from ext4 to btrfs with zstd compression and beesd deduplication while preserving your LUKS encryption and all data.
## Current System Info
- **Hostname**: nix-book
- **Root filesystem**: ext4 on `/dev/disk/by-uuid/bd396529-e2c4-47cb-b844-8d6ed841f81a`
- **Encryption**: LUKS with two devices configured
- **Current usage**: 138GB used / 225GB total (65% full)
- **Free space**: 76GB available (sufficient for conversion)
## Pre-Migration Checklist
### 1. Create Full System Backup (CRITICAL)
```bash
# Boot from NixOS live USB
# Mount encrypted filesystem
cryptsetup luksOpen /dev/disk/by-uuid/4126fbd4-bd09-4ece-af0d-6fff414c21b3 luks-nixbook
mount /dev/mapper/luks-nixbook /mnt
# Create backup to external drive (adjust target as needed)
rsync -avxHAX --progress /mnt/ /path/to/backup/nixbook-backup/
```
### 2. Verify Configuration Changes
The following files have been updated for btrfs:
- `machines/nix-book/configuration.nix` - Added beesd service
- `machines/nix-book/hardware-configuration.nix` - Changed fsType to btrfs with compression
## Migration Process
### Phase 1: Boot to Live Environment
1. **Create NixOS live USB**:
```bash
# Download latest NixOS ISO
# Flash to USB drive
dd if=nixos-minimal-xx.xx-x86_64-linux.iso of=/dev/sdX bs=4M status=progress
```
2. **Boot from live USB** and ensure you can access the encrypted drives
### Phase 2: Filesystem Conversion
3. **Unlock LUKS volumes**:
```bash
cryptsetup luksOpen /dev/disk/by-uuid/4126fbd4-bd09-4ece-af0d-6fff414c21b3 luks-nixbook
cryptsetup luksOpen /dev/disk/by-uuid/b614167b-9045-4234-a441-ac6f60a96d81 luks-nixbook2
```
4. **Check filesystem before conversion**:
```bash
fsck.ext4 -f /dev/mapper/luks-nixbook
```
5. **Convert ext4 to btrfs** (this preserves all data):
```bash
# Install btrfs-progs if not available
nix-shell -p btrfs-progs
# Convert the filesystem (takes 15-45 minutes depending on data)
btrfs-convert /dev/mapper/luks-nixbook
# Verify conversion succeeded
mount /dev/mapper/luks-nixbook /mnt
ls -la /mnt # Should show your normal filesystem
btrfs filesystem show /mnt
```
6. **Get new filesystem UUID** (may have changed):
```bash
blkid /dev/mapper/luks-nixbook
# Note the new UUID if it changed
```
### Phase 3: Configuration Update
7. **Mount and chroot into system**:
```bash
mount -o compress=zstd,noatime /dev/mapper/luks-nixbook /mnt
mount /dev/disk/by-uuid/7A0B-CF88 /mnt/boot
nixos-enter --root /mnt
```
8. **Update hardware-configuration.nix** if UUID changed:
```bash
# Edit /etc/nixos/hardware-configuration.nix if needed
# Update the UUID in fileSystems."/" section
```
9. **Rebuild system with btrfs configuration**:
```bash
cd /home/johno/nixos-configs
nixos-rebuild switch --flake .#nix-book
```
### Phase 4: Enable Compression and Deduplication
10. **Reboot into new btrfs system**:
```bash
exit # Exit chroot
umount -R /mnt
reboot
```
11. **Verify btrfs is working**:
```bash
mount | grep btrfs
btrfs filesystem usage /
```
12. **Enable and start beesd**:
```bash
systemctl status beesd-root
systemctl start beesd-root
systemctl enable beesd-root
```
13. **Force compression on existing files** (optional but recommended):
```bash
# This will compress existing files with zstd
btrfs filesystem defragment -r -czstd /
```
## Post-Migration Verification
### Check System Health
```bash
# Verify btrfs health
btrfs scrub start /
btrfs scrub status /
# Check compression effectiveness
compsize /
# Monitor beesd deduplication
journalctl -u beesd-root -f
# Check filesystem usage
btrfs filesystem usage /
df -h /
```
### Performance Monitoring
```bash
# Monitor beesd hash table
ls -lh /.beeshash
# Check compression ratio over time
compsize /home /nix /var
```
## Expected Benefits
### Space Savings
- **Compression**: 20-30% reduction in disk usage from zstd
- **Deduplication**: Additional 10-20% savings on duplicate files
- **Combined**: Potentially 30-40% total space savings
### Performance Impact
- **Compression**: Minimal CPU overhead, often improves I/O performance
- **Deduplication**: Background process, minimal impact during normal use
- **Overall**: Should be neutral to positive performance impact
## Rollback Plan (Emergency)
If something goes wrong:
1. **Boot from live USB**
2. **Restore from backup**:
```bash
cryptsetup luksOpen /dev/disk/by-uuid/4126fbd4-bd09-4ece-af0d-6fff414c21b3 luks-nixbook
mkfs.ext4 /dev/mapper/luks-nixbook
mount /dev/mapper/luks-nixbook /mnt
rsync -avxHAX --progress /path/to/backup/nixbook-backup/ /mnt/
```
3. **Restore original hardware-configuration.nix** with ext4 settings
4. **Rebuild and reboot**
## Troubleshooting
### Common Issues
**"Device busy" during conversion**:
- Ensure no processes are accessing the filesystem
- Check with `lsof` and `fuser`
**UUID changed after conversion**:
- Update hardware-configuration.nix with new UUID
- Regenerate initrd: `nixos-rebuild switch`
**Beesd service fails to start**:
- Check disk space for hash table
- Verify filesystem is btrfs: `mount | grep btrfs`
- Check logs: `journalctl -u beesd-root`
**Boot issues after conversion**:
- Boot from live USB
- Check /boot partition is mounted correctly
- Verify LUKS UUIDs match in configuration
- Rebuild bootloader: `nixos-rebuild switch --install-bootloader`
## Maintenance
### Regular Tasks
```bash
# Monthly scrub (checks for corruption)
btrfs scrub start /
# Monitor compression effectiveness
compsize /
# Check beesd deduplication status
systemctl status beesd-root
```
### Space Management
```bash
# Balance filesystem (defragments and optimizes)
btrfs balance start -dusage=50 /
# Check for space issues
btrfs filesystem usage /
```
This migration preserves all your data while gaining the benefits of modern btrfs features including transparent compression and automatic deduplication.

168
roles/btrfs/default.nix Normal file
View File

@@ -0,0 +1,168 @@
{ lib, config, pkgs, ... }:
with lib;
let
cfg = config.roles.btrfs;
in
{
options.roles.btrfs = {
enable = mkEnableOption "Enable btrfs filesystem management";
filesystems = mkOption {
type = types.attrsOf (types.submodule {
options = {
# Filesystem-level maintenance options
scrub = {
enable = mkOption {
type = types.bool;
default = true;
description = "Enable automatic scrubbing for this filesystem";
};
interval = mkOption {
type = types.str;
default = "weekly";
description = "Scrub interval (systemd timer format)";
};
};
deduplication = {
enable = mkOption {
type = types.bool;
default = false;
description = "Enable beesd deduplication for this filesystem";
};
hashTableSizeMB = mkOption {
type = types.int;
default = 1024;
description = "Hash table size in MB (should be multiple of 16)";
};
verbosity = mkOption {
type = types.str;
default = "info";
description = "Logging verbosity level";
};
};
balance = {
enable = mkOption {
type = types.bool;
default = false;
description = "Enable periodic balance operations";
};
interval = mkOption {
type = types.str;
default = "monthly";
description = "Balance interval (systemd timer format)";
};
dataUsage = mkOption {
type = types.int;
default = 50;
description = "Data usage threshold for balance";
};
metadataUsage = mkOption {
type = types.int;
default = 50;
description = "Metadata usage threshold for balance";
};
};
# Mountpoint-based configuration
mountpoints = mkOption {
type = types.attrsOf (types.submodule {
options = {
subvolume = mkOption {
type = types.nullOr types.str;
default = null;
description = "Subvolume name. If null, uses default subvolume.";
};
compression = mkOption {
type = types.str;
default = "zstd";
description = "Compression algorithm (zstd, lzo, lz4, none)";
};
autodefrag = mkOption {
type = types.bool;
default = false;
description = "Enable automatic defragmentation";
};
extraOptions = mkOption {
type = types.listOf types.str;
default = [];
description = "Additional mount options";
};
};
});
default = {};
description = "Mountpoint configurations for this filesystem";
};
};
});
default = {};
description = "Btrfs filesystems configuration";
};
};
config = mkIf cfg.enable {
# Generate fileSystems configuration from mountpoints
fileSystems = mkMerge (flatten (mapAttrsToList (device: fsCfg:
mapAttrsToList (mountpoint: mountCfg:
{
${mountpoint} = {
device = device;
fsType = "btrfs";
options =
(optional (mountCfg.subvolume != null) "subvol=${mountCfg.subvolume}") ++
[ "compress=${mountCfg.compression}" ] ++
(optional mountCfg.autodefrag "autodefrag") ++
mountCfg.extraOptions;
};
}
) fsCfg.mountpoints
) cfg.filesystems));
# Configure scrub service using NixOS built-in
services.btrfs.autoScrub = mkIf (any (fs: fs.scrub.enable) (attrValues cfg.filesystems)) {
enable = true;
interval = "weekly"; # TODO: Make this configurable per filesystem
fileSystems = attrNames (filterAttrs (_: fs: fs.scrub.enable) cfg.filesystems);
};
# Configure beesd for filesystems with deduplication enabled
services.beesd.filesystems = mapAttrs' (device: fsCfg:
nameValuePair (replaceStrings ["/"] ["_"] (replaceStrings ["-"] ["_"] device)) {
spec = device;
hashTableSizeMB = fsCfg.deduplication.hashTableSizeMB;
verbosity = fsCfg.deduplication.verbosity;
}
) (filterAttrs (_: fs: fs.deduplication.enable) cfg.filesystems);
# Custom balance services for filesystems with balance enabled
systemd.services = mkMerge (mapAttrsToList (device: fsCfg: mkIf fsCfg.balance.enable {
"btrfs-balance-${replaceStrings ["/"] ["-"] (replaceStrings ["-"] ["_"] device)}" = {
description = "Balance btrfs filesystem ${device}";
script = ''
${pkgs.btrfs-progs}/bin/btrfs balance start \
-dusage=${toString fsCfg.balance.dataUsage} \
-musage=${toString fsCfg.balance.metadataUsage} \
${device}
'';
serviceConfig = {
Type = "oneshot";
Nice = 19;
IOSchedulingClass = "idle";
};
};
}) cfg.filesystems);
# Balance timers
systemd.timers = mkMerge (mapAttrsToList (device: fsCfg: mkIf fsCfg.balance.enable {
"btrfs-balance-${replaceStrings ["/"] ["-"] (replaceStrings ["-"] ["_"] device)}" = {
description = "Periodic balance for ${device}";
wantedBy = [ "timers.target" ];
timerConfig = {
OnCalendar = fsCfg.balance.interval;
Persistent = true;
};
};
}) cfg.filesystems);
};
}

View File

@@ -6,6 +6,7 @@ with lib;
imports = [
./audio
./bluetooth
./btrfs
./desktop
./kodi
./nfs-mounts