Nix flakes

Nix Flakes for Small R Projects

Typical Project Structure

my-project/
├── flake.nix
├── flake.lock
├── .envrc
├── R/
└── other/

What the files do

flake.nix

Defines the environment you want:

  • Which Nix package repository to use (nixpkgs)
  • Which R packages to install
  • Any system dependencies

Example:

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

flake.lock

This is the important, automatically generated, file that pins the environment to a specific commit. Even if nixos-unstable moves on, my project will continue using the exact versions recorded in flake.lock until you choose to update.

.envrc

This is used by direnv to automatically activate/deactivate the environment when I enter that folder. Instead of entering a folder and typing

use flake

with direnv installed, entering the directory automatically loads the Nix environment.


First Time Setup

Create:

flake.nix

and

.envrc

containing:

use flake

Then run:

direnv allow

We normally only need to do this once per project (or after changing .envrc) and should even be getting prompted.

Entering the Environment

If using direnv:

cd my-project

The environment loads automatically.

If not using direnv:

nix develop

This starts a shell containing the packages defined in your flake.


Leaving the Environment

If we started manually:

exit

or:

Ctrl-D

If we used direnv:

cd ..

The environment unloads automatically when you leave the directory.


Updating Packages

Current workflow:

flake.nix
flake.lock (pins exact versions)

To update to newer software:

nix flake update

This refreshes flake.lock to newer commits from the configured branch.

After updating:

git add flake.lock
git commit -m "Update Nix packages"

Stable vs Unstable

Some thoughts about which target URL to use:

Research papers / teaching materials

Use a stable branch:

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

Advantages:

  • More stable
  • Better long-term reproducibility
  • Less risk of breakage

Personal projects

Use:

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

Advantages:

  • Newer R versions
  • Newer package versions
  • Easier access to recent software

Remember that after flake.lock is created, both remain fully reproducible until we run:

nix flake update

Mental Model

Think of:

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

as:

“When I choose to update, get updates from this branch.”

and think of:

flake.lock

as:

“Use these exact package versions until I explicitly update them.”

That’s the key idea behind flakes.