NixOS config for my personal computer and servers
Presentation
Here are my NixOS machines:
- carokann: personal computer (Framework laptop).
- najdorf: server where I deploy my self-hosted apps.
- ginko: RaspberryPi used as tailscale exit node.
The hosts communicate through Tailscale.
This repo is structured with flake-parts and haumea for automatic module/profile discovery, preserving all the convenience features from the original digga setup.
Directory Structure
nixfiles/
├── hosts/ → Host configurations
├── profiles/ → Reusable configuration profiles
├── modules/ → Custom NixOS modules
├── hm-modules/ → Custom home-manager modules
├── pkgs/ → Custom packages
├── overlays/ → Additional overlays
├── lib.nix → Custom lib functions
└── shell.nix → Development shell
Software I use on my personal computer (carokann)
- Wayland compositor: hyprland
- Desktop shell: DankMaterialShell
- Editor: kakoune and Zed
- Terminal: wezterm
- Shell: fish
- Browser: zen
Self-hosted apps on my server (najdorf)
Most services are exposed with Tailscale Serve.
Here's the list of the main services deployed through their NixOS modules:
I deploy some service as Docker containers through Arion:
Important data is backed up with Restic.
Bootstrap
PC
Create a bootstrap ISO and put it on your usb key:
nixos-rebuild build-image --image-variant iso --flake '.#bootstrap'
sudo dd if=your.iso of=/dev/sda bs=4M status=progress oflag=directThen, from that key, install NixOS:
cd nixfiles sudo disko --mode destroy,format,mount -f '.#carokann' sudo mount /dev/mapper/cryptroot /mnt sudo mkdir /mnt/boot sudo mount /dev/nvme0n1p1 /mnt/boot # Generate the hardware config for reference, change what you need before install sudo nixos-generate-config --root /mnt --dir /home/sweenu sudo nixos-install --flake '.#carokann' --root /mnt # Optional: # Enroll your fingerprint sudo fprintd-enroll sweenu # Enroll TPM2 for dm-crypt (if enabled in config) sudo systemd-cryptenroll --tpm2-device=auto /dev/nvme0n1p2
After logging in with tailscale and enabling SSH connections (sudo tailscale set --ssh), you can backup the important files:
- ~/.ssh
- ~/.local/share/fish/fish_history
- /etc/NetworkManager/system-connections (replace interface names:
sed -i 's/wlp166s0f0/wlp192s0/' *) - All documents from ~ that you want to keep
Raspberry Pi
Create a ready-to-boot SD card for a RaspberryPi, do the following:
nixos-rebuild build-image --image-variant sd-card --flake '.#ginko' unzstd -d {the output path from the command above} -o nixos-sd-image.img sudo dd if=nixos-sd-image.img of=/dev/sda bs=4M status=progress oflag=direct
Server
Deploy the server config to a new machine:
# 0) Preperation # Uncomment all services in hosts/najdorf/default.nix to have a minimal deployment at first. # Generate a tailscale auth key for unattended login here: https://login.tailscale.com/admin/settings/keys, and add it through `services.tailscale.authKeyFile`. This way, your old and new server have direct access to each other. # 1) Provision # We use --copy-host-keys to temporarily allow agenix to decrypt the secrets. nixos-anywhere --copy-host-keys --flake '.#najdorf' root@<ip-address> # 2) Preserve SSH host identity scp -p root@najdorf:/etc/ssh/ssh_host_* root@najdorf-1:/etc/ssh/ # 2b) (Optional) Generate an initrd SSH host key (only needed for remote LUKS unlock) # See https://nixos.org/manual/nixos/unstable/options#opt-boot.initrd.network.ssh.hostKeys ssh root@najdorf-1 'sudo ssh-keygen -t ed25519 -N "" -f /etc/ssh/initrd_ssh_host_ed25519_key' # 3) Pre-populate known_hosts ssh root@najdorf 'ssh-keyscan -H najdorf-1 >> ~/.ssh/known_hosts' # 4) Freeze writes (stop apps that write into /opt + Postgres) ssh root@najdorf 'systemctl stop docker || true; systemctl stop postgresql || true' # adapt to your services # 5) Copy /opt to new server # Start a detached tmux session that runs the rsync ssh root@najdorf 'tmux new-session -d -s migration "rsync -aAXH --numeric-ids --partial --info=progress2 --log-file=/root/rsync-opt.log /opt/ root@najdorf-1:/opt/"' # Later: check progress by reattaching ssh root@najdorf 'tmux attach-session -t migration' # (Ctrl+B then D to detach again without stopping it) # 6) Postgres migration ssh root@najdorf 'sudo -u postgres pg_dumpall --clean --if-exists --no-role-passwords' \ | ssh root@najdorf-1 'sudo -u postgres psql -X -v ON_ERROR_STOP=1 -d postgres' # 7) Deploy all services # Remove najdorf from tailscale and change the tailscale name from najdorf-1 to najdorf. # Change DNS records to point to the new server (on Cloudflare, change the IP scope of the API token to the new IP). # Uncomment the services in hosts/najdorf/default.nix deploy '.#najdorf'
Acknowledgment:
- Thanks to the digga people for making my life easier when I first started to use NixOS and from which the current structure of the repo is still heavily inspired.
