Using Juliaup on NixOS (2025 edition)

Hey Julia friends. I’ve been trying to figure this out this morning in response to a student who is using NixOS and has convinced me to give it a try. In general on NixOS nothing is in the filesystem where things expect them to be (like in /lib or /usr/lib/ or /usr/bin/ or anything like that).

This means if you download precompiled binaries off the internet they generally won’t run. So if you want to use juliaup in your home directory on a NixOS machine, here’s how I got it working (apparently, tested to work for some very mild test cases).

  1. enable nix-ld on your NixOS config via programs.nix-ld.enable = true;
  2. Make sure you have a .bashrc file (might not if you have a brand new machine, if needed do echo "" > ~/.bashrc
  3. install juliaup according to the instructions on julialang.org
  4. run julia via the following command (or create a shell script)
NIX_LD_LIBRARY_PATH=~/.julia/juliaup/julia-1.11.5+0.x64.linux.gnu/lib/julia julia

nix-ld uses this environment variable to add to the “real” LD_LIBRARY_PATH when it loads julia, thereby avoiding having you link to some system version of stuff… In particular without it you’ll get an error about libcurl when doing package operations. Vscode julia language server cannot load on recent nixos

Now, you’re going to have to be responsible for changing this path when you update julia. So maybe make yourself a ~/bin/julianix script and update the script when you update julia.

Have a good time using Julia on NixOS!

EDIT: added this little shell script which auto-determines the directory from the default julia:

#!/usr/bin/env bash

VERS=$(juliaup status | sed -n -e "s/ *\*.* 1/1/p")

NIX_LD_LIBRARY_PATH=~/.julia/juliaup/${VERS}/lib/julia ~/.juliaup/bin/julia "$@"

It may be OT, but would me nice to have a summary of these arguments.. :slight_smile:

The main reason to use NixOS is that you can declare what you want installed in a file, and it will build that installation for you. Also, if you declare stuff that didn’t work, it is transactional so you can roll back to the previous build. I have a lot of machines I need to administer (like 20 total) so being able to centralize how each one is configured and adjust it in a text file and push it out is super useful.

For the student I think it was more about making his PhD project reproducible via the nix shell stuff, which is kind of user-level environment similar to julia’s environments except for the whole project not just the julia part.

For those wanting a fully declarative Nix approach (no nix-ld, no upstream installer), I packaged juliaup as a Nix flake: s-celles/juliaup-nix

The approach: build juliaup from Rust source via rustPlatform.buildRustPackage — no prebuilt binaries, no patchelf, fully reproducible.

Two outputs:

  • packages.juliaup — the juliaup CLI (system package)
  • packages.julia — a julia dispatcher wrapper (user package)

The wrapper exists because juliaup uses current_exe() (resolves symlinks via /proc/self/exe) to decide whether to launch Julia or show its own CLI. A plain julia → juliaup symlink always resolves to the store path, so juliaup sees itself as juliaup. The wrapper reads ~/.julia/juliaup/juliaup.json with jq and execs the correct Julia binary directly.

NixOS / Home Manager setup:

# flake.nix inputs
juliaup-nix = {
  url = "github:s-celles/juliaup-nix";
  inputs.nixpkgs.follows = "nixpkgs";
};

# system — juliaup CLI only
environment.systemPackages = [
  inputs.juliaup-nix.packages.${system}.juliaup
];

# user — julia wrapper in home.packages, NOT systemPackages
# (avoids binary conflict with julia-bin pulled transitively by quarto etc.)
home.packages = [
  inputs.juliaup-nix.packages.${system}.julia
];

After rebuild:

juliaup add release && juliaup default release
julia --version  # works

Works on any platform supported by Rust + nixpkgs (eachDefaultSystem).


Edit: 2026-09-15
An update on using s-celles/juliaup-nix with NixOS:

Building juliaup from Rust source via rustPlatform.buildRustPackage actually builds both binaries:

  • juliaup (the version manager CLI)
  • julia (the official Rust julialauncher multiplexer)

Because packages.juliaup provides the real julialauncher binary, no wrapper script or symlink workaround is needed anymore. The launcher correctly handles channel switching (e.g. julia +1.10, julia +lts, julia +release).

1. Setup in configuration.nix

Since juliaup downloads standard dynamically linked Linux binaries into ~/.julia/juliaup/, NixOS needs programs.nix-ld to run them:

# flake.nix inputs
juliaup-nix = {
  url = "github:s-celles/juliaup-nix";
  inputs.nixpkgs.follows = "nixpkgs";
};

# NixOS module
environment.systemPackages = [
  inputs.juliaup-nix.packages.${pkgs.stdenv.hostPlatform.system}.juliaup
];

# Dynamic loader for binaries downloaded by juliaup
programs.nix-ld = {
  enable = true;
  libraries = with pkgs; [
    stdenv.cc.cc.lib
    zlib
    openssl
    curl
    libssh2  # Required for Julia 1.10 (LTS) LibCURL compatibility!
  ];
};

Important tip for Julia 1.10 (LTS): If you include curl in programs.nix-ld.libraries, you must also include libssh2. Otherwise, Nixpkgs’s libcurl.so.4 will attempt to link against Julia 1.10’s older bundled libssh2.so.1, leading to a symbol resolution error (undefined symbol: libssh2_session_callback_set2).

2. Usage

After nixos-rebuild switch:

# Install channels
juliaup add release && juliaup default release
juliaup add lts

# Channel switching works out-of-the-box
julia          # Default (release)
julia +1.10    # LTS
julia +lts     # LTS

(Note: for those who still want a 100% store-pinned setup without nix-ld, the flake also exposes pre-patched binaries like packages.julia-lts and packages.julia built with autoPatchelfHook).