Store, profiles, and GC on Linux

Updated

September 4, 2026

Store, profiles, and GC on Linux

Goal: Operate /nix/store confidently on Fedora: see what a profile is, what keeps paths alive (GC roots), and how to garbage-collect without deleting tomorrow’s work.

This is the same store model as NixOS—only the set of roots differs (no bootloader generations yet).


Why this chapter matters

On Fedora, nothing forces you to be declarative. The fastest way to recreate “npm global hell” is:

nix profile install nixpkgs#tool-a
nix profile install nixpkgs#tool-b
# …six months, no locks, no notes…

Learn roots early and you will treat profiles as a small personal toolkit and flakes as the real project SoT—exactly the habit NixOS rewards.


Store anatomy (quick ops view)

ls /nix/store | head
nix path-info nixpkgs#hello
nix path-info -r $(nix build nixpkgs#hello --print-out-paths) | wc -l
Idea Meaning
Store path /nix/store/<hash>-name content-addressed build result
Closure Path + all runtime references
GC root A pointer that says “do not delete this closure”
Profile User (or system) generation of linked apps—a GC root

Diagram:

~/.nix-profile  ──► /nix/var/nix/profiles/per-user/$USER/profile
                              │
                              ▼
                     generation-42-link  ──► store paths

Profiles: what they are for

Inspect

nix profile list
readlink -f ~/.nix-profile
ls -l /nix/var/nix/profiles/per-user/$USER/ | tail

Install / remove (modern)

nix profile install nixpkgs#ripgrep nixpkgs#fd
rg --version
fd --version

nix profile list
nix profile remove …   # use the index/name from list — check `nix profile remove --help`

Upgrade

nix profile upgrade
# or reinstall from a pinned flake input instead of floating nixpkgs#
Tip

Bridge habit: keep the imperative profile thin (editor, rg, direnv). Put project tools in devShells. On NixOS you will barely need nix profile at all.


Other roots you will meet

Root kind Example Created by
User profile ~/.nix-profile nix profile
Result symlink ./result nix build in a directory
direnv nix-direnv GC roots use flake + allow
Home Manager HM profile generations home-manager switch
NixOS system /run/current-system nixos-rebuild (later)
# List roots (classic tool still useful)
sudo nix-store --gc --print-roots 2>/dev/null | head -50
# or
nix-store --gc --print-roots 2>/dev/null | head -50

Find who pins a path:

# After building hello to ./result
nix build nixpkgs#hello
nix-store --query --roots $(readlink -f result) || true

Garbage collection

Safe everyday

# Delete unreachable paths
nix store gc
# or
nix-collect-garbage

Delete old profile generations

# User profiles / HM generations (read manpages for exact flags on your version)
nix-collect-garbage -d
# Older alias many still use:
# nix-env --delete-generations old
Warning

nix-collect-garbage -d is aggressive on generations. Fine on a lab account; think twice if you rely on rolling back HM quickly.

Disk pressure playbook

df -h /nix
nix path-info -Sh /nix/var/nix/profiles/per-user/$USER/profile 2>/dev/null || true
# Find large paths (nix-tree if installed)
nix run nixpkgs#nix-tree

Optional: set free-space goals in nix.conf (daemon may need system file):

min-free = 1073741824
max-free = 5368709120

Channels vs flakes (on Fedora)

Fedora users sometimes enable channels by habit. This book’s default is flakes + locks.

Approach Pinning Team repro
Channels + nix-env Floating Weak
nix profile install nixpkgs#foo without lock Floating nixpkgs Weak
Project flake.lock Strong Strong
HM flake input lock Strong Strong
# Prefer explicit flake refs in projects
nix flake metadata .

You may still see nix-channel on old blog posts—literacy only (Classic CLI).


Binary caches

Default substitutes (cache.nixos.org) keep Fedora+Nix usable.

nix show-config | rg substituter
# First download of a big stdenv is slow; later hits cache

Later: Cachix/Attic in packaging/ops parts. On a laptop, don’t disable substitutes “for purity cosplay” unless studying FODs.


Worked lab: profile vs shell

cd ~/lab/nixos-book/nix-on-linux
mkdir -p store-lab && cd store-lab

# A) Ephemeral — disappears when shell exits (no profile pollution)
nix shell nixpkgs#jq --command jq --version

# B) Build root in cwd
nix build nixpkgs#jq
ls -l result
./result/bin/jq --version

# C) Profile (persistent)
nix profile install nixpkgs#jq
command -v jq

# Clean lab build root
rm -f result
nix store gc

Write three sentences in your journal: what remained after each of A/B/C.


Checkpoint

  • You can define store path, closure, GC root
  • nix profile list is intentional and small
  • You can find roots and run nix store gc safely
  • You prefer flake locks over channels for projects

Further depth