Compare commits

...

3 commits

Author SHA1 Message Date
7ac1e734e7
chore fixes and gaming 2026-06-27 07:44:09 -03:00
91c08fcab7
attempt at fixing ventoy 2026-06-27 05:38:38 -03:00
1adcfe0a12
some fixes 2026-06-27 05:38:38 -03:00
12 changed files with 271 additions and 78 deletions

View file

@ -8,6 +8,7 @@ Personal NixOS configuration using the [den](https://github.com/vic/den) framewo
|------------|----------------------|--------| |------------|----------------------|--------|
| `desktop` | Gaming + development | Nvidia | | `desktop` | Gaming + development | Nvidia |
| `notebook` | Portable development | Intel | | `notebook` | Portable development | Intel |
| `work` | Portable development | AMD + Nvidia (PRIME) |
## Prerequisites ## Prerequisites
@ -43,6 +44,64 @@ just gc
just diff just diff
``` ```
## Installing on a new machine (notebook)
Only the `notebook` host supports automated installation via the installer ISO.
No hardware-specific preparation is needed beforehand — the installer detects the
hardware automatically using `nixos-generate-config`.
### 1. Build and flash the ISO
The ISO embeds the flake at build time, so **all changes must be committed first**.
```bash
# Commit any pending changes — the ISO only includes git-tracked files
git add -A && git commit -m "pre-install snapshot"
just iso
sudo dd if=result/iso/*.iso of=/dev/sdX bs=4M status=progress && sync
```
### 2. Boot and install
Boot the ISO on the target machine. The installer logs in as root automatically.
**If you need Wi-Fi**, the script will prompt you to connect via `nmtui` before proceeding.
Run the installer:
```bash
nixos-install-host
```
The script will:
1. Prompt to set up network (Wi-Fi via `nmtui` if needed)
2. Ask which host to install (`notebook`)
3. **Auto-detect hardware** with `nixos-generate-config` and inject the result into the flake
4. Show available disks and confirm the target
5. Ask for the age key (`keys.txt`) — copy it to a USB or provide the path manually
6. Partition the disk with LUKS + btrfs via disko (prompts for LUKS passphrase)
7. Run `nixos-install`
8. Copy the flake (with detected hardware config) to `~/repos/nixos` on the new system
### 3. Age key
The age key used to encrypt `secrets/secrets.yaml` must be available during installation.
Bring it on a USB drive — the installer will find it automatically at `/run/media/*/keys.txt`.
### 4. After the first boot
Commit the auto-detected hardware config so future ISO builds include it:
```bash
cd ~/repos/nixos
git add modules/_hardware/notebook-hardware.nix
git commit -m "add notebook hardware config"
git push
```
> **Note:** GRUB will ask for the LUKS passphrase once during boot, and the initrd will ask
> again to mount the root filesystem. This is expected behavior with `enableCryptodisk`.
## Secrets (SOPS + age) ## Secrets (SOPS + age)
Secrets are stored encrypted in `secrets/secrets.yaml` and decrypted at boot by [sops-nix](https://github.com/Mic92/sops-nix). Secrets are stored encrypted in `secrets/secrets.yaml` and decrypted at boot by [sops-nix](https://github.com/Mic92/sops-nix).

View file

@ -35,9 +35,13 @@
let let
system = "x86_64-linux"; system = "x86_64-linux";
pkgs = inputs.nixpkgs.legacyPackages.${system}; pkgs = inputs.nixpkgs.legacyPackages.${system};
pkgs-unstable = import inputs.nixpkgs-unstable {
inherit system;
config.allowUnfree = true;
};
flake = (inputs.nixpkgs.lib.evalModules { flake = (inputs.nixpkgs.lib.evalModules {
modules = [ (inputs.import-tree ./modules) ]; modules = [ (inputs.import-tree ./modules) ];
specialArgs.inputs = inputs; specialArgs = { inherit inputs pkgs-unstable; };
}).config.flake; }).config.flake;
in flake // { in flake // {
nixosConfigurations = flake.nixosConfigurations // { nixosConfigurations = flake.nixosConfigurations // {

View file

@ -14,23 +14,71 @@ let
warn() { echo -e "''${YELLOW}[warn]''${NC} $1"; } warn() { echo -e "''${YELLOW}[warn]''${NC} $1"; }
die() { echo -e "''${RED}[error]''${NC} $1"; exit 1; } die() { echo -e "''${RED}[error]''${NC} $1"; exit 1; }
FLAKE="path:/etc/nixos-config" # ------------------------------------------------------------------ #
# Network #
# ------------------------------------------------------------------ #
header "Network"
echo "An internet connection is required to download packages during installation."
echo "If you need Wi-Fi, connect now with: nmtui"
echo ""
read -p "Press Enter when the network is ready (or Ctrl-C to abort)..."
# ------------------------------------------------------------------ #
# Host selection #
# ------------------------------------------------------------------ #
header "NixOS Installer" header "NixOS Installer"
echo "Evaluating flake..."
HOSTS_JSON=$(nix eval "path:/etc/nixos-config#nixosConfigurations" \
--apply builtins.attrNames --json) \
|| die "Failed to evaluate the flake at /etc/nixos-config."
echo "Available hosts:" echo "Available hosts:"
nix eval "$FLAKE#nixosConfigurations" --apply builtins.attrNames --json 2>/dev/null \ echo "$HOSTS_JSON" | ${pkgs.jq}/bin/jq -r '.[]' | grep -v installer | sed 's/^/ /'
| ${pkgs.jq}/bin/jq -r '.[]' | grep -v installer | sed 's/^/ /'
echo "" echo ""
read -p "Host to install: " HOST read -p "Host to install: " HOST
[ -z "$HOST" ] && die "No host specified." [ -z "$HOST" ] && die "No host specified."
# Verify the selected host has disko configured before touching anything.
# local.notebook.disk is only defined for hosts that include notebook-disko.nix.
echo "Checking that '$HOST' supports automated installation..."
nix eval "path:/etc/nixos-config#nixosConfigurations.$HOST.config.local.notebook.disk" \
--raw > /dev/null 2>&1 \
|| die "Host '$HOST' does not have a disko configuration. Only 'notebook' is supported."
ok "Host '$HOST' is supported."
# ------------------------------------------------------------------ #
# Hardware detection #
# ------------------------------------------------------------------ #
header "Detecting hardware"
echo "Running nixos-generate-config..."
DETECTED_HW=$(nixos-generate-config --no-filesystems --show-hardware-config 2>/dev/null) \
|| die "Failed to detect hardware. Is nixos-generate-config available?"
ok "Hardware detected."
# Build a writable copy of the embedded flake and inject the detected
# hardware config so both disko and nixos-install use the right modules.
echo "Preparing installation flake..."
rm -rf /tmp/nixos-flake
cp -rL /etc/nixos-config /tmp/nixos-flake
echo "$DETECTED_HW" > /tmp/nixos-flake/modules/_hardware/notebook-hardware.nix
ok "Hardware config written to flake."
FLAKE="path:/tmp/nixos-flake"
# ------------------------------------------------------------------ #
# Disk selection #
# ------------------------------------------------------------------ #
header "Available disks" header "Available disks"
lsblk -d -o NAME,SIZE,MODEL --noheadings | grep -v loop lsblk -d -o NAME,SIZE,MODEL --noheadings | grep -v loop
echo "" echo ""
CONFIGURED_DISK=$(nix eval "$FLAKE#nixosConfigurations.$HOST.config.local.notebook.disk" --raw 2>/dev/null \ CONFIGURED_DISK=$(nix eval "$FLAKE#nixosConfigurations.$HOST.config.local.notebook.disk" \
|| echo "/dev/nvme0n1") --raw 2>/dev/null || echo "/dev/nvme0n1")
echo -e "Disk configured for this host: ''${BOLD}$CONFIGURED_DISK''${NC}" echo -e "Disk configured for this host: ''${BOLD}$CONFIGURED_DISK''${NC}"
read -p "Target disk [$CONFIGURED_DISK]: " DISK_INPUT read -p "Target disk [$CONFIGURED_DISK]: " DISK_INPUT
DISK="''${DISK_INPUT:-$CONFIGURED_DISK}" DISK="''${DISK_INPUT:-$CONFIGURED_DISK}"
@ -39,13 +87,23 @@ let
if [ "$DISK" != "$CONFIGURED_DISK" ]; then if [ "$DISK" != "$CONFIGURED_DISK" ]; then
warn "Disk $DISK differs from configured $CONFIGURED_DISK." warn "Disk $DISK differs from configured $CONFIGURED_DISK."
warn "Edit modules/_hardware/<host>-disko.nix and rebuild the ISO if it doesn't match." warn "The disko config will use $DISK regardless, but update local.notebook.disk in"
warn "modules/_hardware/notebook-disko.nix and commit it after installation."
fi fi
# ------------------------------------------------------------------ #
# Age key #
# ------------------------------------------------------------------ #
header "Age key (secrets decryption)" header "Age key (secrets decryption)"
KEYS_PATH="" KEYS_PATH=""
for candidate in /run/media/nixos/*/keys.txt /run/media/*/keys.txt /tmp/keys.txt; do # Search already-mounted media (standard auto-mount paths)
for candidate in \
/run/media/nixos/*/keys.txt \
/run/media/*/keys.txt \
/run/media/*/*/keys.txt \
/tmp/keys.txt; do
if [ -f "$candidate" ]; then if [ -f "$candidate" ]; then
KEYS_PATH="$candidate" KEYS_PATH="$candidate"
ok "Found at $KEYS_PATH" ok "Found at $KEYS_PATH"
@ -53,16 +111,48 @@ let
fi fi
done done
# When booting via Ventoy the USB data partition (label "Ventoy") is not
# auto-mounted in the live environment — only the ISO loop device is set up.
# Detect it by label, mount read-only, copy keys.txt to /tmp, then unmount.
if [ -z "$KEYS_PATH" ]; then
VENTOY_DEV=$(${pkgs.util-linux}/bin/blkid -t LABEL="Ventoy" -o device 2>/dev/null | head -1 || true)
if [ -n "$VENTOY_DEV" ]; then
warn "keys.txt not found in mounted media. Trying Ventoy partition ($VENTOY_DEV)..."
VENTOY_MNT=$(mktemp -d)
if mount -o ro "$VENTOY_DEV" "$VENTOY_MNT" 2>/dev/null; then
if [ -f "$VENTOY_MNT/keys.txt" ]; then
cp "$VENTOY_MNT/keys.txt" /tmp/keys.txt
chmod 600 /tmp/keys.txt
KEYS_PATH="/tmp/keys.txt"
ok "Found on Ventoy USB copied to /tmp/keys.txt"
else
warn "Ventoy partition mounted but no keys.txt found at its root."
echo "Contents of Ventoy root:"
ls "$VENTOY_MNT" | sed 's/^/ /'
fi
umount "$VENTOY_MNT" 2>/dev/null || true
rm -rf "$VENTOY_MNT"
else
warn "Could not mount Ventoy partition $VENTOY_DEV."
fi
fi
fi
if [ -z "$KEYS_PATH" ]; then if [ -z "$KEYS_PATH" ]; then
warn "Age key not found automatically." warn "Age key not found automatically."
echo "Options:" echo "Options:"
echo " 1. Copy keys.txt to a USB, mount it, and it will be found at /run/media/*" echo " 1. Place keys.txt at the root of the Ventoy USB (alongside the .iso)"
echo " 2. Enter the path manually below" echo " 2. Mount another USB and it will be found at /run/media/*"
echo " 3. Enter the path manually below"
read -p "Path to keys.txt: " KEYS_PATH read -p "Path to keys.txt: " KEYS_PATH
fi fi
[ ! -f "$KEYS_PATH" ] && die "Age key not found at $KEYS_PATH" [ ! -f "$KEYS_PATH" ] && die "Age key not found at $KEYS_PATH"
# ------------------------------------------------------------------ #
# Confirmation #
# ------------------------------------------------------------------ #
header "Confirmation" header "Confirmation"
echo -e " Host : ''${BOLD}$HOST''${NC}" echo -e " Host : ''${BOLD}$HOST''${NC}"
echo -e " Disk : ''${BOLD}$DISK''${NC} (ALL DATA WILL BE ERASED)" echo -e " Disk : ''${BOLD}$DISK''${NC} (ALL DATA WILL BE ERASED)"
@ -71,6 +161,10 @@ let
read -p "Type 'yes' to continue: " CONFIRM read -p "Type 'yes' to continue: " CONFIRM
[ "$CONFIRM" != "yes" ] && { echo "Aborted."; exit 1; } [ "$CONFIRM" != "yes" ] && { echo "Aborted."; exit 1; }
# ------------------------------------------------------------------ #
# Installation #
# ------------------------------------------------------------------ #
header "Partitioning and formatting" header "Partitioning and formatting"
echo "(You will be prompted to set the LUKS passphrase.)" echo "(You will be prompted to set the LUKS passphrase.)"
disko --mode destroy,format,mount --flake "$FLAKE#$HOST" disko --mode destroy,format,mount --flake "$FLAKE#$HOST"
@ -83,14 +177,41 @@ let
header "Installing NixOS" header "Installing NixOS"
nixos-install --root /mnt --flake "$FLAKE#$HOST" --no-root-passwd nixos-install --root /mnt --flake "$FLAKE#$HOST" --no-root-passwd
# ------------------------------------------------------------------ #
# Post-install: save config to the new system #
# ------------------------------------------------------------------ #
header "Saving configuration"
# Copy the flake (including the detected hardware config) to the user's
# working directory on the installed system so they can commit it.
mkdir -p /mnt/home/zoty/repos
cp -r /tmp/nixos-flake /mnt/home/zoty/repos/nixos
# UID 1000 is the first normal user, matching the zoty account.
chown -R 1000:1000 /mnt/home/zoty/repos/nixos
ok "Configuration saved to ~/repos/nixos on the installed system."
echo "" echo ""
ok "Installation complete! Remove the USB drive and reboot." ok "Installation complete! Remove the USB drive and reboot."
echo ""
echo "After the first boot, commit the detected hardware config:"
echo " cd ~/repos/nixos"
echo " git add modules/_hardware/notebook-hardware.nix"
echo " git commit -m 'add notebook hardware config'"
echo " git push"
''; '';
in { in {
imports = [ imports = [
"${modulesPath}/installer/cd-dvd/installation-cd-minimal.nix" "${modulesPath}/installer/cd-dvd/installation-cd-minimal.nix"
]; ];
# Ventoy presents the ISO as a virtual CDROM without the filesystem label
# that NixOS stage-1 expects (nixos-minimal-*). Stage-1 cannot find the
# loop device for nix-store.squashfs, causing "unable to read id index table".
# copytoram loads the entire ISO into RAM before the squashfs mount, removing
# the dependency on the Ventoy device remaining accessible during boot.
# See: https://github.com/NixOS/nixpkgs/issues/245101
boot.kernelParams = [ "copytoram" ];
services.getty.autologinUser = lib.mkForce "root"; services.getty.autologinUser = lib.mkForce "root";
nix.settings = { nix.settings = {
@ -112,7 +233,9 @@ in {
pkgs.neovim pkgs.neovim
]; ];
# Embed the flake source so the install script can reference it at path:/etc/nixos-config # Embed the flake source so the install script can copy it at install time.
# The script copies it to /tmp/nixos-flake (writable) and injects the
# detected hardware config before running disko and nixos-install.
environment.etc."nixos-config".source = ../.; environment.etc."nixos-config".source = ../.;
documentation.enable = lib.mkForce false; documentation.enable = lib.mkForce false;

View file

@ -1,17 +1,28 @@
# Hardware-specific configuration for the notebook. # Notebook hardware configuration.
# fileSystems and swap are declared by disko (notebook-disko.nix). #
# Regenerate this file with: nixos-generate-config --no-filesystems --show-hardware-config # This file is REPLACED automatically during installation.
{ config, lib, modulesPath, ... }: # The installer runs:
# nixos-generate-config --no-filesystems --show-hardware-config
# and writes the output here before calling nixos-install.
#
# After installation, commit the generated file:
# git add modules/_hardware/notebook-hardware.nix
# git commit -m "add notebook hardware config"
#
# To regenerate on the installed system:
# nixos-generate-config --no-filesystems --show-hardware-config \
# > ~/repos/nixos/modules/_hardware/notebook-hardware.nix
{ lib, modulesPath, ... }:
{ {
imports = [ imports = [
(modulesPath + "/installer/scan/not-detected.nix") (modulesPath + "/installer/scan/not-detected.nix")
]; ];
boot.initrd.availableKernelModules = [ "xhci_pci" "ehci_pci" "ahci" "usb_storage" "ums_realtek" "sd_mod" "sr_mod" ]; # Filled in by the installer. These are placeholder values that allow
boot.kernelModules = [ "kvm-intel" ]; # the flake to evaluate before the real hardware is detected.
boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" ];
boot.kernelModules = [];
boot.extraModulePackages = []; boot.extraModulePackages = [];
networking.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
} }

View file

@ -9,7 +9,7 @@
]; ];
boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" ]; boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" ];
boot.initrd.kernelModules = [ ]; boot.initrd.kernelModules = [ "amdgpu" ];
boot.kernelModules = [ "kvm-amd" ]; boot.kernelModules = [ "kvm-amd" ];
boot.extraModulePackages = [ ]; boot.extraModulePackages = [ ];

View file

@ -1,11 +1,5 @@
{ den, inputs, ... }: { { den, pkgs-unstable, ... }: {
den.aspects.creative.nixos = { pkgs, ... }: den.aspects.creative.nixos = { ... }: {
let
pkgs-unstable = import inputs.nixpkgs-unstable {
system = pkgs.stdenv.hostPlatform.system;
config.allowUnfree = true;
};
in {
environment.systemPackages = with pkgs-unstable; [ environment.systemPackages = with pkgs-unstable; [
# 3D # 3D
blender blender

View file

@ -68,10 +68,10 @@ in {
den.aspects.dev den.aspects.dev
den.aspects.creative den.aspects.creative
den.aspects.secrets den.aspects.secrets
den.aspects.steam den.aspects.gaming
den.aspects.prismlauncher
den.aspects.androidcam den.aspects.androidcam
den.aspects.winvm den.aspects.winvm
den.aspects.leisure
]; ];
nixos = { nixos = {
system.stateVersion = "25.11"; system.stateVersion = "25.11";

View file

@ -1,14 +1,8 @@
{ den, inputs, config, ... }: { den, pkgs-unstable, config, ... }:
let let
username = config.local.identity.username; username = config.local.identity.username;
in { in {
den.aspects.dev.nixos = { pkgs, ... }: den.aspects.dev.nixos = { pkgs, ... }: {
let
pkgs-unstable = import inputs.nixpkgs-unstable {
system = pkgs.stdenv.hostPlatform.system;
config.allowUnfree = true;
};
in {
environment.systemPackages = with pkgs-unstable; [ environment.systemPackages = with pkgs-unstable; [
# CLI utilities # CLI utilities
gcc gcc
@ -72,6 +66,7 @@ in {
virtualisation.docker = { virtualisation.docker = {
enable = true; enable = true;
enableOnBoot = false;
package = pkgs-unstable.docker_29; package = pkgs-unstable.docker_29;
}; };
users.users.${username}.extraGroups = [ "docker" ]; users.users.${username}.extraGroups = [ "docker" ];

View file

@ -1,7 +1,13 @@
{ den, ... }: { { den, pkgs-unstable, ... }: {
den.aspects.steam.nixos = { pkgs, ... }: { den.aspects.gaming.nixos = { pkgs, ... }: {
hardware.graphics = {
enable = true;
enable32Bit = true;
};
programs.steam = { programs.steam = {
enable = true; enable = true;
package = pkgs-unstable.steam;
remotePlay.openFirewall = false; remotePlay.openFirewall = false;
dedicatedServer.openFirewall = false; dedicatedServer.openFirewall = false;
@ -12,23 +18,19 @@
extraCompatPackages = with pkgs; [ extraCompatPackages = with pkgs; [
proton-ge-bin proton-ge-bin
]; ];
# Extra packages that steam might need
extraPackages = with pkgs; [
xorg.libXcursor
xorg.libXi
xorg.libXinerama
xorg.libXScrnSaver
libpng
libpulseaudio
libvorbis
stdenv.cc.cc.lib
libkrb5
keyutils
];
}; };
# Fonts for better game text rendering environment.systemPackages = with pkgs; [
(prismlauncher.override {
jdks = [
temurin-bin-8
temurin-bin-17
temurin-bin-21
temurin-bin-25
];
})
];
fonts.packages = with pkgs; [ fonts.packages = with pkgs; [
liberation_ttf liberation_ttf
wqy_zenhei wqy_zenhei

18
modules/leisure.nix Normal file
View file

@ -0,0 +1,18 @@
{ den, pkgs-unstable, ... }: {
den.aspects.leisure.nixos = { ... }: {
environment.systemPackages = with pkgs-unstable; [
# Streaming
stremio-linux-shell
# Torrenting
qbittorrent
# Media playback
mpv
yt-dlp
# Social
discord
];
};
}

View file

@ -14,9 +14,10 @@
services.thermald.enable = true; services.thermald.enable = true;
boot = { boot = {
initrd.availableKernelModules = [ "xhci_pci" "ahci" "usbhid" "sd_mod" ]; # Hardware-specific modules (kvm-intel/kvm-amd, nvme, etc.) come from
# modules/_hardware/notebook-hardware.nix, generated during installation
# by nixos-generate-config --no-filesystems --show-hardware-config.
initrd.kernelModules = [ "dm-crypt" ]; initrd.kernelModules = [ "dm-crypt" ];
kernelModules = [ "kvm-intel" ];
initrd.compressor = "zstd"; initrd.compressor = "zstd";
loader = { loader = {

View file

@ -1,14 +0,0 @@
{ den, ...}: {
den.aspects.prismlauncher.nixos = { pkgs, ... }: {
environment.systemPackages = with pkgs; [
(prismlauncher.override {
jdks = [
temurin-bin-8
temurin-bin-17
temurin-bin-21
temurin-bin-25
];
})
];
};
}