NixOS Flakes❄️
automatisierte VM Installation mittels NixOS Flakes
NixOS Installation¶
Für die Installation via NixOS Flakes muss ein Git-Repo mit den entsprechenden Dateien erstellt werden. Das Repo wird dann in die laufende ISO geclont und die Nix Installation gestartet. Damit die Installation noch einfacher abläuft, wurde das install.sh script erstellt um die Installation automatisiert ablaufen zu lassen. Ohne das Script muss die Partitionierung von Hand erfolgen und auch die mount-Pfade müssen erstellt werden.
Das Script installiert NixOS automatisch auf vdb, sollte eure Festplatte anders heißen, muss dies im install.sh angepasst werden.
manuele Schritte¶
1. Festplatte formatieren und mounten¶
parted /dev/vdb -- mklabel gpt
parted /dev/vdb -- mkpart ESP fat32 1MiB 513MiB
parted /dev/vdb -- set 1 esp on
parted /dev/vdb -- mkpart primary 513MiB 100%
mkfs.vfat -F32 -n EFI /dev/vdb1
mkfs.ext4 -L nixos /dev/vdb2
mount /dev/disk/by-label/nixos /mnt
mkdir -p /mnt/boot
mount /dev/disk/by-label/EFI /mnt/boot2. nixos Hardware Konfiguration erstellen¶
nixos-generate-config --root /mnt --show-hardware-config > /mnt/etc/nixos/hosts/nix-host1/hardware-configuration.nix3. git clone¶
git clone --config core.sshCommand="ssh -i ~/.ssh/key -p 222" ssh://git@git.DEINREPO/nixos-flakes.git /mnt/etc/nixos4. Installation starten¶
nixos-install --flake /mnt/etc/nixos#nix-host1Git Repo Struktur¶
nixos-flakes
├─ flake.nix
├─ nixos-setup.sh
├─ .gitignore
├─ README.md
└─ hosts/
└─ nix-host1/
├─ configuration.nix
└─ hardware-configuration.nixDateien¶
flake.nix Konfig¶
🛠 flake.nix
{
description = "Single-host NixOS flake (nix-host1)";
inputs = {
# Auf aktuelle Stable pinnen
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05";
};
outputs = { self, nixpkgs }:
let
lib = nixpkgs.lib;
in {
nixosConfigurations = {
nix-host1 = lib.nixosSystem {
# Moderne Schreibweise: Host-Architektur als Option setzen
modules = [
{ nixpkgs.hostPlatform = "x86_64-linux"; } # bei ARM: "aarch64-linux"
./hosts/nix-host1/configuration.nix
];
};
};
};
}install.sh Script¶
#!/bin/sh
# NixOS Autoinstall für /dev/vdb + Git-Klon via benutzerdefiniertem SSH-Key/Port
# Kompatibel mit /bin/sh, geeignet für "curl ... | sh"
set -eu
REPO_SSH='ssh://git@DEINREPO'
REPO_PORT='22'
DISK='/dev/vdb'
EFI_LABEL='EFI'
ROOT_LABEL='nixos'
MNT='/mnt'
CLONE_DIR="$MNT/etc/nixos"
HOST_NAME='nix-host1'
HWC_PATH="$CLONE_DIR/hosts/$HOST_NAME/hardware-configuration.nix"
KEY_DIR="$HOME/.ssh"
KEY_FILE="$KEY_DIR/key"
KNOWN_HOSTS="$KEY_DIR/known_hosts"
need_cmd() {
command -v "$1" >/dev/null 2>&1 || {
echo "Fehler: benötigtes Kommando nicht gefunden: $1" >&2
exit 1
}
}
# Root-Prüfung
if [ "$(id -u)" -ne 0 ]; then
echo "Bitte als root ausführen." >&2
exit 1
fi
# Benötigte Tools prüfen
for c in parted mkfs.vfat mkfs.ext4 mount git nixos-generate-config nixos-install; do
need_cmd "$c"
done
echo "⚠️ Dieses Skript löscht und partitioniert $DISK vollständig."
printf "Gib 'YES' ein, um fortzufahren: " >/dev/tty
ANS=''
IFS= read -r ANS </dev/tty || true
if [ "$ANS" != "YES" ]; then
echo "Abgebrochen."
exit 1
fi
# SSH-Key interaktiv einsammeln (über /dev/tty)
echo
echo "Bitte füge jetzt deinen privaten SSH-Schlüssel ein."
echo "(Beende die Eingabe mit einer einzelnen Zeile: EOF)"
mkdir -p "$KEY_DIR"
chmod 700 "$KEY_DIR"
: > "$KEY_FILE"
chmod 600 "$KEY_FILE"
while IFS= read -r line </dev/tty; do
[ "$line" = "EOF" ] && break
printf '%s\n' "$line" >> "$KEY_FILE"
done
# Optional: Host-Key einsammeln (vermeidet Interaktion bei erstem Git-Zugriff)
if command -v ssh-keyscan >/dev/null 2>&1; then
echo "Hole SSH-Host-Key von git.knoll-systems.de:$REPO_PORT ..."
ssh-keyscan -p "$REPO_PORT" git.knoll-systems.de 2>/dev/null >> "$KNOWN_HOSTS" || true
chmod 600 "$KNOWN_HOSTS" || true
fi
echo
echo "Starte Partitionierung von $DISK ..."
umount "$MNT/boot" 2>/dev/null || true
umount "$MNT" 2>/dev/null || true
parted -s "$DISK" mklabel gpt
parted -s "$DISK" mkpart ESP fat32 1MiB 513MiB
parted -s "$DISK" set 1 esp on
parted -s "$DISK" mkpart primary 513MiB 100%
# Kernel/udev informieren
command -v partprobe >/dev/null 2>&1 && partprobe "$DISK" || true
command -v udevadm >/dev/null 2>&1 && { udevadm trigger --subsystem-match=block || true; udevadm settle || true; }
sleep 1
echo "Formatiere Dateisysteme ..."
mkfs.vfat -F 32 -n "$EFI_LABEL" "${DISK}1"
mkfs.ext4 -L "$ROOT_LABEL" "${DISK}2"
# Erneut sicherstellen, dass Devices/Symlinks da sind
command -v partprobe >/dev/null 2>&1 && partprobe "$DISK" || true
command -v udevadm >/dev/null 2>&1 && { udevadm trigger --subsystem-match=block || true; udevadm settle || true; }
sleep 1
# Device-Pfade (Label bevorzugt, sonst direkter Gerätename)
ROOT_DEV="/dev/disk/by-label/$ROOT_LABEL"; [ -e "$ROOT_DEV" ] || ROOT_DEV="${DISK}2"
EFI_DEV="/dev/disk/by-label/$EFI_LABEL"; [ -e "$EFI_DEV" ] || EFI_DEV="${DISK}1"
echo "Mounten ..."
# 1) Root mounten
mkdir -p "$MNT"
mount "$ROOT_DEV" "$MNT"
# 2) Boot-Mountpoint *nach* Root-Mount anlegen (wichtig!)
mkdir -p "$MNT/boot"
mount "$EFI_DEV" "$MNT/boot"
echo "Klonen des Repos nach $CLONE_DIR ..."
mkdir -p "$(dirname "$CLONE_DIR")"
git clone --config core.sshCommand="ssh -i $KEY_FILE -p $REPO_PORT" \
"$REPO_SSH" "$CLONE_DIR"
echo "Erzeuge hardware-configuration.nix ..."
mkdir -p "$(dirname "$HWC_PATH")"
nixos-generate-config --root "$MNT" --show-hardware-config > "$HWC_PATH"
echo "Starte NixOS-Installation mit Flake $CLONE_DIR#$HOST_NAME ..."
nixos-install --flake "$CLONE_DIR#$HOST_NAME"
echo
echo "✅ Fertig. System wurde installiert (falls keine Fehler gemeldet wurden)."
echo "Hinweis: Nach dem Reboot wird die Konfiguration aus $CLONE_DIR verwendet."Host Konfig¶
🛠 configuration.nix
{ config, lib, pkgs, ... }:
{
imports = [
./hardware-configuration.nix
];
# --- Bootloader (UEFI) ---
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
# Setzt die Version 25.05
system.stateVersion = "25.05";
# Setzt den Hostnamen
networking.hostName = "nix-host1";
# deaktivert dhcp und networkmanager
systemd.network.enable = true;
networking.useDHCP = false;
networking.networkmanager.enable = false;
services.resolved.enable = true;
# Netzwerkkonfiguration
systemd.network.networks."10-wired-static" = {
matchConfig.Name = "en*";
address = [ "192.168.200.100/24" ];
gateway = [ "192.168.200.1" ];
dns = [ "192.168.222.17" ];
# Optional: IPv6-Router-Announcements aus, wenn reines IPv4 gewünscht
networkConfig.IPv6AcceptRA = false;
};
# --- Firewall: strikt, nur SSH (22/tcp) & ICMP Echo (Ping) erlaubt ---
networking.firewall = {
enable = true;
allowedTCPPorts = [ 22 ];
allowPing = true;
rejectPackets = true;
checkReversePath = true;
logRefusedConnections = true;
};
# --- OpenSSH: sicher, nur Schlüssel, Root-Login aus, Port 22 ---
services.openssh = {
enable = true;
ports = [ 22 ];
settings = {
PasswordAuthentication = false;
KbdInteractiveAuthentication = false;
PermitRootLogin = "no";
X11Forwarding = false;
AllowAgentForwarding = "no";
# Optional etwas strenger:
# MaxAuthTries = 3;
};
};
# --- Benutzer & Auth ---
users.mutableUsers = true; # Passwörter können interaktiv geändert werden
# --- Admin-User 'service' in sudo-Gruppe (NixOS: 'wheel') ---
users.users.service = {
isNormalUser = true;
description = "Administrator";
extraGroups = [ "wheel" ];
openssh.authorizedKeys.keys = [
"ssh-ed25519 xxxxx"
];
initialHashedPassword = "xxxx";
};
# --- Tools ---
environment.systemPackages = with pkgs; [
btop htop iotop
];
# --- Nix CLI & Flakes ---
nix.settings = {
experimental-features = [ "nix-command" "flakes" ];
warn-dirty = false;
};
}