00
DESCRIPTION
Fedora Kinoite is an atomic/immutable distro: the OS image is read-only and updated transactionally, while
$HOME and the userland are yours to modify freely. This setup layers Nix + home-manager on top of that split to manage the userland declaratively, for two reasons:- Keep multiple machines (laptop + desktop) in lockstep — same packages, same configs, same versions, all from one flake.
- Per-project development shells — Ruby/Node/Go versions and native libs (libpq, libyaml, libvips) flow in via per-project flakes without polluting global state.
Starting state assumed: a freshly-installed Fedora Kinoite. The eight numbered steps below take you from there to a working machine; §09 MAINTAIN covers ongoing sync.
01
PREPARE
Layered RPMs and transient root.
Add a
[root] section to /etc/ostree/prepare-root.conf (use sudo $EDITOR) so the Nix installer can write to the root inode. Fresh Kinoite default:[composefs]
enabled = yesAfter your edit:
[composefs]
enabled = yes
[root]
transient = trueLayer the 1Password trio. App, CLI, and Chrome have to live on the host together: the browser extension talks to the app via Chrome's native-messaging hosts (paths under
/etc/opt/chrome/native-messaging-hosts/), the CLI talks to the app over a Unix socket, and git signs commits via /opt/1Password/op-ssh-sign at 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-stableLayer the podman tooling on top of Kinoite's base
podman: podman-docker aliases the docker CLI, podman-tui is a terminal UI for managing containers.$sudo rpm-ostree install \
podman-docker podman-tuiTrack the prepare-root config so it survives ostree updates.
$sudo rpm-ostree initramfs-etc \
--track=/etc/ostree/prepare-root.confReboot to apply layered packages and the transient-root flag.
$sudo systemctl reboot
02
1PASSWORD
Install the 1Password desktop app and CLI, then enable the SSH agent. Every git push and ssh login that follows is signed by the agent.
Open the 1Password app, sign in with your account, and complete the first-run setup.
In 1Password: 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 1Password agent.
$ssh-add -lConfirm GitHub accepts the agent-signed key.
$ssh -T git@github.com
03
INSTALL
Determinate Nix in ostree mode.
Detects ostree + transient root, arranges
nix.mount for /var/home/nix → /nix.$curl --proto '=https' --tlsv1.2 -sSf -L \
https://install.determinate.systems/nix \
| sh -s -- installReboot so
nix.mount and the daemon come up cleanly.$sudo systemctl reboot↻ After 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
04
SUBSTITUTE
Pre-built Rubies from nixpkgs-ruby cachix.
Add the nixpkgs-ruby substituter so per-patch Rubies pull pre-built; without this each patch compiles from source (~5 min).
$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
05
PURGE
Remove dotfiles HM is about to manage.
Drop shell rc files; HM refuses to clobber existing ones on first activation.
$rm -f ~/.bashrc ~/.bash_profile ~/.profile ~/.bash_logoutDrop tool configs HM will replace with managed symlinks.
$rm -f ~/.inputrc ~/.gitconfig ~/.gitignore ~/.vimrc ~/.npmrc
06
ACTIVATE
Fetch the flake. Build and switch the laptop profile.
Ensure
~/.config exists.$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 laptop profile. First run pulls 2–4 GB; expect 5–20 min.
$nix run home-manager/master -- \
init --switch \
--flake ~/.config/home-manager#laptop
07
RELOGIN
Re-source the HM-managed environment.
End the session so the next login picks up HM-managed PATH and starts the podman quadlets.
$loginctl terminate-user $USER
08
VERIFY
Confirm the four quadlets are up and the dev tools resolve.
Confirm home-manager itself is installed.
$home-manager --versionConfirm git is signing commits via the 1Password SSH agent.
$git config --get gpg.ssh.programConfirm all four podman quadlets are active.
$systemctl --user is-active \
postgres16 redis mysql57 memcachedConfirm the dev tools resolve to
~/.nix-profile/bin/.$which git fd rg jq vim claudeRootless networking smoke-test — exercises the slirp4netns workaround.
$podman run --rm docker.io/library/alpine \
wget -qO- https://example.com | head -c 100Launch Zed once (app menu or
zed in a terminal), then confirm the Vulkan ICD wrapper took effect.$grep 'Selected GPU' ~/.local/share/zed/logs/Zed.log | head -1Confirm the npm-globals activation hooks landed (herb-tools, ccusage, git-xor).
$ls ~/.local/bin | grep -E 'herb-|ccusage|git-xor'
09
MAINTAIN
Day-to-day sync; bump pinned inputs.
Pull the latest committed config and re-activate. Same command after editing the flake locally — drop the
git pull.$cd ~/.config/home-manager \
&& git pull \
&& home-manager switch --flake .#laptopBump
nixpkgs and home-manager pins to the latest revisions. Commit the new flake.lock, then git pull on the other host.$cd ~/.config/home-manager \
&& nix flake update \
&& home-manager switch --flake .#laptop
10
SEE ALSO
- andreimaxim/nix-config — the home-manager flake
- Determinate Systems Nix installer
- Fedora Kinoite documentation
- bobvanderlinden/nixpkgs-ruby — per-patch Ruby flake