Ever struggle with conflicting software versions between projects? Nix-shell can help! Nix-shell allows you create customized development environments for each project, complete with all the necessary tools and libraries.
These environments are isolated, meaning they won't interfere with other projects on your system. This approach keeps your development workflow smooth and avoids the "dependency hell" where software conflicts cause headaches.
Nix-shell makes it easy to build these environments and switch between them, ensuring consistent setups across different machines. This can be a huge time-saver for you and your team.
In this guide, we'll walk you through the steps of creating and managing isolated development environments using nix-shell in Linux.
Table of Contents
What is Nix-shell?
Nix is a powerful package manager and build system that provides a functional and declarative approach to managing software dependencies. It uses a purely functional approach, treating packages like values in functional programming languages.
Nix-shell, a command line utility included with Nix package manager, allows you to create isolated development environments based on Nix expressions. These environments encapsulate all the necessary tools, libraries, and dependencies required for a specific project.
By building each dependency independently and avoiding interference, nix-shell eliminates "dependency hell" and provides precise control over the dependencies in your development and production environments.
This isolation and reproducibility ensure a consistent setup across different systems and enable smooth collaboration between developers.
Advantages of using Nix-shell
- Isolation: Each
nix-shell
environment is isolated from your system and other environments, preventing conflicts between dependencies. - Reproducibility: Environments are defined in code, ensuring that they can be reproduced on any system running Nix.
- Atomic Upgrades and Rollbacks: Nix's approach to package management supports atomic upgrades and rollbacks, making it safe to experiment with different dependencies.
- Testing Packages without Installing them: One of the useful features of the Nix package manager is that it allows users to test packages without having to install them locally. This can be helpful when you want to use a particular application temporarily.
How to use Nix-shell to Create and Manage Development Environments
As stated already, nix-shell creates separate, reproducible environments for project dependencies. This isolation prevents conflicts between different projects' dependencies.
Here's how you can create and manage development environments using nix-shell.
Creating a Nix Expression
The first step is to create a Nix expression that describes the dependencies required for your project. This is typically done in a file named default.nix
or shell.nix
in the root of your project.
Let us create a sample project named myproject
.
$ mkdir myproject
Cd into the myproject
directory:
$ cd myproject
Create a simple shell.nix
file:
$ nano shell.nix
Add the following lines in it:
{ pkgs ? import <nixpkgs> {} }: pkgs.mkShell { buildInputs = [ pkgs.python38 pkgs.nodejs pkgs.ruby ]; }
This file declares a development environment with Python 3.8, Node.js and Ruby as dependencies. When you run nix-shell
in the directory containing this file, Nix will download and install these packages in an isolated environment, without affecting your global system packages.
You can also specify the dependencies in a single line like below:
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
buildInputs = with pkgs.buildPackages; [ python38 nodejs ruby ];
}
Save the file and close it.
Ad-hoc Environments
For a quick, ad-hoc development environment, you can run
nix-shell
with the-p
flag followed by the packages you need. For example:nix-shell -p python39Packages.numpy python39Packages.scipyThis command launches a
nix-shell
with Python 3.9, NumPy, and SciPy available.
Entering the Nix Shell
Once you have your Nix expression, you can enter the isolated environment using the following command:
$ nix-shell
Or,
$ nix-shell shell.nix
To ensure that system-installed tools don’t interfere with your defined dependencies, use the --pure
option with nix-shell.
$ nix-shell --pure shell.nix
This will create a new shell session with the specified dependencies (Python 3.8, Node.js and Ruby) available. Any commands you run within this shell will have access to the isolated environment.
Using Nix-shell for Development
Within the nix-shell environment, you can run your development tools, scripts, and commands as you normally would.
The isolated environment ensures that your project's dependencies are available and consistent, regardless of the host system's configuration.
You can verify it by checking the versions of the dependencies:
[nix-shell:~/myproject]$ python -V Python 3.8.19
[nix-shell:~/myproject]$ node -v v18.19.1
[nix-shell:~/myproject]$ ruby -v ruby 3.1.4p223 (2023-03-30 revision 957bb7cb81) [x86_64-linux]
As you see in the output above, the development environment is ready with Python 3.8.19, Node 18.19.1 and Ruby 3.1.4 installed. You can now start building and testing your applications.
Exit Nix-shell
To exit from the nix-shell, simply type:
$ exit
Or you can press CTRL+D
to exit from the shell.
When you exit the nix-shell
environment, the following happens:
- Environment Isolation Ends: The isolated development environment created by
nix-shell
is temporary and exists only for the duration of the shell session. Once you exit thenix-shell
, the isolation provided by that environment is removed, and your shell returns to its previous state. - Packages and Dependencies are Unloaded: All the packages, dependencies, and environment variables that were loaded and made available within the
nix-shell
environment are unloaded and no longer accessible from your shell. Any commands or tools that relied on those packages will no longer work unless they are installed system-wide or in another environment. - Shell Environment Reverts: The shell environment, including PATH, environment variables, and other settings, reverts to their state before entering the
nix-shell
. Any modifications made to these settings within thenix-shell
are undone. - No Persistent Changes: By default,
nix-shell
does not make any persistent changes to your system. The isolation and changes made within thenix-shell
environment are temporary and do not affect your system-wide configuration or installed packages. - Project State: Any files or changes you made within the
nix-shell
environment, such as creating or modifying files in your project directory, will persist even after exiting thenix-shell
. Only the environment itself is temporary, not the files you worked on. - Garbage Collection: Over time, as you use more packages and possibly update them, the Nix store can grow in size because it keeps old versions of packages. These packages and environments remain accessible until a Nix garbage collection is performed. Exiting
nix-shell
doesn't automatically trigger garbage collection. You can manually initiate a garbage collection to remove unused packages from the Nix store, freeing up disk space. Refer our getting started with Nix guide to know how to clean up unused packages.
In summary, exiting nix-shell
cleanly separates you from the temporary development environment it provided, without affecting your system's global environment or removing any data from your projects. The packages used remain in the Nix store for efficient reuse, ensuring your system remains clean and your development environments are reproducible and isolated.
If you need to use the same development environment again, you can simply re-enter the nix-shell
by running the nix-shell
command from the same directory containing your shell.nix
file. This will recreate the isolated environment with the specified dependencies.
Frequently Asked Questions
Here's a list commonly asked questions (FAQ) and answers about Nix.
nix-shell
?A: nix-shell
is a command-line tool provided by the Nix package manager that creates a temporary shell environment with specific software packages installed. It is designed to provide an isolated environment for development or testing without affecting the rest of the system.
nix-shell
?A: nix-shell
is part of the Nix package manager. To use nix-shell
, you must first install Nix on your system. You can install Nix by referring our Nix Installation guide.
nix-shell
to create an isolated environment?A: To create an isolated environment, you can use a shell.nix
file in your project directory that specifies the dependencies required. Running nix-shell
in the directory containing shell.nix
will drop you into a shell with those dependencies available. Alternatively, for ad-hoc environments, you can use nix-shell -p package1 package2 ...
to specify packages directly.
nix-shell
on any operating system?A: nix-shell
works on most Unix-like operating systems, including Linux distributions and macOS. It is not natively supported on Windows, but Windows users can access it via the Windows Subsystem for Linux (WSL).
nix-shell
?A: When you exit nix-shell
, the environment it created is dismantled. The temporary additions to your PATH and other environment variables are reverted, returning your shell to its previous state. The packages used remain in the Nix store for future use but are no longer accessible outside of nix-shell
unless installed globally.
nix-shell
avoid "dependency hell"?A: nix-shell
uses the Nix package manager's purely functional approach to package management, where each package is built and stored in an isolated environment. Dependencies for each package are explicitly defined and do not interfere with each other, thus avoiding the common issue of conflicting dependencies.
nix-shell
environment?A: While nix-shell
itself does not directly save states of environments, the declarative nature of the shell.nix
file means your environment is reproducible. Anyone with the same shell.nix
can recreate the identical environment. For more complex scenarios, consider using Nix's ability to create custom packages or even entire system configurations.
nix-shell
environment?A: To modify the packages in your environment, edit the shell.nix
file to add or remove packages from the buildInputs
list in the shell.nix
file. If you are using an ad-hoc environment created with -p
, simply adjust the list of packages you provide to the command.
A: Nix allows you to manually perform garbage collection to remove unused packages from the Nix store, freeing up disk space. You can do this by running nix-collect-garbage -d
from the command line.
Conclusion
Nix-shell helps you keep your development organized. It lets you build separate workspaces for each project, with all the tools they need. This prevents conflicts between projects and ensures everything works the same way on different computers. Now you can focus on coding, not wrestling with software clashes.
Resource:
Related Read:
- Create NodeJS Virtual Environments Using Conda In Linux
- Create Rust Virtual Environments Using Conda In Linux
- Create Golang Virtual Environments Using Conda In Linux
- How To Manage Python Packages Using PIP
- Pipx – Install And Run Python Applications In Isolated Environments
- Pipenv – The Officially Recommended Python Packaging Tool