# Setting Up and Using Nix and Rix on macOS

This vignette covers macOS-specific topics. If you’re using Linux or Windows instead, read the `vignette("setting-up-linux-windows")` vignette.

## Introduction

Nix officially supports only two operating systems: macOS and Linux. Windows support comes via WSL2, which runs a real Linux distribution under the hood — so Linux and Windows can be treated as one case, with macOS as its own, separate case with its own quirks. This vignette walks through them.

Nix on macOS doesn’t have full feature parity with Linux. Because macOS relies on proprietary system frameworks and Xcode’s SDKs, reproducibility can’t always be guaranteed the way it can on Linux. On Linux, nixpkgs controls the entire toolchain — C library, compilers, linker, and most system dependencies — which is why historical nixpkgs snapshots often keep building successfully years later.

On macOS, many builds implicitly depend on the macOS SDK from Xcode and on Apple’s dynamic loader (`dyld`). Both are provided by the operating system and change across macOS and Xcode updates. When Apple updates Xcode or system frameworks, a pinned nixpkgs revision that used to build can stop working — even if nothing in your project changed. This “SDK drift” isn’t a problem on Linux, where Nix controls the full dependency graph.

In practice, this means:

- an environment that worked on macOS may stop building after a system or Xcode update;
- older pinned nixpkgs snapshots are more likely to fail on newer macOS versions;
- the same snapshot will often keep working without issue on Linux.

This isn’t a `{rix}` problem, nor something the nixpkgs maintainers can fully prevent — it’s a structural limitation of the macOS platform and its reliance on proprietary system components.

Given this, we recommend committing the generated `default.nix` to version control, and if you run into build failures on macOS, trying a more recent pinned date first. As a further mitigation, consider setting up your own private binary cache (for example with Cachix, via `ga_cachix()`): this lets you reuse builds you know work on your system, avoiding repeated recompilation and cushioning you somewhat against upstream cache gaps.

If you need long-term archival reproducibility — rebuilding environments from several years ago to compare outputs, say — we strongly recommend building those historical nixpkgs snapshots on Linux rather than directly on macOS, ideally inside a Docker container or a Linux virtual machine. Linux environments stay far more stable over time, since nixpkgs controls the entire toolchain and C library stack, and running inside Docker further isolates the environment from host system updates.

These issues are becoming less common as macOS support in Nix improves. But if you need to work with older versions of R, or other software sensitive to system SDK changes, it’s worth keeping this limitation in mind on macOS.

## Why rix and Nix?

You don’t have to install Nix to use `{rix}`: the package can generate valid Nix expressions on any system, even one without Nix installed. The catch is that you won’t be able to build those expressions until Nix is actually present.

## Installing Nix

Since you don’t need Nix installed to generate expressions, but you do need it to build them, let’s get Nix set up. Installing (and uninstalling) Nix on macOS is straightforward thanks to the installer from Determinate Systems, a company that builds services and tools on top of Nix. Open a terminal and run:

    curl --proto '=https' --tlsv1.2 -sSf \
        -L https://install.determinate.systems/nix | \
         sh -s -- install

Next, configure the `rstats-on-nix` binary cache. This downloads pre-built binaries for many R packages, which significantly speeds up building environments. Many thanks to Cachix for sponsoring the `rstats-on-nix` cache!

### Recommended: `setup_cachix()`

The simplest approach is to use `{rix}`’s `setup_cachix()` function from R. First, start R from a Nix shell:

    nix-shell -p R rPackages.rix

On first use, this may take a few minutes as Nix downloads R and the required packages — be patient, subsequent runs will be instant.

Then run:

    rix::setup_cachix()

This configures the cache in `~/.config/nix/nix.conf`. You also need to add yourself as a trusted user so Nix allows you to use the cache:

    echo "trusted-users = root $USER" | sudo tee -a /etc/nix/nix.conf && sudo launchctl kickstart -k system/org.nixos.nix-daemon

(Note: if you installed Nix via the Determinate Systems installer, you may see `/etc/nix/nix.custom.conf` mentioned elsewhere — that’s a Determinate-specific file, included by their managed `nix.conf` so your customizations survive installer updates. Either file works for a Determinate install, but editing `/etc/nix/nix.conf` directly, as above, is the one that also works for a standard, non-Determinate Nix installation.)

If you later see warnings like `ignoring untrusted substituter`, it usually means this trusted-users step was skipped.

### Alternative: the `cachix` client

Alternatively, you can configure the cache manually with the `cachix` command-line client:

    nix-env -iA cachix -f https://cachix.org/api/v1/install
    cachix use rstats-on-nix

Note that if you installed Nix using the Determinate Systems installer, this approach won’t work, since Determinate’s `/etc/nix/nix.conf` is protected and restored on restart — use `setup_cachix()` instead.

Once Nix is installed and the cache is configured, you’re ready to build the expressions `{rix}` generates.

## Installing rix

With Nix set up, the last step is getting R and `{rix}` onto your system. How you do that depends on whether R is already installed:

### Case 1: you don’t have R installed and want to install it via Nix

If you have Nix installed but not R, you have two options. You could install R the usual way for macOS and then install `{rix}` on top of it — from there, generate project-specific expressions and build them. Or you could install R through Nix directly. Running the following in a terminal drops you into an interactive R session you can use right away:

    nix-shell -p R rPackages.rix

Or, if you’d prefer the development version of `{rix}`:

    nix-shell --expr "$(curl -sl https://raw.githubusercontent.com/ropensci/rix/main/inst/extdata/default.nix)"

After downloading the required packages, this drops you into an R session directly in your terminal. From there you can run something like:

    rix(date = "2025-02-03",
        r_pkgs = c("dplyr", "ggplot2"),
        system_pkgs = NULL,
        git_pkgs = NULL,
        ide = "none",
        project_path = ".",
        overwrite = TRUE)

This generates a `default.nix`, which you can then use to build an environment with R, `{dplyr}`, and `{ggplot2}`. To add more packages later, rerun the command with the additional packages listed in `r_pkgs`. For more on managing project-specific `default.nix` files, see the `vignette("installing-r-packages")` and `vignette("installing-system-tools")` vignettes.

### Case 2: you already have R installed

If R is already installed on your system — either through the usual macOS installer or through Nix as described above — you’re ready to start building project-specific development environments. Generating expressions on macOS works just like on Linux and Windows: start an R session and install `{rix}` if you haven’t already. Since `{rix}` isn’t yet on CRAN, the easiest way is to install it from its r-universe:

    install.packages("rix", repos = c(
      "https://ropensci.r-universe.dev",
      "https://cloud.r-project.org"
    ))

From there, use `{rix}` to generate expressions as described in the next vignette, `vignette("project-environments")`.

## More macOS specificities

### R support for Apple Silicon in nixpkgs

Apple Silicon wasn’t well supported in Nix before 2021. Our `rstats-on-nix` fork of `nixpkgs` improves compatibility by backporting fixes to R and R packages, but only from 2021 onwards. If you need an older R version, it’s quite unlikely to work.

### Shared libraries issue

When using environments built with Nix on macOS, you might see crashes (segmentation faults) referencing “shared libraries.” This usually means your system’s user library of R packages is interfering with the project-specific Nix environment — the system’s default R user library appears on the search path (check `libPaths()`). On macOS, that user library lives at `/Library/Frameworks/R.framework/Versions/<major>.<minor>-<arch>/Resources/library`; we’ve seen crashes with R packages that depend on system libraries, such as `{data.table}` or `{dplyr}`, and their (reverse) dependencies.

Because this same kind of interference can occur on Linux too, running `rix()` also runs `rix_init()`, which creates a custom `.Rprofile` in your project’s path. This `.Rprofile` ensures that only packages declaratively defined in your `default.nix` and built into the Nix store — each R package as its own derivation at a unique Nix path — appear on the R library path.

### RStudio and other development interfaces on macOS

RStudio installed through the usual means can’t be used with Nix shells — to use RStudio with Nix, you need to install it through Nix itself. As of now, RStudio in `nixpkgs` for macOS is only available for R 4.4.3 or later, or for dates on or after 2025-02-28; using RStudio with a Nix environment for older R versions or dates isn’t possible. If you try to generate an expression with `ide = "rstudio"` on macOS for an R version or date older than that, a warning will be raised. Your options are:

- set `r_ver = 4.4.3` or pick a date on or after 2025-02-28, if you don’t need an older version of R;
- ignore the warning — the environment will actually be built on a Linux distribution (even though you generated the expression on macOS) and used on that Linux distribution;
- change the `ide =` argument to `"none"`, `"code"`, or `"positron"`. Use `"code"` for VS Code, or `"other"` for any other editor like Vim or Emacs — unlike RStudio, these don’t need to be installed through `nixpkgs` to use Nix environments. See `vignette("configuring-ide")` for details;
- if you’re working on a `{targets}` pipeline, run it on GitHub Actions — you can then work on the code in RStudio outside the Nix environment, since the code only executes on GitHub Actions runners. See `vignette("reproducible-pipelines")` for details;
- work on your project as usual with your normal R and RStudio installation, but generate a `default.nix` at the end with `ide = "none"` and the right R version, purely for reproducibility purposes;
- use subshells to run only the code you need inside a specific environment — see `vignette("running-code-in-nix")`.

We recommend continuing with `vignette("project-environments")` before tackling the more advanced topics above.

## Why do we need all these special tweaks?

### Path of the Nix installation not in `PATH`

When using RStudio Desktop on macOS, you typically launch it from the Applications folder. But RStudio currently has no option to start an integrated R session via a shell startup on macOS (see this issue) the way it does on Linux, where `PATH` is properly inherited in R sessions. As a result, key environment variables like `PATH` aren’t properly loaded from your default shell (e.g., `zsh`, via `~/.zshrc`) — and RStudio further overwrites any `PATH` you set via `.Rprofile` or `.Renviron` with its own defaults, making it impossible to find Nix and tools like `nix-build`.

This doesn’t affect `rix::rix()`, which only generates Nix expressions and doesn’t require a Nix installation. As a workaround, `nix_build()` and `with_nix()` automatically append the Nix store path to `PATH` in an active RStudio session on macOS (via `Sys.setenv()`) — you don’t have to do anything yourself, and you’ll get a friendly message letting you know it happened.

## Configuring an IDE

Next, we recommend continuing with `vignette("installing-r-packages")` and `vignette("installing-system-tools")`, followed by `vignette("configuring-ide")`, which walks through setting up your editor to work with Nix shells effectively.

## Other “Nix”es

Several other implementations of the Nix package manager exist, if you’re feeling adventurous — but for now, we recommend sticking with Nix itself. If you’re curious, check out Lix!