Nix
Updated: September 28, 2024
Nix is a package manager, repository, operating system and programming language.
Note: This page will be stuctured in the usage of Nix and nixOs and interacting with the repository, less about the language (maybe)
It is not necessary to use every single thing Nix offers. The Nix Package Manager can be used without Nixos. NixOS can be used without Home Manager or Hyprland. Mac people can combine Nix, Home Manager, & Homebrew. You get the idea. I would be remissed if I did not mention the most glorious system combination:
NixOS + Nix + Home Manager + Hyprland for those that want a God Complex
Table of Contents
Resources
nixos.org
github
nix.dev
Home Manager
hyprland.org
What can Nix do?
Youtube Guide
nixified.ai
# run the nixified.ai flake (choose nvidia or amd)
nix run github:nixified.ai/flake#[textgen || invokeai]-[nvidia || amd]
Nix Package Manager
This tool may be installed and used on non-nixos operating systems.
It is included for NixOS, but it is feasible to be used without NixOS.
It can even be run on mac, docker or WSL2. Nix still retains
the ability to revert changes or have throw away shells using nix-shell:
# create a shell with python installed, that is gone after closing session
nix-shell -p python3
# create a shell with home manager installed
nix-shell -p home-manager
The advantage of nix is that your configs and tooling can be built exactly the same, no matter
the computer system, especially if using flakes instead of channel.
Choose Nix Package Manager Installer
Recommended Installer has advantages:
- Do not have any config steps that Official
- Includes an uninstaller
- Sets up daemon properly
- Flakes are adopted and ready to go
- Works on Linux, MacOS, Containers, WSL
- Works with MacOS upgrades
Official Nix and NixOS Installer
- Must edit /etc/nix/nix.conf
- If Multi-user installation must add profile to your preferred shell
- Steps my need to be redone after an OS upgrade
build-users-group = nixbld
experimental-features = nix-command flakes
I keep in a starship module attached to my zsh configuration
If running nix as a Multi-user installation (includes a daemon) it may not start after reboot. Let ensure it does:
# In ~/.zshrc or ~/.bashrc copy anywhere into the file, I append to the end.
# Nix
if [ -e '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh' ]; then
. '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh'
fi
You Should Know
Nix will be placed in its own partition and added to your fstab.
Nix does not follow a normal Filesystem Hierarchy Standard (FHS). ie /usr /lib /local /etc
Instead it places itself in very few places:
First is nix.conf file location in /etc/nix
Second is where store is located in /nix/ (straight off root)
To make changes to Nix access /etc/nix/nix.conf with either sudoedit
or sudo vim
This is because of it being in a secure location of /etc that requires priveledge escalation.
** Do not install programs using nix-env, this is imperative not declarative.**
Installing this way is not reproducible nor follows the intent of Nix!
Instead, consider using flakes or Home Manager
When using Git there may be the following term:
Git Tree is Dirty == there are changes to tracked files in working directory that are not staged or commited.
Channel vs Flakes (Experimental – not really)
While flakes are marked as experimental, do not be discouraged from using them. The developers at Nix promote them. So what is a flake and why use them?
By default Nix Packages Manager and NixOS are set to a channel. That channel indicates the version (branch) of the git repository you are pulling all the packages for compiling. Initially set to the most stable version as of this date it is nixOs v23.11 and Nix v2.19.2. These channels can be set to older versions or the bleeding edge which is the unstable channel.
What a flake intends to do is replace the channel by pinning it for a specific build. When you create a flake.nix file and run it. It will create an additional file called flake.lock. This file pins all the version information so that way when the channel changes, the flake build doesn’t. (Flakes can still manually update the versioning but the key is the build version is under your control).
Channel - exact package versions are stored outside config files.
Flakes - exact package versions are stated inside config files.
If you added a wrong channel and --update
fails to work:
# see list of channels
nix-channel --list
# remove broken channel
nix-channel --remove nixpkgs
Flakes are file(s) selected by paths, so this allows the use of multiple flakes.
They can be run seperately. Lets go over some path details.
.: # refers to a flake in current directory
dir: # flake is located in a subdirectory
narHash: # flake is in tarball form, thus lacks a unique content identifier
ref: # refers to a git branch or tag name
rev: # refers to a git commit hash
Flakes can be different types:
- Indirect (default) refer to a flake registry
- [flake:](/(/rev)?)?
- nixpkgs
- nixpkgs/nixos-unstable
- nixpkgs/a3a3dda3bacf61e8a39258a0ed9c924eeca8e293
- nixpkgs/nixos-unstable/a3a3dda3bacf61e8a39258a0ed9c924eeca8e293
- Path refers to local directories && not in a git repository
- path:(?)?
- path:/home/user/sub/dir
- /home/user/sub/dir
- ./sub/dir (when used on the command line and dir/flake.nix is not in a git repository)
- Git refers to a repository via URL
- git(+http|+https|+ssh|+git|+file):(//)?(?)?
- ref defaults to HEAD reference
- rev defaults to commit currently pointed to by ref
- git:/home/user/sub/dir
- /home/user/sub/dir (if dir/flake.nix is in a git repository)
- ./sub/dir (when used on the command line and dir/flake.nix is in a git repository)
- git+https://example.org/my/repo
- git+https://example.org/my/repo?dir=flake1
- git+ssh://git@github.com/NixOS/nix?ref=v1.2.3
- git://github.com/edolstra/dwarffs?ref=unstable&rev=e486d8d40e626a20e06d792db8cc5ac5aba9a5b4
- git+file:///home/my-user/some-repo/some-repo
- git(+http|+https|+ssh|+git|+file):(//)?(?)?
- Tarball refers to an archive - if format (.zip, .tar, .tgz, .tar.gz, .tar.xz, .tar.bz2 or .tar.zst), then the tarball+ can be dropped
- tarball(+http|+https|+file)://
- File refers to plain files or directory tarballs, either over http(s) or from the local disk
- file(+http|+https|+file)://
- Github downloaded as tarballs
- github:/(/)?(?)?
- github:edolstra/dwarffs
- github:edolstra/dwarffs/unstable
- github:edolstra/dwarffs/d3f2baba8f425779026c6ec04021b2e927f61e31
- github:internal/project?host=company-github.example.org
- Gitlab same as Github but also need to URL-encode / with %2F
- gitlab:/(/)?(?)?
- gitlab:veloren/veloren
- gitlab:veloren/veloren/master
- gitlab:veloren/veloren/80a4d7f13492d916e47d6195be23acae8001985a
- gitlab:openldap/openldap?host=git.openldap.org
NixOS
NixOS is a linux distribution that is like no other. Just as it is inside it’s own package manager. It could be argued as being one the most stable systems due to it’s reproducibility and rollback function. This is in part because NixOS follows the declarative model instead of most systems imperative model.
In declarative, the system settings, configurations, dependecies, everything are declared up front for how the system will be built. When changes need to be made, they are again adjusted in the config file and the system is rebuilt. If something fails, the state is moved back. This keeps the system from having any unwanted or unnecessary files. The system stays clean… Forever.
In imperative, the system starts with a base, slowly and chaotically making changes to the system until satisfied with the result… Over time the system gets crufty with no longer used dependencies, settings that, if things go bad, are gone forever - good luck remember what changes you made. And how much work will it be to rebuild an imperative system? With NixOS you can have the EXACT system rebuilt in a few minutes! This is especially great if using many machines.
Benefits of NixOS:
- Declarative - declare the state of all things to include in the build.
- Immutable - components are replaced rather than changed
- Reproducible - build exact replica’s of state even on different hardware
- Unbreakable - extreme stability due to the aforementioned
Install NixOS
Install goes about the same as any distro. NixOS uses their pre-built version of Calamares to assist with a GUI walk-through install. The Download and instructions.
While in Calamares install do:
- Do create a swap file (4gb is good) unless creating a virtual machine.
- Do select the setting for unfree to avoid future issues.
- Make sure you have internet for the install process
After the base install and logging in, it’s time to manage the system with config files.
Configuation of NixOS
NixOS is controlled by 2 files similar to Nix Package Manager, but in their own location of /etc/nixos/ Again, because of their location in /etc they can only be edited with priveledge: sudo vim or sudoedit.
configuration.nix - this is the file where most changes to the system are made.
hardware-configuration.nix - relatively little reason to ever touch this file.
The details of what all goes into the file cannot at this point be shown because we all want our systems to have different things. Look online for git repos or check [resources]{#resources} for the specific applications and settings you are looking for. This guide is just to set a basic understainding on how to setup and the principles to maintain these setups. Speaking of which, lets talk about Home Manager!
NixOS Commands
This is by no means an exhaustive list but the most commonly useful:
shutdown # systemctl poweroff
reboot # systemctl reboot
systemctl kexec # bypass BIOS and load new kernel into memory
loginctl # see list of current users
loginctl session-status c3 # see details of user session
loginctl terminate--session c3 # end session and all it's processes
nixos-version # version, git branch & name
sudo nixos-rebuild switch # rebuild and set as boot
--upgrade # apt update and upgrade equivalent
--rollback # switch to the previous configuration of a running system
--repair # check for bad hashes and replace with new correct paths
test # rebuild but do not set as boot
systemd-cgls # list all control groups and their processes
nix-collect-garbage # remove old, unreference packages from /nix/store
-d # deletes old roots, removing the abiity to roll back to them
nix-store --optimise # finds identicle files in nix store, hard links to single copy
--verify --check-contents --repair # scan entire nix store for corrupt and repair
Home Manager
Home Manager is another part of Nix, like a pet project. And what does this do? Well, you know how as you customize certain programs like vim or maybe your terminal or git tooling? What you end up with is a bunch of .dotfiles.
Home Manager manages the type of settings that would exist in all the different places of all the different .dotfiles. Not only does it manage them but does it in the Nix way, with immutability, reproducibility, reliability and declaratively. Starting to see the pattern? Good.
Home Manager can be implemented 2 ways depending if NixOS or Other OS.
# NixOS option in configuration.nix
environment.systemPackages = [
pkgs.home-manager
]
# Other Linux distro or MacOs (create a shell with it) ie must have nix installed!
nix-shell -p home-manager
For the initialization just have to run one command:
# This command will generate 2 files: home.nix and flake.nix in ~/.config/home-manager/
home-manager init
NixOS has the additional option of turning this Standalone into a Method importing into NixOS build itself. Keep in mind, Standalone is set by the flake.nix as default, and is not part of the NixOS build cycle. If on NixOS, one could make changes in flake.nix to import Home Manager as a module of NixOS. Standalone means that our home has no root but can be ported to anywhere (brought to other systems including Non-NixOS, like Mac or Debian). Lets look at an example flake.nix that is cleaned up some. Again, not everything is in there but there are many more settings that can be added, just rebuild each iteration.
# This ~/.config/home-manager/flake.nix sets as a standalone for my Mac Mini M2 Pro
# Completely generated from the home-manager init
{
description = "Home Manager configuration of megacron";
inputs = {
# Specify the source of Home Manager and Nixpkgs.
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
home-manager = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { nixpkgs, home-manager, ... }:
let
system = "aarch64-darwin";
pkgs = nixpkgs.legacyPackages.${system};
in {
homeConfigurations."megacron" = home-manager.lib.homeManagerConfiguration {
inherit pkgs;
# Specify your home configuration modules here, for example,
# the path to your home.nix.
modules = [ ./home.nix ];
# Optionally use extraSpecialArgs
# to pass through arguments to home.nix
};
};
}
See how all this stuff is pulled from a git repo. Nix and NixOS is all about compiling from github.
Ok, so now that Home Manager is set to either Standalone or NixOS Module. Where do we make changes to our services and customizations of our .dotfiles? Well, here is an example with a few services added with a bit of cleanup. Keep in mind, we do not have to change everything all at once. Just something slowly overtime, adding them in, who knows, maybe in a year with a little luck, you’ll have something :p
# ~/.config/home-manager/home.nix
{
home.username = "megacron";
home.homeDirectory = "/Users/megacron";
home.stateVersion = "23.11"; # Please read the comment before changing.
home.packages = [
pkgs.hello
(pkgs.nerdfonts.override { fonts = [ "Maple Mono" ]; })
];
home.file = {
};
home.sessionVariables = {
EDITOR = "vim";
};
programs.home-manager.enable = true;
programs.git = {
enable = true;
userName = "megacron";
userEmail = "secureemail@pm.me";
aliases = {
pu = "push";
co = "checkout";
cm = "commit";
};
};
programs.zsh = {
enable = true;
enableAutosuggestions = true;
enableCompletion = true;
};
}
In the end, what will happen is Home Manager will the create symlink locations to the proper places within the FHS. Once again what is nice is that these config stored in a git repo are replicable. In order to apply the changes we must do a rebuild.
# short
home-manager switch
# full
home-manager switch --flake ~/.config/home-manager/#username
# see old configurations
home-manager generations
# copy a path from command above and add /activate on the end of it to roll back
/nix/store/asdfa8sdf876asdfia8sdf8asdf87-home-manager-generation/activate
There is more implementation within a flake for NixOS to import ./home.nix into the ./hardware-configuration.nix which means
that Home Manager is being maintained as a module with NixOS. Therefore, binding the Home Manager setting in with the rest of the root NixOS settings. Setting up as a module loses portability to other operating systems as Home is built into NixOS. The upside is with a few additonal changes to the flake.nix file, use nixos-rebuild switch
command to implement Home Manager changes like so:
sudo nixos-rebuild switch --flake ~/path/to/flake/#myNixOS
Most people prefer Standalone vs NixOS Module. It is nice to control certain things seperately. By the way, it is possible to control these home manager setting purely in NixOS without the need for Home Manager, but again, those settings stay in NixOS.
And Finally Hyprland
hyprland.org is really for those using Linux, and even then, it’s recommended for Arch or NixOS. The other distros are slow to patch, therefore, likely to fail. Don’t be foolish, of course you’re using NixOS, right? RIIIGHT?!?
So, some other things to know about Hyprland, we first have to know how it is drop in replacement for that involves a key shift that is going on in the paint to screen world. XORG has been the long running champ for drawing images on the screens as most applications are writting to that fact. However, since 2008 Wayland has been in development to replace XORG. It has come along way and we are starting to see applications that rely on wayland…Hyprland compositor being one of them, does not rely on xserver.
Needless to say, it needs work on performance and some bugginess. That takes the few of us who are willing to leap into the depths of change, and forge the way with a bit of adventure. With a NixOS system it is possible to swap out desktops on a whim and in a manner of minutes. Just as easy as going from GNOME to KDE to Plasma. I wouldn’t worry too much about it since NixOS is very good at rolling back when the system goes awry. Wihtout further ado, let’s talk about how to implement this beast.
For a non Nvidia system add
# non-Nvidia enabling of hyprland on NixOS
programs.hyprland.enable = true;
For Nvidia there are additional patches and stuff
# Nvidia enabling of hyprland on NixOS
programs.hyprland = {
enable = true;
nvidiaPatches = true;
xwayland.enable = true;
};
environment.sessionVariables = {
# If cursor becomes invisible
WLR_NO_HARDWARE_CURSORS = "1";
# Hint electron apps like discord to use wayland
NIXOS_OZONE_WL = "1";
};
Additonal things
hardware = {
# opengl
opengl.enable = true;
# most wayland compositors need this
nvidia.modesetting.enable = true;
};
environment.systemPackages = [
(pkgs.waybar.overrideAttrs (oldAttrs: {
mesonFlags = oldAttrs.mesonFlags ++ [ "-Dexperimental=true" ];
})
)
# lookup either x or pure wayland
pkgs.dunst
# lookup
pkgs.mako
# add this
libnotify
# wallpaper daemons
hyprpaper
swaybg
wpaperd
mpvpaper
swww # <--> we'll use this one
#hyprland's default terminal
kitty
# the one I like
wezterm
# pick your own terminal
alacritty
# app launchers
rofi-wayland
wofi
bemenu
fuzzel
tofi
];
# XDG portal
xdg.portal.enable = true;
xdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
# enable sound with pipewire.
sound.enable = true;
security.rtkit.enable = true;
services.pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
jack.enable = true;
};
Some standard things to have in your hyprland file before starting it up, pick one:
environment.systemPackages = {
# This one is simplet, configured with json and css
pkgs.waybar
# Elkwar's Widgets if you want to go crazy with it's own markup language
pkgs.eww
};
Anyway, this is too much to mention as with the others just search out the setting and changes you want to make and add them to the file. Where is the file anyway, you ask?
~/.config/hypr/hyprland.conf
Setup swww
In order to run scripts add to the bottom
exec-once=bash ~/.config/hypr/start.sh
Create startup script start.sh and make executable
touch ~/.config/hypr/start.sh
chmod +x ~/.config/hypr/start.sh
# Inside the file
#!/usr/bin/env bash
# initializing wallpaper daemon
swww init &
# setting wallpaper
swww img ~/Wallpapers/gruvbox-mountain-village.png &
# you can install this by adding
# pkgs.networkmanagerapplet to your packages
nm-applet --indicator &
# the bar
waybar &
# dunst
dunst
Hyprland can be restarted using super + m instead of doing a reboot
Other notes
# screenshot your desktop with selection
grim -l 0 -g "(slurp)" - | wl-copy
pkgs.griim - screenshot utility
pkgs.slurp - select utility
pkgs.wl-clipboard - xclip alternative
Anyway, that is all I have for now. Give me a year or so and hopefully I can supply my own repos of code with screenshots so you can have my exact setup for yourself ⸜(。˃ ᵕ ˂ )⸝♡