github.com/andreimaxim/nix-config

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 op CLI, 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
  1. 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 Hide

    Edit /etc/ostree/prepare-root.conf with sudo $EDITOR and add a [root] section.

    [composefs]
    enabled = yes
    
    [composefs]
    enabled = yes
    
    [root]
    transient = true
    

    Track the file so it survives ostree updates, then reboot.

    sudo rpm-ostree initramfs-etc \
      --track=/etc/ostree/prepare-root.conf
    
    sudo systemctl reboot
    
  2. Layer host packages

    1Password trio, Chrome, podman tooling, and the freeworld mesa drivers for hardware H.264/H.265.
    Show Hide

    App, 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-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-stable
    

    Podman tooling on top of Kinoite’s base podman: podman-docker aliases the docker CLI, podman-tui is a terminal UI.

    sudo rpm-ostree install \
      podman-docker podman-tui
    

    Hardware H.264/H.265: Fedora ships mesa-va-drivers with the patent-encumbered codecs stripped out. RPM Fusion’s -freeworld variant re-enables the hardware encoder on AMD VCN GPUs; gstreamer1-plugins-va exposes it to apps as vah264enc / vah265enc.

    sudo rpm-ostree install \
      https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm
    
    sudo rpm-ostree override replace --experimental \
      --from repo=rpmfusion-free-updates \
      mesa-va-drivers-freeworld
    
    sudo rpm-ostree install gstreamer1-plugins-va
    
    sudo systemctl reboot
    
  3. Sign in to 1Password & enable the SSH agent

    Every git push and ssh login that follows is signed by the agent.
    Show Hide

    Open 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 -l
    

    Confirm GitHub accepts the agent-signed key.

    ssh -T git@github.com
    
  4. Install Determinate Nix

    Detects ostree + transient root, arranges nix.mount for /var/home/nix → /nix.
    Show Hide
    curl --proto '=https' --tlsv1.2 -sSf -L \
      https://install.determinate.systems/nix \
      | sh -s -- install
    

    Reboot 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
    
  5. Add nixpkgs-ruby substituter

    Pre-built Rubies for the ruby/rails template dev shells — without this each patch compiles from source (~5 min).
    Show Hide

    The base config pulls Ruby straight from nixpkgs; only the ruby and rails project 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=
    EOF
    

    Restart the daemon so it picks up the new substituters.

    sudo systemctl restart nix-daemon
    
  6. Fetch the flake & switch the profile

    First run pulls 2–4 GB; expect 5–20 min.
    Show Hide

    Ensure ~/.config exists.

    mkdir -p ~/.config
    

    Clone the flake into the path home-manager expects by default.

    git clone git@github.com:andreimaxim/nix-config.git \
      ~/.config/home-manager
    

    Build and switch the Home Manager profile.

    nix run home-manager/master -- \
      init --switch \
      --flake ~/.config/home-manager#andrei
    

    Enable 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 $USER
    

    Enable 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
    
  7. Install the self-updating leaf tools

    Zed via its vendor installer, npm for the remaining fast-moving leaf tools.
    Show Hide

    These 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/zed and registers its own desktop entry.

    curl -fsSL https://zed.dev/install.sh | sh
    

    The 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 on PATH — without touching ~/.local/bin.

    npm install -g \
      ccusage \
      @andreimaxim/git-xor \
      @herb-tools/language-server
    

    Update later with npm update -g; Zed self-updates in place.

See also