Home NixOS How To Create Development Environments With Nix-shell In Linux

How To Create Development Environments With Nix-shell In Linux

Nix-Shell Tutorial: Isolated Development Environments Made Easy

By sk
Published: Updated: 843 views

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.

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.

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]
Create and Manage Development Environments with Nix-shell
Create and Manage Development Environments with Nix-shell

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:

  1. 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 the nix-shell, the isolation provided by that environment is removed, and your shell returns to its previous state.
  2. 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.
  3. 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 the nix-shell are undone.
  4. No Persistent Changes: By default, nix-shell does not make any persistent changes to your system. The isolation and changes made within the nix-shell environment are temporary and do not affect your system-wide configuration or installed packages.
  5. 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 the nix-shell. Only the environment itself is temporary, not the files you worked on.
  6. 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.

Q: What is 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.

Q: How do I install 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.

Q: How do I use 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.

Q: Can I use 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).

Q: What happens to my environment when I exit 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.

Q: How does 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.

Q: Can I save the state of a 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.

Q: How do I add or remove packages from a 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.

Q: How can I perform garbage collection for unused packages?

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:

You May Also Like

Leave a Comment

* By using this form you agree with the storage and handling of your data by this website.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

This website uses cookies to improve your experience. By using this site, we will assume that you're OK with it. Accept Read More