Running software in NixOS

NixOS is a Linux distribution based around nix package manager, and it is well known for it’s steep learning curve and overly complex features. I recently moved to NixOS for it’s vast package repositories, clean configuration from one set of config files, and ability to rollback updates.

But I, like many more people, noticed that one of things NixOS could have definitely done better is documentation. It does not do a good job explaining why you should do something, like, for example, installing software, in one way or another, and does not even list supported ways in one place.

Video Link to heading

Before I start this video, I should make a quick notice. This video talks about quite complex and not self-explanatory topic, which is not made better by branding for Nix and NixOS being very confusing at times.

When I say package, which usually means “software packaged as file that will be unpacked by system to install”, I mean Nix derivation. It is basically the same for you, but there is some technical differences, such as storing in nix store instead of unpacking and made to be automatically built from source instead of packaged and downloaded.

Nix does a lot of work for you to not notice it, such as checking external website for prebuilt packages so you don’t need to waste your computing resources on building everything from source, and managing applications so you can launch everything normally from command line or graphical interface without thinking how they are actually stored.

Note

I will also mention Flakes. They are nix flakes, new experimental format for config files and packages that is better than current one with newer, faster and more user friendly versions of command line tools made for it, but it is slightly more complex and is not used by default just yet. Enabling flake support is pretty easy with this option in your NixOS config.

nix.settings.experimental-features = [ "nix-command" "flakes" ];

Imperatively installing software Link to heading

Imperatively installing packages on user level is possible with this commands, which is not reccomended, but still usable, especially outside of NixOS.

nix-env Link to heading

Example
nix-env -iA nixos.minetest # on nixos
nix-env -iA nixpkgs.minetest # outside of nixos

nix profiles Link to heading

Nix profile, which is a flake way of installing a packages, is a little bit different, since it will install package inside of so called profile, with ability to do rollbacks and have several independent profiles, and will install package from latest, unstable repository.

Example
nix profile install nixpkgs#minetest # latest unstable repository
nix profile install nixpkgs/nixos-23-05#minetest # 23.05 stable version
Warning
Profile has higher priority than nix-env, so packages installed through later will not be available until you delete profile and stop using nix profile command.

Trying out software (Imperatively) Link to heading

This is a ways to download or build packages and run software in them from separate command line session without persistently installing anything in system. This allows user to try out new software or to use some usually not needed packages without bloating the system.

nix-shell Link to heading

Example
nix-shell -p minetest
# use software
exit # quit from nix shell

nix shell and nix run Link to heading

Example
nix shell nixpkgs#minetest
#use software
exit

# or

nix run nixpkgs#minetest # run main executable once
nix run nixpkgs#minetest -- --help # pass arguments to executable

All three of these are also viable for running software outside of NixOS or without root access.

Warning

Downloaded packages are still stored on device, they are deleted with nix-collect garbage command.

https://nixos.org/manual/nix/stable/command-ref/nix-collect-garbage

Configuration files Link to heading

Main way to persistently install package on NixOS is to modify NixOS configuration file or module imported in such file. Easiest way to do this is with enviroment.systemPackages, where you define packages available to any user on system, as list of package names prefixed with pkgs. and separated by spaces.

Example
{ pkgs, config, lib, ... }:
{
    ...

    enviroment.systemPackages = with pkgs; [
        minetest
        taisei
    ];

    ...
}

Other way is to use user-specific package list in users.users.username.packages which works almost the same, or use an nixos options to install and possibly even configure software that supports it, on a system level. Some software does not work well if installed only as a package, especially if it requires some system-wide changes or daemon to run, and some is not available as configuration option, but works as just a package.

Example
{ pkgs, config, lib, ... }:
{
    ...

    users.users.laika.packages = with pkgs; [
        minetest
        taisei
    ];
    programs.kdeconnect.enable = true;

    ...
}
Warning
For changes to be applied, use sudo nixos-rebuild switch command. Reboot may also be needed for big updates and driver-related changes.

This is a way you will usually install software on nixos, since it allows to rebuild the same system on other device with same software and even most of system-wide settings.

Info
Good noob-friendly guide on this - https://itsfoss.com/nixos-package-management/

Home Manager Link to heading

If you are not on NixOS, or if you are a user without a root access, and want to also have repoducible config-based software list, or if you want to setup user application settings from main config files, in all of that cases you need Home Manager. It is external software that allows you to manage your user-specific software and its configuration, using nix.

Basically, it is a software and a set of configuration files created by user either in home directory or imported inside system config. You can just add home.packages similar to user packages in nixos configuration, or use home manager options, similar to nixos system-wide options.

It also may return errors when it encounters preexisting configuration files, in that case you need to move them out of the way or delete if you are sure you do not need them.

Info

Shell files and Flake development shells Link to heading

In case if you need some kind of working environment, set of packages and environment variables outside of your system configuration that you can just share to any person who also has nix, your stop is shell.nix, or rather, a nix config file you can use to call nix-shell command to get config from it instead of manually specifying package names every time. Use nix-shell shell.nix, or just nix-shell in the same directory, to use this shell file.

Example
{ pkgs ? import <nixpkgs> {} }:
  pkgs.mkShell {
    nativeBuildInputs = with pkgs; [
        minetest
        blockbench
        blender
    ];
}

In case of flakes, though, it is made using a specific option inside of flake file, with different syntax, and is called using nix develop command instead.

Non-nixos executables Link to heading

But what if you need to launch something not in NixOS repositories? Of course, Nixpkgs has a lot of packages ported from other distributions and standalone executables, you will still need to run some specific not packaged software. It is harder to do in NixOS since it does not abide by some standards, making just launching executable directly impossible, but it is actually still possible using built-in nix functions through some external tools.

Steam-run Link to heading

Easiest way to do this if software is standalone binary, or binary in folder with everything near it, like most of games, is to run it through steam-run, a tool emulating standard linux distribution with most common dependencies. It is called that way because it uses same settings as package used to install Steam, the videogame store and platform.

Example
steam-run ./a.out
steam-run ./GodotGame.x86_64
Info
Steam NixOS wiki page - https://nixos.wiki/wiki/Steam

Appimage-run Link to heading

If software is packaged as appimage instead, which is easy to know if you look at file extension, you need to run it using appImage-run tool, which works in a similar way, but tailored towards appimages.

Example
appimage-run ./appimage.AppImage
Info
AppImage NixOS Wiki page - https://nixos.wiki/wiki/Appimage

Ending Link to heading

There is some other other methods, both specific to NixOS, like nix-alien and nix-LD, and just available for any linux distribution, like Wine for Windows applications, Flatpak and Docker for Linux software packaged for them, Waydroid for android applications, and many more, but that could be a topic for another day. I hope this article was useful to you.