Nix on a Foreign Linux

Updated

September 12, 2026

Nix on a Foreign Linux

Most of the desk will not reinstall the OS this quarter. The boring default is: install the Nix daemon on the existing Ubuntu/Fedora/Arch machine, use flakes + Home Manager + direnv, and leave apt/dnf for the kernel, firmware, and the desktop the vendor already glued together.

This is not NixOS. /etc, systemd units, and the kernel stay the host’s. You steal reproducible user environments and project shells. When you are ready to own the machine, install NixOS.

Mental model

Layer Owner on a foreign distro
Kernel, glibc of /usr, display manager Distro (dnf, apt)
/nix/store, nix-daemon Nix 2.35+
User CLIs, git, prompt, nvim Home Manager (standalone), release-26.05
Per-repo compilers nix develop / direnv

PATH will contain both /usr/bin and ~/.nix-profile/bin. Put the Nix profile first so jq is the one you pinned.

Do not replace /usr/bin/python3 with a Nix python. The distro’s tools (PackageKit, GNOME extensions, vendor installers) expect the distro python.

/usr/bin/…          distro, leave it
~/.nix-profile/bin  Home Manager
$PRJ/.direnv        project shell (direnv)

There is no nixos-rebuild here. configuration.nix does nothing until the machine is NixOS.

Worked examples

Case 1: Daemon is already installed — use it

After the Installing Nix chapter:

systemctl is-active nix-daemon
nix --version
echo "$PATH" | tr ':' '\n' | head

You want nix (Nix) 2.35… (or newer). If ~/.nix-profile/bin is missing from PATH, your login shell did not source the daemon profile. For bash, until Home Manager owns it:

# ~/.bashrc
. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh

Confirm flakes in the daemon nix.conf (experimental-features = nix-command flakes), not only in ~/.config/nix/nix.conf — multi-user builds ignore the user file.

Case 2: Standalone Home Manager on Fedora/Ubuntu

Save as flake.nix (user flake):

# flake.nix
{
  description = "Deskadmin on a foreign Linux";

  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05";
  inputs.home-manager.url = "github:nix-community/home-manager/release-26.05";
  inputs.home-manager.inputs.nixpkgs.follows = "nixpkgs";

  outputs = { self, nixpkgs, home-manager }: {
    homeConfigurations.deskadmin = home-manager.lib.homeManagerConfiguration {
      pkgs = nixpkgs.legacyPackages.x86_64-linux;
      modules = [
        {
          home.username = "deskadmin";
          home.homeDirectory = "/home/deskadmin";
          home.stateVersion = "26.05";
          home.packages = [ nixpkgs.legacyPackages.x86_64-linux.jq ];
        }
      ];
    };
  };
}
nix run home-manager/release-26.05 -- switch --flake .#deskadmin
which jq

home.username / home.homeDirectory must match id -un and $HOME. Home Manager will not create /home/deskadmin if you invented a name.

Case 3: Project shells without touching /usr

Save as flake.nix in a Go service repo:

# flake.nix
{
  description = "Desk metrics on a foreign Linux";

  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05";

  outputs = { self, nixpkgs }:
    let
      pkgs = nixpkgs.legacyPackages.x86_64-linux;
    in
    {
      devShells.x86_64-linux.default = pkgs.mkShell {
        packages = [ pkgs.go pkgs.gopls ];
        env.GOTOOLCHAIN = "local";
      };
    };
}
nix develop --command which go
which go || echo 'host go missing (good)'

Inside: store path. Outside: /usr/bin/go or nothing. That split is expected. direnv (use flake) makes the project one automatic.

Case 4: SELinux and /nix

On Fedora, SELinux can deny the daemon. If nix-build fails with Permission denied and dmesg mentions nix-daemon:

sudo ausearch -m avc -ts recent | head

Follow the distro package docs when you installed Nix via dnf. If you used the official installer, a systemd unit plus the installer-provided policy is required. Do not setenforce 0 as a lifestyle.

Case 5: Uninstall without wrecking the distro

sudo systemctl stop nix-daemon
# official installer ships an uninstall script; use it
sudo rm -rf /nix

Then remove the PATH snippet from ~/.bashrc. Distro packages (vim, firefox) stay. That is the whole point of not replacing /usr.

The trap

The trap is environment.systemPackages thinking on Ubuntu: writing a configuration.nix and wondering why nixos-rebuild is not installed. There is no NixOS module system on this host. Home Manager + flakes. If you want services.openssh, install NixOS.

The other trap is mixing distro Node and Nix Node on the same PATH without direnv. CI uses Nix; your laptop uses /usr/bin/node; lockfiles disagree.

The boring rule

  • Nix daemon 2.35+ + flakes + Home Manager release-26.05 + direnv. Distro owns the OS.
  • Nix PATH first for your CLIs. Distro python/node stay for vendor tools.
  • No configuration.nix until the machine is NixOS.
  • SELinux: use the distro’s Nix policy, not setenforce 0.
  • Project compilers only from nix develop.

Try this

  1. which jq before and after Home Manager with jq in home.packages. The second should be /nix/store/….
  2. Case 3: nix develop --command which go versus which go in a fresh terminal.
  3. echo $PATH and label each entry as distro / Nix profile / direnv / other.
  4. Confirm systemctl is-enabled nix-daemon is enabled so a reboot still builds.