diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..d525137 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,61 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## What This Is + +Personal NixOS system configuration for host `cesium` — a QEMU/KVM-virtualized x86_64 desktop workstation. Uses NixOS with Home Manager (channel-based, no Flakes). NixOS version is locked to 25.11. + +## Commands + +```bash +# Rebuild and apply configuration (aliased as 'rebuild') +sudo nixos-rebuild switch + +# Rebuild with package upgrades (aliased as 'update') +sudo nixos-rebuild switch --upgrade + +# Test configuration without persisting (loads into current session only) +sudo nixos-rebuild test + +# Build without applying (useful to check for errors) +sudo nixos-rebuild build + +# Optimize store and garbage collect (aliased as 'ngc') +sudo nix-store --optimise && sudo nix-collect-garbage -d + +# After first install: setup SMB credentials +sudo /etc/nixos/setup-smb-credentials.sh +``` + +## Architecture + +Entry point is `config/configuration.nix`, which imports all other modules: + +``` +config/configuration.nix # Top-level: imports all modules, enables Home Manager +├── hardware-configuration.nix # Auto-generated (gitignored), QEMU guest hardware +├── common.nix # System-wide: bootloader, locale, GNOME, PipeWire, packages +├── mounts.nix # CIFS/SMB mounts to TrueNAS (automount with systemd) +├── services.nix # Docker (custom data root /home/docker), ddev +├── users/sebastian.nix # User account, groups, SSH askpass +│ └── imports home.nix # Home Manager config for this user +├── home.nix # User environment: apps, shell, git, scripts, Flatpak +├── scripts.nix # Custom shell scripts (composer, lazydocker, gclb) +├── vm-guest.nix # Optional: SPICE agent for VM clipboard/file sharing +└── vm-host.nix # Optional: KVM/QEMU host with libvirtd, virt-manager +``` + +Key design patterns: +- `common.nix` handles all system-level config (boot, locale, desktop, audio, auto-updates, garbage collection) +- `home.nix` handles all user-level config via Home Manager (applications, shell aliases, git, vim, GTK theme, GNOME extensions, Flatpak activation scripts) +- `scripts.nix` defines Docker-wrapped CLI tools (composer, lazydocker) and git helpers using `writeShellScriptBin` +- `mounts.nix` uses systemd automount with 60s idle timeout for TrueNAS SMB shares +- `vm-guest.nix` and `vm-host.nix` are optional modules (not imported by default in configuration.nix) + +## Conventions + +- **Commit messages** use `[TASK]` prefix (e.g., `[TASK] Add filemounts`) +- **Formatting**: 2-space indentation for `.nix` files, 4-space for everything else (see `.editorconfig`) +- **Unfree packages** are allowed (`nixpkgs.config.allowUnfree = true`) +- `hardware-configuration.nix` is gitignored — it's auto-generated per machine \ No newline at end of file diff --git a/README.md b/README.md index 11e08eb..b2633ea 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,7 @@ sudo apt install qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils vir ``` - Video: QXL -- In `configuration.nix`: `services.spice-vdagentd.enable = true;` -- Falls die HDD zu klein ist: `qemu-img resize nixos.qcow2 +20G` +- If the HDD for the VM is too small: `qemu-img resize nixos.qcow2 +20G` ## Manuelle Installation (UEFI) @@ -20,15 +19,19 @@ sudo -i # Use german keyboard layout loadkeys de -# Short for all the stuff below !!! ONLY ON EMPTY DRIVES !!! +# Short for all the stuff below !!! TAKE CARE OF THE USERDATA !!! curl -L https://www.fischer.im/nixos/minimal-install --output install.sh chmod 744 ./install.sh ./install.sh + +reboot ``` +If you don't use the installation script, you need to follow the steps 2-8 + ### 2. Partitionierung -Das folgende Schema erstellt fuenf Partitionen auf `/dev/sda`: +The following schema creates four partitions on `/dev/sda`: | Partition | Typ | Groesse | Mountpoint | |-------------|----------------|-------------------|------------| @@ -37,26 +40,26 @@ Das folgende Schema erstellt fuenf Partitionen auf `/dev/sda`: | `/dev/sda3` | ext4 (Root) | Rest minus Home | `/` | | `/dev/sda4` | ext4 (Home) | 50% des Rests | `/home` | -**Hinweis:** Die Groessen muessen an die eigene Festplatte angepasst werden. Im Beispiel wird eine 100 GB Festplatte verwendet. +**HINT:** The sizes must be adapted to your hard drive. In the example it's assumed that a 100GB drive is in use. ```bash -# GPT-Partitionstabelle erstellen +# GPT-partition table parted /dev/sda -- mklabel gpt -# EFI-Partition (512 MB) +# EFI-partition (512 MB) parted /dev/sda -- mkpart esp fat32 1MB 512MB parted /dev/sda -- set 1 esp on -# Swap-Partition (8 GB) +# Swap-partition (8 GB) parted /dev/sda -- mkpart swap linux-swap 512MB 8626MB -# Root-Partition (ca. 45 GB) +# Root-partition (ca. 45 GB) parted /dev/sda -- mkpart root ext4 8636MB 40000MB -# Home-Partition (Rest) +# Home-partition (Rest) parted /dev/sda -- mkpart home ext4 40000MB 100% -# Ergebnis pruefen +# Check result parted /dev/sda -- print ``` @@ -96,55 +99,76 @@ mount /dev/disk/by-label/home /mnt/home swapon /dev/disk/by-label/swap ``` -### 6. Konfiguration generieren +### 6. Generate configuration ```bash nixos-generate-config --root /mnt ``` -Dies erzeugt zwei Dateien: -- `/mnt/etc/nixos/hardware-configuration.nix` — erkannte Hardware und Mountpoints -- `/mnt/etc/nixos/configuration.nix` — Grundkonfiguration +This creates two files: +- `/mnt/etc/nixos/hardware-configuration.nix` — detected hardware and mountpoints +- `/mnt/etc/nixos/configuration.nix` — Base configuration -### 7. Bootloader konfigurieren +### 7. Check the detected bootloader -In `/mnt/etc/nixos/configuration.nix` sicherstellen, dass der Bootloader korrekt eingerichtet ist: +Check in `/mnt/etc/nixos/configuration.nix`, that the bootloader is configured like this: ```nix -boot.loader = { - systemd-boot.enable = true; - efi.canTouchEfiVariables = true; -}; +{ + boot.loader = { + systemd-boot.enable = true; + efi.canTouchEfiVariables = true; + }; +} ``` -### 8. System installieren +### 8. Install system ```bash nixos-install -``` -Nach der Installation wird ein Root-Passwort abgefragt. Danach: +# After the installation the script sets your root password. (Test1) -```bash reboot ``` -### 9. Nach dem ersten Start +### 9. After the first reboot ```bash +curl --output release.tar.gz https://gitea.fischer.im/sebastian/nixos-cesium/archive/[0.0.2].tar.gz +tar xzf release.tar.gz +chmod 744 nixos-cesium/script/post-install.sh +./nixos-cesium/script/post-install.sh +``` + +If you don't use the post-installation script, follow the next step + +```bash +cp -r ~/nixos-cesium/config/* /etc/nixos/ + +# Remember to activate vm-guest.nix or vm-host.nix in configuration.nix + nix-channel --add https://github.com/nix-community/home-manager/archive/release-25.11.tar.gz home-manager nix-channel --update # Konfiguration anwenden -sudo nixos-rebuild switch +nixos-rebuild switch --option experimental-features "nix-command flakes" -# SMB-Zugangsdaten einrichten (falls Netzlaufwerke genutzt werden) +reboot +``` + +### 10. Post Installation + +Generate SMB-credentials (if network mounts are used) + +```bash sudo /etc/nixos/setup-smb-credentials.sh ``` ## Wartung +Optimise Nix Store and remove old generations + ```bash -# Nix Store optimieren und alte Generationen entfernen sudo nix-store --optimise && sudo nix-collect-garbage -d ``` diff --git a/config/config/crest_iv_black-cut.jpg b/config/config/crest_iv_black-cut.jpg new file mode 100644 index 0000000..d2fde55 Binary files /dev/null and b/config/config/crest_iv_black-cut.jpg differ diff --git a/config/configuration.nix b/config/configuration.nix index 41565eb..a13996c 100644 --- a/config/configuration.nix +++ b/config/configuration.nix @@ -1,7 +1,8 @@ { config, pkgs, ... }: { - imports = [ # Include the results of the hardware scan. + imports = [ + # Include the results of the hardware scan. ./hardware-configuration.nix ./common.nix ./mounts.nix @@ -11,13 +12,14 @@ ]; - # Home Manager Konfiguration + # Home Manager configuration home-manager.useGlobalPkgs = true; home-manager.useUserPackages = true; home-manager.backupFileExtension = "backup"; - # NixOS Version (nicht ändern nach Erstinstallation) + # NixOS Version (don't change after first installation) system.stateVersion = "25.11"; nixpkgs.config.allowUnfree = true; + nix.settings.experimental-features = [ "nix-command" "flakes" ]; } diff --git a/config/flakes.nix b/config/flakes.nix new file mode 100644 index 0000000..0bf61b5 --- /dev/null +++ b/config/flakes.nix @@ -0,0 +1,5 @@ +{ system ? "x86_64-linux" }: + +{ + hytale-launcher = (builtins.getFlake "github:TNAZEP/HytaleLauncherFlake").packages.${system}.default; +} \ No newline at end of file diff --git a/config/home.nix b/config/home.nix index 8d55161..33fc85b 100644 --- a/config/home.nix +++ b/config/home.nix @@ -3,6 +3,7 @@ let localScripts = import ./scripts.nix { inherit pkgs; }; + flakePackages = import ./flakes.nix {}; in { home.stateVersion = "25.11"; @@ -37,6 +38,7 @@ in lutris steam prismlauncher + flakePackages.hytale-launcher # Entwicklung jetbrains-toolbox @@ -90,6 +92,10 @@ in }; dconf.settings = { + "org/gnome/desktop/interface" = { + color-scheme = "prefer-dark"; + accent-color = "green"; + }; "org/gnome/desktop/wm/preferences" = { button-layout = "appmenu:minimize,maximize,close"; focus-mode = "sloppy"; @@ -103,6 +109,19 @@ in dash-to-dock.extensionUuid ]; }; + "org/gnome/desktop/background" = { + picture-uri = "file:///etc/nixos/config/crest_iv_black-cut.jpg"; + picture-uri-dark = "file:///etc/nixos/config/crest_iv_black-cut.jpg"; + picture-options = "centered"; + primary-color = "#000000"; + }; + "org/gnome/shell/extensions/dash-to-dock" = { + show-mounts = false; + show-trash = false; + }; + "org/gnome/shell/keybindings" = { + show-screenshot-ui = ["5"]; + }; }; programs.git = { @@ -203,7 +222,6 @@ in ]; }; - # Vim Konfiguration programs.vim = { enable = true; defaultEditor = true; @@ -224,7 +242,6 @@ in ''; }; - # Zsh mit Oh-My-Zsh und Powerlevel10k programs.zsh = { enable = true; enableCompletion = true; @@ -252,6 +269,9 @@ in }; initContent = '' + # Bell deaktivieren + unsetopt BEEP + # Powerlevel10k Konfiguration laden (falls vorhanden) [[ -f ~/.p10k.zsh ]] && source ~/.p10k.zsh ''; diff --git a/config/vm-guest.nix b/config/vm-guest.nix index aacb817..58fda5c 100644 --- a/config/vm-guest.nix +++ b/config/vm-guest.nix @@ -1,10 +1,24 @@ -{ pkgs, ... }: +{ pkgs, lib, ... }: +let + spice-vdagent-desktop = pkgs.makeDesktopItem { + name = "spice-vdagent-custom"; + desktopName = "Spice vdagent Custom"; + comment = "Startet das Clipboard für QEMU/Spice"; + exec = "${pkgs.spice-vdagent}/bin/spice-vdagent"; + terminal = false; + type = "Application"; + categories = [ "Network" ]; + extraConfig.StartupNotify = "false"; + extraConfig."X-GNOME-Autostart-enabled" = "true"; + }; +in { environment.systemPackages = with pkgs; [ spice-vdagent phodav wl-clipboard + spice-vdagent-desktop ]; # List services that you want to enable: @@ -13,20 +27,18 @@ services.gvfs.enable = true; services.qemuGuest.enable = true; + networking.hostName = lib.mkForce "cesium-vm"; + # Open ports in the firewall. networking.firewall.allowedTCPPorts = [ 9843 22 ]; # Enable the OpenSSH daemon. services.openssh.enable = true; - environment.etc."xdg/autostart/spice-vdagent-custom.desktop".text = '' - [Desktop Entry] - Name=Spice vdagent Custom - Comment=Startet das Clipboard für QEMU/Spice - Exec=${pkgs.spice-vdagent}/bin/spice-vdagent - Terminal=false - Type=Application - Categories=Network; - StartupNotify=false - X-GNOME-Autostart-enabled=true - ''; + users.users.sebastian.openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL/i/b9o5LKRr+h7vwq1dLCQ+vz9DTf4EvaLeCRUxtIZ sebastian@cesium" + ]; + + # Symlink für Autostart + environment.etc."xdg/autostart/spice-vdagent-custom.desktop".source = + "${spice-vdagent-desktop}/share/applications/spice-vdagent-custom.desktop"; } diff --git a/scripts/minimal-install.sh b/scripts/minimal-install.sh old mode 100644 new mode 100755 index a45065a..01ce8dd --- a/scripts/minimal-install.sh +++ b/scripts/minimal-install.sh @@ -4,46 +4,51 @@ sudo -i loadkeys de -lsbkl +lsblk +# Disk selection +DEFAULT_DISK="/dev/sda" +read -p "Disk to install to [${DEFAULT_DISK}]: " DISK +DISK="${DISK:-$DEFAULT_DISK}" + +if [ ! -b "${DISK}" ]; then + echo "Error: ${DISK} is not a valid block device." + exit 1 +fi + +echo "Using disk: ${DISK}" # Partitioning -read -p "Create partitions table? DELETES ALL DATA! (j/N): " answer -if [ "$answer" = "j" ] || [ "$answer" = "J" ]; then - # GPT-partition table creation - parted /dev/sda -- mklabel gpt +read -p "Create partitions table? DELETES ALL DATA! (j/N): " ANSWER +if [ "${ANSWER}" = "j" ] || [ "${ANSWER}" = "J" ]; then + # GPT-partition table + parted "${DISK}" -- mklabel gpt # EFI-partition (512 MB) - parted /dev/sda -- mkpart esp fat32 1MB 512MB - parted /dev/sda -- set 1 esp on + parted "${DISK}" -- mkpart esp fat32 1MB 512MB + parted "${DISK}" -- set 1 esp on # Swap-partition (8 GB) - parted /dev/sda -- mkpart swap linux-swap 512MB 8626MB + parted "${DISK}" -- mkpart swap linux-swap 512MB 8626MB # Root-partition (ca. 45 GB) - parted /dev/sda -- mkpart root ext4 8636MB 40000MB + parted "${DISK}" -- mkpart root ext4 8636MB 40000MB # Home-partition (Rest) - parted /dev/sda -- mkpart home ext4 40000MB 100% + parted "${DISK}" -- mkpart home ext4 40000MB 100% fi # Check results -parted /dev/sda -- print +parted "${DISK}" -- print +mkfs.fat -F 32 -n boot ${DISK}1 +mkswap -L swap ${DISK}2 +mkfs.ext4 -L nixos ${DISK}3 -# Format EFI-partition -mkfs.fat -F 32 -n boot /dev/sda1 - -# Format swap-partition -mkswap -L swap /dev/sda2 - -# Format root-partition -mkfs.ext4 -L nixos /dev/sda3 - -read -p "Home-Partition formatieren? LOESCHT BENUTZERDATEN! (j/N): " answer -if [ "$answer" = "j" ] || [ "$answer" = "J" ]; then +read -p "Format Home-partition? Deletes all userdata! (j/N): " ANSWER +if [ "${ANSWER}" = "j" ] || [ "${ANSWER}" = "J" ]; then # Format home-partition - mkfs.ext4 -L home /dev/sda4 + mkfs.ext4 -L home ${DISK}4 fi @@ -53,19 +58,25 @@ mount /dev/disk/by-label/nixos /mnt mkdir /mnt/boot mount -o umask=077 /dev/disk/by-label/boot /mnt/boot -mkdir -p /mnt/home -mount /dev/disk/by-label/home /mnt/home - # Activate swap swapon /dev/disk/by-label/swap +mkdir -p /mnt/home +mount /dev/disk/by-label/home /mnt/home + + +echo "If you want to configure additional partitions, this is the right moment." +echo "Switch to console with [Ctrl + Z] and return with [fg] continue after that." +read -p "Continue?" + nixos-generate-config --root /mnt +nixos-install # If root password wasn't set because the installation needed to be restarted. -read -p "Root-Passwort mit nixos-enter setzen? (j/N): " answer -if [ "$answer" = "j" ] || [ "$answer" = "J" ]; then +read -p "Set Root-password with nixos-enter? (j/N): " ANSWER +if [ "${ANSWER}" = "j" ] || [ "${ANSWER}" = "J" ]; then nixos-enter --root '/mnt' passwd fi diff --git a/scripts/post-install.sh b/scripts/post-install.sh new file mode 100755 index 0000000..191f28c --- /dev/null +++ b/scripts/post-install.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env sh + +sudo -i + +cp -r ~/nixos-cesium/config/* /etc/nixos/ + +# VM module activation +echo "" +echo "Select what configuration to include?" +echo " 1) vm-guest.nix (VM runs inside a hypervisor)" +echo " 2) vm-host.nix (System runs VMs via libvirtd)" +echo " n) None" +read -p "Selection [n]: " VM_CHOICE +VM_CHOICE="${VM_CHOICE:-n}" + +case "${VM_CHOICE}" in + 1) + sed -i 's|# ./vm-guest.nix|./vm-guest.nix|' /etc/nixos/configuration.nix + echo "vm-guest.nix activated." + ;; + 2) + sed -i 's|# ./vm-guest.nix|./vm-host.nix|' /etc/nixos/configuration.nix + echo "vm-host.nix activated." + ;; + *) + echo "No VM module activated." + ;; +esac + +nix-channel --add https://github.com/nix-community/home-manager/archive/release-25.11.tar.gz home-manager +nix-channel --update + +nixos-rebuild switch --option experimental-features "nix-command flakes"