Skip to content

konradmalik/dotfiles

Repository files navigation

Actions Status Actions Status

Dotfiles

My NixOS and Nix-Darwin configurations.

Commands

Note: in all commands flake location can be one of the following:

# github repo
github:konradmalik/dotfiles#<target>
# local current dir
.#<target>
# absolute local git repo
git+file://$HOME/Code/github.com/konradmalik/dotfiles#<target>

I'll use the local version for brevity.

NixOS:

Build and enable config locally:

$ sudo nixos-rebuild --flake . switch

To just build (for example for a test):

$ nix build .#nixosConfigurations.$(hostname -s).config.system.build.toplevel

Build and enable config on remote:

Note: this will fail because of this bug. Workaround is to use root ssh access, but I don't want to do that

$ TARGET=rpi4-1 nixos-rebuild --flake .#$TARGET --target-host $TARGET --build-host $TARGET --use-remote-sudo boot

Instead, this will work for now. I may create a wrapper for that:

$ TARGET=rpi4-1 ssh $TARGET -- sudo nixos-rebuild --flake github:konradmalik/dotfiles#$TARGET boot

Build sd-image:

$ nix build .#rpi4-2-sd-image

Copy it somewhere and unpack:

$ unzstd -d rpi4-2.img.zst

Flash directly to the card:

$ sudo dd if=rpi4-2.img of=/dev/sdX bs=4096 conv=fsync status=progress

NOTE:

The filesystem won't be complete, it will miss etc and more. NixOS will populate those dirs on first boot.

So if you need to modify something on the card (like read host keys or add wpa_supplicant.conf) then the steps are:

  • boot rpi with the newly flashed card once
  • wait a minute or two
  • poweroff rpi and mount the card on your PC
  • filesystem will be complete

In my case, Wi-Fi (wpa_supplicant.conf) is symlinked from sops, but you may still need to add appropriate host key to .sops.yaml.

Build minimal ISO with ssh access for root:

Useful for installing any nixos-config through ssh.

$ nix build .#installer-iso

Flash iso to a pendrive

$ sudo dd if=installer.iso of=/dev/sdX bs=4096 conv=fsync status=progress

Boot, find the ip and ssh connect as root.

Consider using nmap for discovery:

$ sudo nmap -p 22 --open -sV 192.168.178.0/24

Format, partition the drive etc.

Then you can install the system from flake directly:

$ sudo nixos-install --flake github:konradmalik/dotfiles#m3800 --root /mnt --no-bootloader

Tip: nixos-enter is also very handy if you have a working system but need to fix something, e.g. change your password.

Tip2: I use --no-bootloader because I don't want grub (either way it will fail if there is systemd already defined I think, it will say something like '/boot/efi is not at the root'). My flake has already all the needed hardware and booloader configs for the machines I use. In order to install on a new machine, just generate hardware-configuration.nix on that machine and add a new entry in this flake.

nix-darwin:

Disable gatekeeper or however it's called:

$ sudo spctl --master-disable

Go to Settings → Security and Privacy and allow apps from "Anywhere".

Then install nix following the official guidelines and installer.

Then build and enable config locally:

$ darwin-rebuild switch --flake .#$(hostname -s)

To just build (for example for a test):

$ nix build .#darwinConfigurations.$(hostname -s).config.system.build.toplevel
# or shortened by nix-darwin
$ nix build .#darwinConfigurations.$(hostname -s).system

Linux builder

It is useful to have a Linux builder on a macOS machine to build linux-specific stuff.

NixOS has a great support for this. We need to:

  • set up a remote builder
  • configure nix.buildMachines to use it

We can have either a truly remote machine (local PC, cloud VM etc. etc.) or a 'local remote builder' which is just a qemu virtual machine with NixOS inside. This 'local remote builder' is very handy to have either way, very easy to deploy and very lightweight (it mounts your existing /nix/store for example for absolutely minimal disk usage).

nix-darwin support a Linux builder as an option:

nix.linux-builder.enable = true;

Docker on Darwin

Use darwin-docker module.

Linux (non-NixOS; home-manager):

Build and enable config locally:

$ home-manager switch --flake .

To just build (for example for a test):

$ nix build .#homeConfigurations.$(whoami)@$(hostname -s).activationPackage

sops-nix

system-wide (Linux only)

We use age, it's way easier and more straightforward than gpg.

Strategy with keys:

  • age derived from host ssh key for host-wide secrets
  • age derived from personal ssh key for personal secrets
  • one global age key per person that is kept secret and not directly on any machine. Serves as a backup to decrypt in case of 'tragedy'

Create age directory for sops:

$ mkdir -p "$XDG_CONFIG_HOME/sops/age" \
$ && touch "$XDG_CONFIG_HOME/sops/age/keys.txt" \
$ && chmod 700 "$XDG_CONFIG_HOME/sops/age" \
$ && chmod 600 "$XDG_CONFIG_HOME/sops/age/keys.txt"

Create age key from your personal ssh key:

Why do this when decryption keys are also derived from host ssh keys?

  1. Redundancy, 2. Personal (user-specific) secrets, 3. Keys generated here can also be used in the home-manager module below
$ ssh-to-age -private-key -i ~/.ssh/personal > "$XDG_CONFIG_HOME/sops/age/keys.txt"

Add this key to .sops.yaml and propagate re-encryption to all secrets:

# adjust this command, glob may not work!
$ sops updatekeys secrets/*.yaml

home-manager

For user-specific secrets, a home-manager modules of sops-nix is used.

We similarly use age. The key is reused from system-wide config (the one derived from personal ssh). See how sops is configured in the home-manager (it just points at the keys.txt file).

Credits

Misterio77 - big inspiration for hyprland and nix files structure.