snapshot pre-cleanup-2026-06-04T16-00-46Z

This commit is contained in:
2026-06-04 18:00:46 +02:00
parent 9e0f4e9aca
commit 501965a0dc
11 changed files with 791 additions and 3 deletions
Generated
+21
View File
@@ -46,6 +46,26 @@
"type": "github"
}
},
"disko": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1780290312,
"narHash": "sha256-eTAlX0CwgB84Ts3GaBd944A3DRXVMzgA0EqroZBISUo=",
"owner": "nix-community",
"repo": "disko",
"rev": "115e5211780054d8a890b41f0b7734cafad54dfe",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "disko",
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
@@ -285,6 +305,7 @@
"root": {
"inputs": {
"caelestia-shell": "caelestia-shell",
"disko": "disko",
"flake-parts": "flake-parts",
"flake-utils": "flake-utils",
"home-manager": "home-manager",
+4
View File
@@ -27,6 +27,10 @@
url = "github:caelestia-dots/shell";
inputs.nixpkgs.follows = "nixpkgs-unstable";
};
disko = {
url = "github:nix-community/disko";
inputs.nixpkgs.follows = "nixpkgs";
};
microPlugins-vivify = {
url = "git+https://codeberg.org/gibbert/micro-vivify";
flake = false;
+7
View File
@@ -48,6 +48,13 @@
];
};
};
flake.homeModules.hyprland-desktop = _: {
wayland.windowManager.hyprland.settings = {
monitor = [
", highres@highrr, auto, 1"
];
};
};
flake.homeModules.hyprland = {pkgs-unstable, ...}: let
wallpaper = ../../assets/wallpaper1.jpg;
in {
+11 -3
View File
@@ -7,10 +7,18 @@
};
};
};
flake.homeModules.zsh = {pkgs, ...}: {
flake.homeModules.zsh-desktop = _: {
programs.zsh = {
shellAliases = {
snrt = "git -C ~/nixos add -A && time sudo nixos-rebuild test --flake ~/nixos/#desktop && pkill shell || true && pkill caelestia-shell || true && caelestia-shell -n > /dev/null 2>&1 & disown";
snrs = "git -C ~/nixos add -A && time sudo nixos-rebuild switch --flake ~/nixos/#desktop && pkill shell || true && pkill caelestia-shell || true && caelestia-shell -n > /dev/null 2>&1 & disown";
};
};
};
flake.homeModules.zsh = {pkgs, pkgs-unstable, ...}: {
home.packages = [
self.packages.${pkgs.system}.dejaManuallyDerived
#pkgs-unstable.deja
#self.packages.${pkgs.system}.dejaManuallyDerived
pkgs-unstable.deja
];
programs.zsh = {
+14
View File
@@ -9,6 +9,20 @@ _: {
theme = inputs.nixos-grub-themes.packages.${pkgs.system}.nixos; # if you want to use nixos grub theme
};
# Bootloader.
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
};
flake.nixosModules.bootloader-desktop = {
inputs,
pkgs,
...
}: {
# grub theme
boot.loader.grub = {
theme = inputs.nixos-grub-themes.packages.${pkgs.system}.nixos; # if you want to use nixos grub theme
};
# Bootloader.
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
+241
View File
@@ -0,0 +1,241 @@
Note : ChatGPT helped me with the disko setup
This is the layout I'd start with. It's not fully copy-paste ready because you'll need to fill in the actual disk IDs after booting the installer, but it captures the architecture you described:
* SSD: LUKS → Btrfs
* HDD: LUKS → ext4
* One password entered at boot
* HDD unlocked using a keyfile stored on the SSD
* Suitable for a desktop host
# disko/desktop.nix
```
{
disko.devices = {
disk = {
ssd = {
# Replace with actual disk id from:
# ls -l /dev/disk/by-id
device = "/dev/disk/by-id/REPLACE_SSD_ID";
type = "disk";
content = {
type = "gpt";
partitions = {
ESP = {
size = "1G";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
};
};
luks = {
size = "100%";
content = {
type = "luks";
name = "cryptroot";
# You will type this password at boot.
settings.allowDiscards = true;
content = {
type = "btrfs";
extraArgs = [ "-f" ];
subvolumes = {
"@root" = {
mountpoint = "/";
mountOptions = [
"compress=zstd"
"noatime"
];
};
"@home" = {
mountpoint = "/home";
mountOptions = [
"compress=zstd"
"noatime"
];
};
"@nix" = {
mountpoint = "/nix";
mountOptions = [
"compress=zstd"
"noatime"
];
};
"@snapshots" = {
mountpoint = "/.snapshots";
};
# Keyfile storage.
# This subvolume will contain the key used
# to unlock the HDD automatically.
"@keys" = {
mountpoint = "/keys";
};
};
};
};
};
};
};
};
hdd = {
# Replace with actual disk id
device = "/dev/disk/by-id/REPLACE_HDD_ID";
type = "disk";
content = {
type = "gpt";
partitions = {
luks = {
size = "100%";
content = {
type = "luks";
name = "cryptdata";
# IMPORTANT:
# This keyfile will be created after installation.
# The SSD unlocks first.
# Then this keyfile unlocks the HDD automatically.
settings = {
keyFile = "/keys/hdd.key";
};
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/data";
};
};
};
};
};
};
};
```
};
}
A few notes:
### 1. You'll need the disk IDs
On the installer:
```bash
ls -l /dev/disk/by-id
```
Then replace:
```text
REPLACE_SSD_ID
REPLACE_HDD_ID
```
with the actual values.
---
### 2. The HDD keyfile is a second step
After installation:
```bash
sudo mkdir -p /keys
sudo chmod 700 /keys
sudo dd if=/dev/urandom of=/keys/hdd.key bs=4096 count=1
sudo chmod 000 /keys/hdd.key
```
Then add the key to the HDD LUKS container:
```bash
sudo cryptsetup luksAddKey /dev/disk/by-id/ACTUAL_HDD_PARTITION /keys/hdd.key
```
Now:
```text
boot
enter SSD password
SSD unlocks
keyfile becomes available
HDD unlocks automatically
```
One password.
---
### 3. Btrfs subvolumes
I intentionally kept it simple:
```text
/
/home
/nix
/.snapshots
```
This is a very common NixOS layout.
---
### 4. Swap
I haven't included swap because there are a few valid choices:
* swapfile on Btrfs
* swap partition inside the SSD LUKS container
* zram only
I'd probably use **zram + a small swapfile** unless you have a very specific workload.
---
### 5. Dendritic adaptation
The actual Disko definition above won't change much.
The dendritic part is mostly wrapping it in your top-level module structure, something like:
```nix
{
flake.diskoConfigurations.desktop = {
imports = [
./desktop-disko.nix
];
};
}
```
or whatever convention your repository uses.
The storage design itself remains the same.
+122
View File
@@ -0,0 +1,122 @@
_: {
flake.diskoConfigurations.desktop = _: {
disko.devices = {
disk = {
ssd = {
# Replace with actual disk id from:
# ls -l /dev/disk/by-id
device = "/dev/disk/by-id/REPLACE_SSD_ID";
type = "disk";
content = {
type = "gpt";
partitions = {
ESP = {
size = "1G";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
};
};
luks = {
size = "100%";
content = {
type = "luks";
name = "cryptroot";
# You will type this password at boot.
settings.allowDiscards = true;
content = {
type = "btrfs";
extraArgs = [ "-f" ];
subvolumes = {
"@root" = {
mountpoint = "/";
mountOptions = [
"compress=zstd"
"noatime"
];
};
"@home" = {
mountpoint = "/home";
mountOptions = [
"compress=zstd"
"noatime"
];
};
"@nix" = {
mountpoint = "/nix";
mountOptions = [
"compress=zstd"
"noatime"
];
};
"@snapshots" = {
mountpoint = "/.snapshots";
};
# Keyfile storage.
# This subvolume will contain the key used
# to unlock the HDD automatically.
"@keys" = {
mountpoint = "/keys";
};
};
};
};
};
};
};
};
hdd = {
# Replace with actual disk id
device = "/dev/disk/by-id/REPLACE_HDD_ID";
type = "disk";
content = {
type = "gpt";
partitions = {
luks = {
size = "100%";
content = {
type = "luks";
name = "cryptdata";
# IMPORTANT:
# This keyfile will be created after installation.
# The SSD unlocks first.
# Then this keyfile unlocks the HDD automatically.
settings = {
keyFile = "/keys/hdd.key";
};
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/data";
};
};
};
};
};
};
};
}
+137
View File
@@ -0,0 +1,137 @@
# Note : i should add a way to communicate, annote which commits i should cherry-pick between computers
{
inputs,
self,
...
}: {
flake.nixosConfigurations.desktop = inputs.nixpkgs.lib.nixosSystem {
#system = "x86_64-linux";
specialArgs = {
inherit (self) pkgs-unstable;
};
modules = with self.nixosModules; [
# important do not remove
home-manager-desktop
desktop
{nixpkgs.pkgs = self.pkgs;}
# keep this alphabetically organised
anki
audioAndMedia
autoCleanup-desktop
autoUpdate-desktop
bluetooth
bootloader-desktop
browsers
caelestia
development
documentation
disk # this only installs some disk utilities. disko will format the drives
fonts
#hardware-configuration-desktop
hyprland
IO
#kdrive-laptop # we will setup this later
latex
ly
mullvad
networking
notifications
office
#ollama
otherUtils
printer
rss
udev
user
];
};
flake.homeModules.desktop = {...}: {
imports = with self.homeModules; [
inputs.caelestia-shell.homeManagerModules.default
anki
caelestia
cursor
development
eza
fastfetch
git
gtk
hyprland
hyprland-desktop
kitty
librewolf
mullvad
neovim
notewrapper
oh-my-zsh
ripgrep
rofi
sbb-tui
ssh
thunderbird
tomasr
vivify
zoxide
zsh
zsh-desktop
];
};
flake.nixosModules.desktop = _: {
# This value determines the NixOS release from which the default
# settings for stateful data, like file locations and database versions
# on your system were taken. Its perfectly fine and recommended to leave
# this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "25.11"; # Did you read the comment?
nix.settings.experimental-features = [
"nix-command"
"flakes"
];
};
flake.nixosModules.home-manager-desktop = {pkgs, ...}: {
imports = [
inputs.home-manager.nixosModules.default # import official home-manager NixOS module
];
# Warning. Git is used in case I break everything up. It already saved me once
environment.systemPackages = [pkgs.git];
home-manager = {
useGlobalPkgs = true;
useUserPackages = true;
extraSpecialArgs = {
inherit (self) pkgs-unstable;
inherit self;
};
};
users.users.tomasr = {
isNormalUser = true;
};
home-manager.users.tomasr = self.homeModules.desktop;
};
# this is a copy of what is in laptop.nix
/*flake.homeModules.tomasr = _: {
home.username = "tomasr";
home.homeDirectory = "/home/tomasr";
home.sessionVariables = {
EDITOR = "neovim";
TERMINAL = "kitty";
};
# Required for Home Manager
home.stateVersion = "25.11"; # match your Home Manager release
# This value determines the Home Manager release that your configuration is
# compatible with. This helps avoid breakage when a new Home Manager release
# introduces backwards incompatible changes.
#
# You should not change this value, even if you update Home Manager. If you do
# want to update the value, then make sure to first check the Home Manager
# release notes.
# Let Home Manager install and manage itself.
programs.home-manager.enable = true;
};*/
}
+1
View File
@@ -3,6 +3,7 @@
imports = [
# adds home-manager options to flake-parts
inputs.home-manager.flakeModules.home-manager
inputs.disko.flakeModules.default
];
config.systems = [
+124
View File
@@ -117,6 +117,130 @@
fi
git -C "$FLAKE_DIR" tag -d "pre-cleanup-$TIME" # removes the tag
rm -f "$ERROR_FILE"
'';
};
};
## Desktop
flake.nixosModules.autoCleanup-desktop = {
pkgs,
pkgs-unstable,
...
}: {
# Ensure your script is available system-wide
environment.systemPackages = [
self.packages.${pkgs.system}.custom-cleanNix-desktop
pkgs-unstable.statix
];
users.users.tomasr = {
linger = true; # lingering is required
};
systemd.user.services.custom-cleanNix = {
description = "NixOS configuration auto cleanup";
serviceConfig = {
Type = "oneshot";
ExecStart = "/run/current-system/sw/bin/custom-cleanNix";
# safety for long rebuilds
TimeoutStartSec = "45min";
TimeoutStopSec = "10min";
# avoid overlap
RemainAfterExit = true;
# tweaks that should make the system run normally during the rebuilds
Nice = 10;
IOSchedulingClass = "best-effort";
IOSchedulingPriority = 7;
};
};
# Systemd USER timer
systemd.user.timers.custom-cleanNix = {
wantedBy = ["timers.target"];
timerConfig = {
OnCalendar = "Sat *-*-* 20:00:00"; # runs saturday night. If for whatever reason something breaks. I have whole sunday to fix it.
Persistent = true; # if it happens during shutted down
# avoids thundering herd on boot
RandomizedDelaySec = "2h";
};
};
};
perSystem = {pkgs, ...}: {
packages.custom-cleanNix-desktop = pkgs.writeShellApplication {
name = "custom-cleanNix";
runtimeInputs = with pkgs; [
git
nixos-rebuild
matrix-commander-rs
libnotify
alejandra
deadnix
];
text = ''
set -e
FLAKE_DIR="/home/tomasr/nixos"
FLAKE="$FLAKE_DIR#desktop"
TIME=$(date -u +"%Y-%m-%dT%H-%M-%SZ")
ERROR_FILE=$(mktemp)
# snapshot current state
git -C "$FLAKE_DIR" add -A
git -C "$FLAKE_DIR" commit --allow-empty -m "snapshot pre-cleanup-$TIME"
git -C "$FLAKE_DIR" tag "pre-cleanup-$TIME" HEAD
# the echos are to separate what each one is doing. Just for curiosity
echo "deadnix scans your Nix code and removes or reports unused (dead) variables and bindings"
deadnix --edit "$FLAKE_DIR" # removes unused code
echo "--------------------------------------------------------------"
echo "statix lints your Nix code to find stylistic issues, bad patterns, and potential mistakes."
statix fix "$FLAKE_DIR" # check other linting issues
echo "--------------------------------------------------------------"
echo "alejandra formats your Nix code consistently according to a strict, opinionated style."
alejandra "$FLAKE_DIR" # formats the config
echo "--------------------------------------------------------------"
if sudo /run/current-system/sw/bin/nixos-rebuild switch --flake "$FLAKE" 2> "$ERROR_FILE"; then # use /run/.../bin/ uses the sudoless rule
if ! git -C "$FLAKE_DIR" diff --quiet HEAD; then
git -C "$FLAKE_DIR" add -A
git -C "$FLAKE_DIR" commit -m "Auto: cleanup-$TIME"
git -C "$FLAKE_DIR" push
notify-send "Nix auto cleanup" "Everything OK"
matrix-commander-rs --verbose -m "Nix auto cleanup. Everything OK.<br><a href=\"https://matrix.to/#/@notificationbot_0000:matrix.org\">@notificationbot_0000</a>" \
--html \
-r "\!7j-78_02dHROeLj4Ns8F12eo4IiZGv4zNsQ_1-WlyIU"
else
notify-send "Nix auto cleanup" "No changes"
git -C "$FLAKE_DIR" push
fi
else
ERROR_MSG=$(cat "$ERROR_FILE")
notify-send -u critical "Nix auto cleanup" "FAILED"
matrix-commander-rs --verbose -m "Nix auto cleanup failed.<br>Error: <pre>$ERROR_MSG</pre><br><a href=\"https://matrix.to/#/@notificationbot_0000:matrix.org\">@notificationbot_0000</a>" \
--html \
-r "\!7j-78_02dHROeLj4Ns8F12eo4IiZGv4zNsQ_1-WlyIU"
git -C "$FLAKE_DIR" reset --hard "pre-cleanup-$TIME"
fi
git -C "$FLAKE_DIR" tag -d "pre-cleanup-$TIME" # removes the tag
rm -f "$ERROR_FILE"
'';
};
+109
View File
@@ -103,6 +103,115 @@
git -C "$FLAKE_DIR" tag -d "pre-autoupdate-$TIME" # removes the tag
rm -f "$ERROR_FILE"
'';
};
};
## desktop
flake.nixosModules.autoUpdate-desktop = {pkgs, ...}: {
# Ensure your script is available system-wide
environment.systemPackages = [
self.packages.${pkgs.system}.custom-autoupdate-desktop
];
users.users.tomasr = {
linger = true; # lingering is required
};
systemd.user.services.custom-autoupdate = {
description = "NixOS flake auto update";
serviceConfig = {
Type = "oneshot";
ExecStart = "/run/current-system/sw/bin/custom-autoupdate";
# safety for long rebuilds
TimeoutStartSec = "45min";
TimeoutStopSec = "10min";
# avoid overlap
RemainAfterExit = true;
# tweaks that should make the system run normally during the rebuilds
Nice = 10;
IOSchedulingClass = "best-effort";
IOSchedulingPriority = 7;
};
};
# Systemd USER timer
systemd.user.timers.custom-autoupdate = {
wantedBy = ["timers.target"];
timerConfig = {
OnCalendar = "Fri *-*-* 20:00:00"; # runs friday night. If for whatever reason something breaks. I have whole week-end to fix it.
Persistent = true; # if it happens during shutted down
# avoids thundering herd on boot
RandomizedDelaySec = "2h";
};
};
};
perSystem = {pkgs, ...}: {
packages.custom-autoupdate-desktop = pkgs.writeShellApplication {
name = "custom-autoupdate";
runtimeInputs = with pkgs; [
git
nixos-rebuild
matrix-commander-rs
libnotify
];
text = ''
set -e
FLAKE_DIR="/home/tomasr/nixos"
FLAKE="$FLAKE_DIR#desktop"
TIME=$(date -u +"%Y-%m-%dT%H-%M-%SZ")
ERROR_FILE=$(mktemp)
# snapshot current state
git -C "$FLAKE_DIR" add -A
git -C "$FLAKE_DIR" commit --allow-empty -m "snapshot pre-autoupdate-$TIME"
git -C "$FLAKE_DIR" tag "pre-autoupdate-$TIME" HEAD
# update lock only
nix flake update --flake "$FLAKE_DIR"
if sudo /run/current-system/sw/bin/nixos-rebuild switch --flake "$FLAKE" 2> "$ERROR_FILE"; then # use /run/.../bin/ uses the sudoless rule
if ! git -C "$FLAKE_DIR" diff --quiet -- flake.lock; then
git -C "$FLAKE_DIR" add flake.lock
git -C "$FLAKE_DIR" commit -m "flake.lock: autoupdate-$TIME"
git -C "$FLAKE_DIR" push
notify-send "Flake autoupdate" "Rebuild OK"
matrix-commander-rs --verbose -m "Flake rebuild succesfull.<br><a href=\"https://matrix.to/#/@notificationbot_0000:matrix.org\">@notificationbot_0000</a>" \
--html \
-r "\!7j-78_02dHROeLj4Ns8F12eo4IiZGv4zNsQ_1-WlyIU"
else
notify-send "Flake autoupdate" "No changes"
git -C "$FLAKE_DIR" push
fi
else
ERROR_MSG=$(cat "$ERROR_FILE")
notify-send -u critical "Flake autoupdate" "FAILED"
matrix-commander-rs --verbose -m "Flake rebuild failed.<br>Error: <pre>$ERROR_MSG</pre><br><a href=\"https://matrix.to/#/@notificationbot_0000:matrix.org\">@notificationbot_0000</a>" \
--html \
-r "\!7j-78_02dHROeLj4Ns8F12eo4IiZGv4zNsQ_1-WlyIU"
git -C "$FLAKE_DIR" reset --hard "pre-autoupdate-$TIME"
fi
git -C "$FLAKE_DIR" tag -d "pre-autoupdate-$TIME" # removes the tag
rm -f "$ERROR_FILE"
'';
};