Usage
Pull the latest committed config and apply.
$cd ~/.config/home-manager && git pull && home-manager switch
Or, update the pins to the latest revisions and apply.
$cd ~/.config/home-manager && nix flake update && home-manager switch
Motivation
Fedora’s atomic distributions split the OS into a read-only base that updates transactionally, and user-land apps distributed as flatpaks. Developer tooling is the gray area — compilers, linkers, kernel headers traditionally live in the OS layer, which makes a setup hard to replicate across machines and strays from the atomic approach of layering as little as possible on top.
Home Manager and Nix shells own the user configuration and activate the right tools per project. Fedora owns the base OS. A handful of packages still get layered onto the host — container tooling and hardware video drivers among them (see Bootstrap) — but two are GUI apps whose integrations leave no choice:
- 1Password — GUI plus the
opCLI, used to keep secrets out of env files. - Google Chrome — mostly for the 1Password extension integration.
Both could be flatpaks; the integration would just involve more moving parts.
A third category sits between Nix and the base OS: fast-moving leaf tools and
the Zed editor. They self-update several times a week, faster than nixpkgs
tracks them, so the binaries come from their own installers (the vendor script
or npm) instead of being pinned through Nix. Home Manager still owns their
configuration; only the binaries float.
Bootstrap
[ + ] expand all-
Prepare a transient root
Nix needs to write to /nix, but Kinoite's composefs root is read-only. Mark it transient so the installer can land.Show HideEdit
/etc/ostree/prepare-root.confwithsudo $EDITORand add a[root]section.[composefs] enabled = yes[composefs] enabled = yes [root] transient = trueTrack the file so it survives ostree updates, then reboot.
sudo rpm-ostree initramfs-etc \ --track=/etc/ostree/prepare-root.confsudo systemctl reboot -
Layer host packages
1Password trio, Chrome, podman tooling, and the freeworld mesa drivers for hardware H.264/H.265.Show HideApp, CLI, and Chrome have to live on the host together: the extension talks to the app via Chrome’s native-messaging hosts, the CLI talks via a Unix socket, and git signs commits via
/opt/1Password/op-ssh-signat a fixed absolute path. Flatpak sandboxing or Nix’s FHS layout breaks each of those wires.sudo rpm-ostree install \ 1password 1password-cli google-chrome-stablePodman tooling on top of Kinoite’s base
podman:podman-dockeraliases thedockerCLI,podman-tuiis a terminal UI.sudo rpm-ostree install \ podman-docker podman-tuiHardware H.264/H.265: Fedora ships
mesa-va-driverswith the patent-encumbered codecs stripped out. RPM Fusion’s-freeworldvariant re-enables the hardware encoder on AMD VCN GPUs;gstreamer1-plugins-vaexposes it to apps asvah264enc/vah265enc.sudo rpm-ostree install \ https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpmsudo rpm-ostree override replace --experimental \ --from repo=rpmfusion-free-updates \ mesa-va-drivers-freeworldsudo rpm-ostree install gstreamer1-plugins-vasudo systemctl reboot -
Sign in to 1Password & enable the SSH agent
Every git push and ssh login that follows is signed by the agent.Show HideOpen the 1Password app, sign in, and complete the first-run setup.
Settings → Developer → enable Use the SSH agent. Add at least one SSH key to your vault if you don’t already have one.
List authorised SSH keys handed out by the agent.
ssh-add -lConfirm GitHub accepts the agent-signed key.
ssh -T git@github.com -
Install Determinate Nix
Detects ostree + transient root, arranges nix.mount for /var/home/nix → /nix.Show Hidecurl --proto '=https' --tlsv1.2 -sSf -L \ https://install.determinate.systems/nix \ | sh -s -- installReboot so
nix.mountand the daemon come up cleanly.sudo systemctl rebootAfter reboot, return here for the sanity check below.
Sanity check: version, mount, and a one-shot package run.
nix --version \ && mount | grep ' /nix ' \ && nix run nixpkgs#hello -
Add nixpkgs-ruby substituter
Pre-built Rubies for the ruby/rails template dev shells — without this each patch compiles from source (~5 min).Show HideThe base config pulls Ruby straight from nixpkgs; only the
rubyandrailsproject templates build their Ruby through nixpkgs-ruby. Point Nix at its cachix so those per-project dev shells don’t compile each Ruby patch from source.sudo tee /etc/nix/nix.custom.conf <<'EOF' extra-substituters = https://nixpkgs-ruby.cachix.org extra-trusted-public-keys = nixpkgs-ruby.cachix.org-1:vrcdi50fTolOxWCZZkw0jakOnUI1T19oYJ+PRYdK4SM= EOFRestart the daemon so it picks up the new substituters.
sudo systemctl restart nix-daemon -
Fetch the flake & switch the profile
First run pulls 2–4 GB; expect 5–20 min.Show HideEnsure
~/.configexists.mkdir -p ~/.configClone the flake into the path home-manager expects by default.
git clone git@github.com:andreimaxim/nix-config.git \ ~/.config/home-managerBuild and switch the Home Manager profile.
nix run home-manager/master -- \ init --switch \ --flake ~/.config/home-manager#andreiEnable lingering once so the user systemd manager can start the Podman quadlets at boot, before the first interactive login. Home Manager does not manage this host setting; it is a one-time workstation bootstrap step.
loginctl enable-linger $USEREnable the rootless Podman REST socket. Used by Podman Desktop, DataGrip’s Docker integration, and anything reading
DOCKER_HOST=unix:///run/user/$UID/podman/podman.sock.systemctl --user enable --now podman.socket -
Install the self-updating leaf tools
Zed via its vendor installer, npm for the remaining fast-moving leaf tools.Show HideThese live outside Nix on purpose (see Motivation). Home Manager has already deployed their config and the Node runtime in the previous step; here you install the binaries themselves.
Zed: the editor uses the host Vulkan/Mesa stack, so it comes from the vendor installer rather than Nix. Lands a self-updating binary at
~/.local/bin/zedand registers its own desktop entry.curl -fsSL https://zed.dev/install.sh | shThe npm utilities and the ERB language server via
npm.~/.npmrc(from Home Manager) points the global prefix at~/.npm-global, so these land in~/.npm-global/bin— already onPATH— without touching~/.local/bin.npm install -g \ ccusage \ @andreimaxim/git-xor \ @herb-tools/language-serverUpdate later with
npm update -g; Zed self-updates in place.