diff --git a/flake.lock b/flake.lock
index 39566af..bdde15f 100755
--- a/flake.lock
+++ b/flake.lock
@@ -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",
diff --git a/flake.nix b/flake.nix
index 5d51296..ed6a709 100644
--- a/flake.nix
+++ b/flake.nix
@@ -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;
diff --git a/modules/applications/hyprland.nix b/modules/applications/hyprland.nix
index c4de24a..e9e25d4 100644
--- a/modules/applications/hyprland.nix
+++ b/modules/applications/hyprland.nix
@@ -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 {
diff --git a/modules/applications/zsh.nix b/modules/applications/zsh.nix
index b63a7db..6e82f18 100644
--- a/modules/applications/zsh.nix
+++ b/modules/applications/zsh.nix
@@ -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 = {
diff --git a/modules/hardware/bootloader.nix b/modules/hardware/bootloader.nix
index bfd1f1a..54b6a3d 100644
--- a/modules/hardware/bootloader.nix
+++ b/modules/hardware/bootloader.nix
@@ -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;
diff --git a/modules/hardware/disko/README.md b/modules/hardware/disko/README.md
new file mode 100644
index 0000000..d9cf7fc
--- /dev/null
+++ b/modules/hardware/disko/README.md
@@ -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.
diff --git a/modules/hardware/disko/disko-config.nix b/modules/hardware/disko/disko-config.nix
new file mode 100644
index 0000000..65d5c14
--- /dev/null
+++ b/modules/hardware/disko/disko-config.nix
@@ -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";
+ };
+ };
+ };
+ };
+ };
+ };
+};
+}
diff --git a/modules/hosts/desktop.nix b/modules/hosts/desktop.nix
new file mode 100644
index 0000000..6d348d8
--- /dev/null
+++ b/modules/hosts/desktop.nix
@@ -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. It‘s 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;
+ };*/
+}
diff --git a/modules/parts.nix b/modules/parts.nix
index dfc6adb..ed5411c 100644
--- a/modules/parts.nix
+++ b/modules/parts.nix
@@ -3,6 +3,7 @@
imports = [
# adds home-manager options to flake-parts
inputs.home-manager.flakeModules.home-manager
+ inputs.disko.flakeModules.default
];
config.systems = [
diff --git a/modules/utilities/autoCleanup.nix b/modules/utilities/autoCleanup.nix
index 21641f9..d11d824 100644
--- a/modules/utilities/autoCleanup.nix
+++ b/modules/utilities/autoCleanup.nix
@@ -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.
@notificationbot_0000" \
+ --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.
Error:
$ERROR_MSG
$ERROR_MSG