NixOS Journey, Part 1
So, for those who have yet to go down this path, it would be helpful to explain what NixOS is. NixOS is a free and open-source Linux distribution. What sets itself apart from Pop!os, Debian, Ubuntu, Arch, and many others is that its entire operating system is built by the Nix package manager. This includes nix application packages, your kernel, system settings, SMB shares, and pretty much anything you can think of.
What this allows the users to do is work within a declarativve configuration. If you make a change to the configuration file and want the changes to take, you run nixos-rebuild switch
. NixOS then takes in the new changes, goes out to get new packages if needed, and generates a new configuration file. If this breaks anything or you just want to go back to the previous version, all you have to do is nixos-rebuild switch --rollback
. Even on boot, you are presented with previous nixos-rebuild
events that you can select and boot right into. Combine this with commiting to github or version control manager and you could start sharing your configs with other devices.
Are you starting to get it yet?
To most, even the seasoned Linux user, nixOS can be daunting at a glance. It takes every fiber of my being not to install packages via apt install
or snap install
or yum install
. Finding packages that the community and nixOS team have compiled specifically for nixOS is easy, and can be done by searching directly on the site (https://search.nixos.org/packages). However, there is a possibility that your favorite package may not be packaged yet. You can request that package be assembled via github (https://github.com/NixOS/nixpkgs/issues). I am currently hoping for tabby.sh to be packaged up for me so I can use my favorite terminal app. Someone already requested it, but fingers crossed it gets done!
But the catch is, while you can “install” packages using nix-env -iA cider
, for example. This installs at the user level, so it will not be system wide and will not appear in your nixOS config. Additionally, you can try out a package without installing it by running nix shell
, and a shell instance will run the package. When the shell instance is terminated, it will no longer persist on your device.
The NixOS Config
I have referenced the “nixOS config” file a few times now, which is the whole reason why I wanted to try nixOS out. It is just like any config file, but you can declare your entire state in this SINGLE file. Got a bunch of guh-nome (gnome) extensions you always setup on a fresh install? Yeah, you can declare that in your nix config file. Packages? Easy, all in the config file. Services like your vpn, syncthing shared folders, and your tailscale mesh network? Ye…you get the point.
The ‘Planned’ Outcome
The whole purpose of this is for me to, at the end of all of this fiddling around, have a nixOS config file that I can pull down from my private repo, run nixos-rebuild switch
and let the device configure itself. I want to be able to do this on all of my laptops or desktops that I come in possession of. That way, I have the same desktop environment switching from one device to the next.
The Stretch Goal
You know what would be really nice? Moving all my servers over from Debian and Ubuntu to nixOS………..
NixOS Config (as of 2023/12/29)
{ config, pkgs, ... }:
{
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
];
# Bootloader.
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
networking.hostName = "nixos"; # Define your hostname.
# networking.wireless.enable = true; # Enables wireless support via wpa_supplicant.
# Configure network proxy if necessary
# networking.proxy.default = "http://user:password@proxy:port/";
# networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";
# Enable networking
networking.networkmanager.enable = true;
# Set your time zone.
time.timeZone = "America/Chicago";
# Select internationalisation properties.
i18n.defaultLocale = "en_US.UTF-8";
i18n.extraLocaleSettings = {
LC_ADDRESS = "en_US.UTF-8";
LC_IDENTIFICATION = "en_US.UTF-8";
LC_MEASUREMENT = "en_US.UTF-8";
LC_MONETARY = "en_US.UTF-8";
LC_NAME = "en_US.UTF-8";
LC_NUMERIC = "en_US.UTF-8";
LC_PAPER = "en_US.UTF-8";
LC_TELEPHONE = "en_US.UTF-8";
LC_TIME = "en_US.UTF-8";
};
# Enable the X11 windowing system.
services.xserver.enable = true;
# Enable the GNOME Desktop Environment.
services.xserver.displayManager.gdm.enable = true;
services.xserver.desktopManager.gnome.enable = true;
# Tailcale
services.tailscale.enable = true;
# Configure keymap in X11
services.xserver = {
layout = "us";
xkbVariant = "";
};
# Enable CUPS to print documents.
services.printing.enable = true;
# Enable sound with pipewire.
sound.enable = true;
hardware.pulseaudio.enable = false;
security.rtkit.enable = true;
services.pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
# If you want to use JACK applications, uncomment this
#jack.enable = true;
# use the example session manager (no others are packaged yet so this is enabled by default,
# no need to redefine it in your config for now)
#media-session.enable = true;
};
# Enable touchpad support (enabled default in most desktopManager).
# services.xserver.libinput.enable = true;
# Define a user account. Don't forget to set a password with ‘passwd’.
users.users.randoneering = {
isNormalUser = true;
description = "randoneering";
extraGroups = [ "networkmanager" "wheel" ];
packages = with pkgs; [
firefox
# thunderbird
];
};
# Allow unfree packages
nixpkgs.config.allowUnfree = true;
nixpkgs.config.permittedInsecurePackages = [
"electron-24.8.6"
];
# List packages installed in system profile. To search, run:
# $ nix search wget
environment.systemPackages = with pkgs; [
firefox
element-desktop
discord
cider
vscodium
remmina
wget
neofetch
signal-desktop
obsidian
syncthing
gnome-extension-manager
git
steam
bitwarden
tailscale
bash
gnome.gnome-tweaks
gnomeExtensions.tophat
gnomeExtensions.dash-to-panel
woeusb
vlc
bspwn
python3
bottom
fish
terminator
openvpn3
tuba
zoom-us
popsicle
gimp
inkscape
flameshot
gnupg
hugo
tailscale
starship
zip
rake
rubyPackages.rake
libgtop
gtop
flameshot
pinentry
pinentry-curses
pinentry-gtk2
pinentry-gnome
brave
];
# Some programs need SUID wrappers, can be configured further or are
# started in user sessions.
# programs.mtr.enable = true;
programs.gnupg.agent = {
enable = true;
pinentryFlavor = "gtk2";
enableSSHSupport = true;
# };
#
# List services that you want to enable:
# Enable the OpenSSH daemon.
services.openssh.enable = true;
services.syncthing = {
enable = true;
user = "randoneering";
dataDir = "/home/randoneering/Documents/"; # Default folder for new synced folders
configDir = "/home/randoneering/Documents/.config/syncthing";
};
# Open ports in the firewall.
# networking.firewall.allowedTCPPorts = [ ... ];
# networking.firewall.allowedUDPPorts = [ ... ];
# Or disable the firewall altogether.
# networking.firewall.enable = false;
# This value determines the NixOS release from which the default
# settings for stateful data, like file locations and database versions
# on your system were taken. It‘s perfectly fine and recommended to leave
# this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "23.05"; # Did you read the comment?
}