Started on Jun 20, 2024. Still updating.
Distro | Package Manager | Minimal | Comments |
---|---|---|---|
PeppermintOS | Debian based | Yes | Small community; only xfce supported? |
antiX Linux | Debian based | Extremely | Looks old |
Tiny Core Linux | Extremely | Advanced | |
Void Linux | XBPS (independent) | No | |
Arch Linux | Pacman (AUR - independent) | Maybe | Great documentation |
✔️ NixOS | Nix (independent) | No | Has the most packages; clean config |
Display Server & Window Manager
X11 will be replaced by Wayland.
Compositing Window Manager |
Minimal Eyecandy |
Comments |
---|---|---|
Qtile | Neither | Written in Python |
Sway | Neither | |
dwl | Minimal | dwm fork |
SwayFX | Eyecandy | Inferior to Hyprland? |
river | Minimal | Lacking wiki |
✔️ Hyprland | Eyecandy | Great wiki |
A command shell converts human commands to something the kernel understands. Use $ echo $SHELL
to see the current command shell. NixOS by default uses Bourne-Again shell (bash). Popular modern command shells:
- Friendly Interactive Shell (fish)
- ✔️ Z Shell (zsh)
Terminals provide access to the command shell. The TTY (TeleTYpe informally, virtual terminal formally, framebuffer terminal functionally; switch between TTYs using ctrl+alt+F#) does not support copy and paste, panels, scrolling, multitasking with multiple windows, etc... Therefore, a non-framebuffer terminal emulator is useful for using commands without having to switch out of the graphical environment.
- Alacritty: A cross-platform, OpenGL terminal emulator.
- Foot: A fast, lightweight and minimalistic Wayland terminal emulator.
- Terminator: Multiple GNOME terminals in one window!
- WezTerm: A GPU-accelerated cross-platform terminal emulator and multiplexer written by @wez and implemented in Rust.
- ✔️ kitty: The fast, feature-rich, GPU based terminal emulator.
Not included in Home Manager option documentation:
- Konsole: A powerful and customizable terminal emulator made by KDE.
- MLTERM: Multi Lingual TERMinal emulator.
- st: A simple terminal implementation for X.
- Warp: The terminal reimagined with AI and collaborative tools for better productivity.
- Contour: A modern & actually fast Terminal Emulator.
- Darktile: A GPU rendered terminal emulator designed for tiling window managers.
Not in nixpkgs:
- Blink: Chromium
- QtWebEngine (Chromium): Qutebrowser
- ✔️ Gecko: Firefox
Other web engines have outdated browsers.
Text based browsers are interesting but impractical.
Forks of Firefox or Chromium are generally inferior. Edge, Brave, and Opera are modern but bloated.
Numix, Gruppled, Graphite, Afterglow (recolored), McMojave, Breeze Hacked, Comix, Bibata, Google inspired, Phinger, Quintom, Whitesur, Vimix, Catppuccin, Vanilla DMZ, OpenZone, Hackneyed, Borealis, Nordzy, Simp1e, Volantes, ✔️ Capitaine, ...
Wayland wallpaper managers (all in nixpkgs):
Manager | Animated | Transitions | Home Manager |
---|---|---|---|
swaybg | ? | ? | No |
mpvpaper | MPV | ? | No |
Wallutils | No | Yes | No |
wbg | No | No | No |
hyprpaper | No | No | Yes |
wpaperd | No | Cross Fade | Yes |
✔️ swww | GIF | Yes | No (CLI) |
Wayland status bars (all in nixpkgs):
- eww: ElKowars wacky widgets (extreme, complicated customizability with its own language)
- ags: Scaffolding CLI for Astal+TypeScript (similar to eww but with TypeScript)
- Yambar: Modular status panel for X11 and Wayland (similar to Waybar but not as popular and not as many modules; does not support Hyprland by default)
- xmobar: A minimalist status bar (originally designed to work with xmonad; Wayland support was an afterthought)
- ✔️ Waybar: Highly customizable Wayland bar for Sway and Wlroots based compositors.
Not included in Home Manager option documentation:
- HyprPanel: A Bar/Panel for Hyprland with extensive customizability. (only avaible through flake)
- Luastatus: universal status bar content generator
- Fabric: The next-generation framework for building desktop widgets using Python (only available through flake)
- Ironbar: Customisable Wayland gtk bar written in Rust.
- gBar: Blazingly fast status bar written with GTK
- Root Bar: Root Bar is a bar for wlroots based wayland compositors such as sway and was designed to address the lack of good bars for wayland.
- sfwbar: S* Floating Window Bar
- nwg-panel: GTK3-based panel for sway and Hyprland Wayland compositors
- ashell: A ready to go Wayland status bar for Hyprland (only available through flake)
- Quickshell: Flexible toolkit for making desktop shells with QtQuick, targeting Wayland and X11 (only available through flake)
Installing NixOS minimal (no GNOME or KDE) on an HP ZHAN 66 Pro 14 G2:
-
Download NixOS minimal ISO image.
-
Use balenaEtcher to flash the .iso to a USB.
-
Plug the USB into the laptop and turn on the laptop.
Spam esc while booting to open the HP startup menu.
Disable secure boot.
Select boot from USB in Boot Menu (F9). -
Follow manual: Networking (use following commands).
# systemctl start wpa_supplicant
# wpa_cli
> add_network
(0
should appear)
> set_network 0 ssid "CU_FS6D"
(network calledCU_FS6D
)
> set_network 0 psk "redacted"
(using passwordredacted
forCU_FS6D
)
> set_network 0 key_mgmt WPA-PSK
> enable_network 0
If something like<3>CTRL-EVENT-CONNECTED - Connection to 32:85:ab:ef:24:5c completed [id=0 id_str=]
appears, then the laptop has connection to the internet. Leavewpa_cli
using> quit
.
Note: Also use# ping www.baidu.com
to test the internet connection. Use ctrl+c to quitping
. -
Follow manual: Partitioning.
Turns out my laptop only has a single SSD drive, which means I have to install Linux and keep Windows on the same drive; I have to dual boot Windows 10 and Linux if I want to keep Windows. I could also install Linux on a USB, but that seems iffy.
I ditch this installation and boot into Windows to create a partition for Linux on the same drive as Windows.
Note: To launch the Windows 10 partitioning software, search in Windows "创建并格式换硬盘分区".
I set up partitions. Windows displays that my drive has 476.92GB total (Why is it not 512GB?).- Before:
- 260MB: EFI系统分区
- Windows (C:)
- 930MB: 恢复分区
- After:
- 260MB: EFI系统分区
- 243.82GB: Windows (C:)
- 231.93GB: 未分配
- 930MB: 恢复分区
- Before:
-
Boot into Linux and follow manual to partitioning again.
/dev/sda
is my USB;/dev/nvme0n1
is my SSD drive. Using# parted /dev/nvme0n1 print
only shows non-free partitions, which are all numbered and named. Using# parted /dev/nvme0n1 print free
shows free or 未分配 partitions:Model: INTEL SSDPEKNW512G8H (nvme) Disk /dev/nvme0n1: 512GB Sector size (logical/physical): 512GB/512GB Partition Table: gpt Disk Flags: Number Start End Size File system Name Flags 17.4kB 1049kB 1031kB Free Space 1 1049kB 274MB 273MB fat32 EFI system partition boot, esp, no_automount 2 274MB 290MB 16.8MB Microsoft reserved partition msftres, no_automount 3 290MB 262GB 262GB ntfs Basic data partition msftdata 262GB 511GB 249GB Free Space 4 511GB 512GB 975MB ntfs Basic data partition hidden, diag, no_automount 512GB 512GB 5578kB Free Space
This shows that the 未分配 partition I created is the Free Space after number 3 with apparently 249GB. From here on, I have to slightly deviate from the NixOS manual, which assumes a clean SATA (
/dev/sda
) drive; I have an NVMe drive with Windows 10 and some partitions already configured. The manual recommends:- GPT partition table:
# parted /dev/sda -- mklabel gpt
- A boot partition (EFI system partition) of 512MiB at the start of the drive:
# parted /dev/sda -- mkpart ESP fat32 1MB 512MB
and# parted /dev/sda -- set 3 esp on
- A swap (extended RAM) partition of 8GB at the end of the drive:
# parted /dev/sda -- mkpart swap linux-swap -8GB 100%
- A root partition as large as possible in between:
# parted /dev/sda -- mkpart root ext4 512MB -8GB
Since
/dev/nvme0n1
already has partition table: gpt, I can skip step 1.
Since I know I'm using UEFI, and UEFI has only 1 EFI system partition, and Windows already created that partition with an esp flag, I can completely skip step 2.
I use# parted /dev/nvme0n1 -- mkpart root ext4 262GB -10GB
for creating the root partition.
I use# parted /dev/nvme0n1 -- mkpart swap linux-swap -10GB 510GB
for creating the swap partition.
Note: Partition 4 created by Windows (Basic data partition) is likely the Windows recovery partition, so I left 1GB of margin for error to make sure it doesn't get messed up; I use510GB
instead of511GB
for the swap partition.
After partitioning,# parted /dev/nvme0n1 print free
shows (header incomplete):Number Start End Size File system Name Flags 17.4kB 1049kB 1031kB Free Space 1 1049kB 274MB 273MB fat32 EFI system partition boot, esp, no_automount 2 274MB 290MB 16.8MB Microsoft reserved partition msftres, no_automount 3 290MB 262GB 262GB ntfs Basic data partition msftdata 5 262GB 502GB 240GB root 6 502GB 510GB 7889MB swap swap 510GB 511GB 1129MB Free Space 4 511GB 512GB 975MB ntfs Basic data partition hidden, diag, no_automount 512GB 512GB 5578kB Free Space
- GPT partition table:
-
Follow manual: Formatting.
I use# mkfs.ext4 -L nixos /dev/nvme0n1p5
to my format my root partition (number 5).
I use# mkswap -L swap /dev/nvme0n1p6
to format my swap partition (number 6).
Note: I still use-L
to label the partitions even though they already have names because filesystem labels are different from partition names. Filesystem labels are used to mount partitions in the next step.
Note: Boot partition (EFI system partition; number 1) is already formatted.
After formatting,# parted /dev/nvme0n1 print free
shows (incomplete):Number Start End Size File system Name Flags 5 262GB 502GB 240GB ext4 root 6 502GB 510GB 7889MB linux-swap(v1) swap swap
-
Follow manual: Mounting.
Note: Saying "mount A to B" means "make the contents of A accessible at location B".
I use# mount /dev/disk/by-label/nixos /mnt
to mount my root partition to/mnt
, which exists by default in the root filesystem of my live environment, which is a complete but temporary OS running in RAM using read-only storage in the USB. Use# ls /
(/
is the root filesystem) to seemnt
:bin dev etc home iso mnt nix proc root run srv sys tmp usr var
. Here, themount
command creates a "bridge" between the partition on the disk and the live environment. After installation, the live environment "dies", meaning the temporary OS along with its files won't be accessible anymore. Also, the command uses the filesystem label; for me, it is equivalent to# mount /dev/nvme0n1p5 /mnt
.
I use# mkdir -p /mnt/boot
then# mount -o umask=077 /dev/nvme0n1p1 /mnt/boot
to mount Windows' EFI system partition to/mnt/boot
.-o umask=077
specifies an option that sets the permission for the newly created directory; 077 means that the owner has full permissions (read, write, execute), and no permissions for everyone else (this only affects Linux, not Windows). I could maybe use# mount -o umask=077 /dev/disk/by-label/boot /mnt/boot
, but I do not know for sure if Windows' boot partition has the filesystem labelboot
.
I use# swapon /dev/disk/by-label/swap
to enable swap. Equivalent to# swapon /dev/nvme0n1p6
for me. -
Follow manual: Configure NixOS and install.
Generate the NixOS configuration file using# nixos-generate-config --root /mnt
.
Note: Using# ls /mnt/etc/nixos
now showsconfiguration.nix hardware-configuration.nix
.
Edit the NixOS configuration using# nano /mnt/etc/nixos/configuration.nix
.
I'm using UEFI, andboot.loader.systemd-boot.enable = true;
andboot.loader.efi.canTouchEfiVariables = true;
have already been automatically uncommented, so I don't have to change that.
Uncomment or edit:{ config, lib, pkgs, ... }: { imports = [ ./hardware-configuration.nix ]; boot.loader = { systemd-boot.enable = true; efi.canTouchEfiVariables = true; }; networking = { hostName = "ZHAN"; networkmanager.enable = true; }; time.timeZone = "America/New_York"; services = { libinput.enable = true; }; users = { users.tim = { isNormalUser = true; extraGroups = [ "wheel" "networkmanager" ]; }; }; system.stateVersion = "24.05"; }
Press ctrl+o, enter, and ctrl+x to save
configuration.nix
and exitnano
.
Install NixOS using# nixos-install
. Wait for a few minutes.
Set the root password as prompted.
Reboot using# reboot
.
Reboot automatically booted into Windows 10. Shutdown and turn on laptop to access HP startup menu again.
Select "UEFI - Linux Boot Manager" from Boot Menu (F9). -
Login to NixOS by typing
root
forZHAN login:
and my root password forPassword:
.
Use# passwd tim
to set the password fortim
as prompted.
Done! Unplug the USB.
Revert bootable USB to storage USB.
Using # systemctl start wpa_supplicant
and then # wpa_cli
doesn't work anymore. Could not connect to wpa_supplicant: (nil) - re-trying
. This is probably because in configuration.nix
:
# Pick only one of the below networking options.
# networking.wireless.enable = true;
networking.networkmanager.enable = true; # Easiest to use and most distros use this by default.
Anyways, since networking.networkmanager.enable = true;
was uncommented, I can use that.
- Use
$ nmcli device wifi list
to list available wifi. - Use
$ nmcli device wifi connect "CU_FS6D" password "redacted"
to connect.
Seems like it automatically connects at each boot.
Nixpkgs is the git repository containing many packages. A channel is a branch of a repository such as nixpkgs; the current nixpkgs stable channel is 24.05. Use # nix-channel --list
to see nixos https://nixos.org/channels/nixos-24.05
; my NixOS is currently following the nixpkgs stable channel. Before flakes existed, packages in NixOS had to be imperatively (opposite of declaratively) updated through using commands like # nix-channel --update
, and using commands was required for adding new channels to use and update packages outside the nixpkgs repository (such as Home Manager with commands like nix-channel --add https://github.com/branch-of-home-manager
).
Great resources for understanding flakes:
- Nix flakes explained: Using flakes to create a nix shell.
- Ultimate NixOS Guide | Flakes | Home-manager: Advantages of flakes and using flakes to configure NixOS.
- NixOS with Flakes: General guides for flakes, modules, and Home Manager.
- Intro Flake Config Setup for New NixOS Users: Structure and syntax of a flake explained.
- Ultimate Nix Flakes Guide: Comprehensive guide for flakes.
Nix is the programming language used primarily by NixOS. Flakes are simply Nix programs (flake.nix
files) that have specific agreed upon structures making them do specific things. They all have input and output parts. This flake template lists common inputs and outputs and their use cases. Briefly speaking:
- Inputs can be git repositories, local paths, or other flakes.
- Outputs can be pretty much anything; some are recognized and used by NixOS.
flake.lock
files are automatically created with flake.nix
files. flake.lock
files store information about the exact versions of the input(s) at the time the lock file was created (or updated). Therefore, the outputs of flake.nix
with flake.lock
are deterministic and reproducible since the inputs are locked.
An output for flakes used by NixOS is nixosConfigurations
. So, I can declaratively set a flake's input as the nixpkgs unstable channel and its output as OS configurations. The flake.lock
file generated with this flake specifies the version of the channel. I can use # nix flake update
to update the flake.lock
file; I no longer use # nix-channel --update
.
Enable flakes for NixOS:
- Flakes is still an experimental feature; enable it by adding in
configuration.nix
:{ config, lib, pkgs, ... }: { imports = [ ./hardware-configuration.nix ]; boot.loader = { # ... }; + nix.settings.experimental-features = [ "nix-command" "flakes" ]; networking = { # ... }; time.timeZone = "America/New_York"; services = { # ... }; users = { # ... }; + programs = { + git.enable = true; + }; system.stateVersion = "24.05"; }
- Connect to internet. Use
# nixos-rebuild switch
.
Switch system configuration to a flake:
- Use
$ cd /etc/nixos
then# nix flake init
to create or initialize a flake file in/etc/nixos
.
Note: Use$ ls
to seeconfiguration.nix flake.nix hardware-configuration.nix
. - Edit
flake.nix
:The input is the nixpkgs unstable channel, the git repository. The output is{ description = "NixOS configuration flake"; inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; }; outputs = { self, nixpkgs, ... }: { nixosConfigurations.ZHAN = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; modules = [ ./configuration.nix ]; }; }; }
nixosConfigurations
ofZHAN
.ZHAN
is my hostname; with "flakes" experimental feature enabled,# nixos-rebuild switch
by default looks for the file/etc/nixos/flake.nix
and builds thenixosConfigurations
item matching the current hostname of the OS. To specify a different flake directory and hostname, use# nixos-rebuild switch --flake /path/to/flake#hostname
.configuration.nix
is included;.
is a navigation shortcut for the current directory (on a side note,..
is the parent directory). - Connect to internet. Use
# nixos-rebuild switch
. Wait a few minutes.
Aflake.lock
file is generated in/etc/nixos
; use$ ls
to seeconfiguration.nix flake.lock flake.nix hardware-configuration.nix
.
Installing Home Manager
Files or directories that have names beginning with .
like the directory /home/tim/.config/
are called dotfiles. Dotfiles are hidden by default; use $ ls -a
to see them. Dotfiles typically store configuration settings.
Home Manager translates .nix
files to dotfiles and creates symlinks (similar to shortcuts in Windows) for the dotfiles for programs like Firefox and Hyprland to use. This allows me to declare configurations for user specific programs with .nix
files so I don't have to edit dotfiles, just like how I declare settings in configuration.nix
for the OS. Home Manager also supports rollbacks.
Note: Home Manager can be used to declare or install packages for specific users, but that's not useful for me.
Home Manager can be installed 2 different ways in NixOS:
- Standalone: Manage dotfiles independent from the OS. No root permission required. Works on other Linux distributions.
- NixOS Module: Manage dotfiles through the OS for all users. Root permission required.
Install Home Manager as a NixOS module:
- Edit
flake.nix
:Since Home Manager isn't part of the nixpkgs repository, it is installed through adding its channel in the inputs of the flake.{ description = "NixOS configuration flake"; inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + home-manager.url = "github:nix-community/home-manager"; + home-manager.inputs.nixpkgs.follows = "nixpkgs"; }; - outputs = { self, nixpkgs, ... }: { + outputs = { self, nixpkgs, home-manager, ... }: { nixosConfigurations.ZHAN = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; modules = [ ./configuration.nix + home-manager.nixosModules.home-manager + { + home-manager.useGlobalPkgs = true; + home-manager.useUserPackages = true; + home-manager.users.tim = import ./home.nix; + } ]; }; }; }
home-manager.inputs.nixpkgs.follows = "nixpkgs";
reduces the number of inputs the flake depends on; packages installed through Home Manager will still be installed from the samenixos-unstable
branch used forconfiguration.nix
.useGlobalPkgs
anduseUserPackages
explained here. - Create and edit
/etc/nixos/home.nix
(unlike non-flake setups,home.nix
must be present before the flake is built):{ config, lib, pkgs, ... }: { home = { username = "tim"; homeDirectory = "/home/tim"; stateVersion = "24.05"; }; programs.home-manager.enable = true; }
- Connect to internet. Use
# nixos-rebuild switch
.
flake.lock
is automatically updated and now contains version information about bothnixpkgs
andhome-manager
.
See available options to edithome.nix
.
Problem:
-
During boot, error messages appear (filtered to only
iwlwifi
):Messages
[ 5.962536] iwlwifi 0000:00:14.3: enabling device (0000 -> 0002) [ 5.963629] iwlwifi 0000:00:14.3: Detected crf-id 0x2816, cnv-id 0x1000100 wfpm id 0x80000000 [ 5.963635] iwlwifi 0000:00:14.3: PCI dev 9df0/0034, rev=0x312, rfid=0x105110 [ 5.980414] iwlwifi 0000:00:14.3: WRT: Overriding region id 0 [ 5.980417] iwlwifi 0000:00:14.3: WRT: Overriding region id 1 [ 5.980419] iwlwifi 0000:00:14.3: WRT: Overriding region id 2 [ 5.980420] iwlwifi 0000:00:14.3: WRT: Overriding region id 3 [ 5.980421] iwlwifi 0000:00:14.3: WRT: Overriding region id 4 [ 5.980422] iwlwifi 0000:00:14.3: WRT: Overriding region id 6 [ 5.980423] iwlwifi 0000:00:14.3: WRT: Overriding region id 8 [ 5.980424] iwlwifi 0000:00:14.3: WRT: Overriding region id 9 [ 5.980425] iwlwifi 0000:00:14.3: WRT: Overriding region id 10 [ 5.980426] iwlwifi 0000:00:14.3: WRT: Overriding region id 11 [ 5.980427] iwlwifi 0000:00:14.3: WRT: Overriding region id 15 [ 5.980428] iwlwifi 0000:00:14.3: WRT: Overriding region id 16 [ 5.980429] iwlwifi 0000:00:14.3: WRT: Overriding region id 18 [ 5.980430] iwlwifi 0000:00:14.3: WRT: Overriding region id 19 [ 5.980431] iwlwifi 0000:00:14.3: WRT: Overriding region id 20 [ 5.980432] iwlwifi 0000:00:14.3: WRT: Overriding region id 21 [ 5.980433] iwlwifi 0000:00:14.3: WRT: Overriding region id 28 [ 5.980875] iwlwifi 0000:00:14.3: loaded firmware version 46.7e3e4b69.0 9000-pu-b0-jf-b0-46.ucode op_mode iwlmvm [ 6.495945] iwlwifi 0000:00:14.3: Detected Intel(R) Wireless-AC 9560 160MHz, REV=0x312 [ 11.906805] iwlwifi 0000:00:14.3: Failed to load firmware chunk! [ 11.906930] iwlwifi 0000:00:14.3: iwlwifi transaction failed, dumping registers [ 11.906975] iwlwifi 0000:00:14.3: iwlwifi device config registers: [ 11.907150] iwlwifi 0000:00:14.3: 00000000: 9df08086 00100406 02800011 00800000 f4210004 00000000 00000000 00000000 [ 11.907205] iwlwifi 0000:00:14.3: 00000020: 00000000 00000000 00000000 00348086 00000000 000000c8 00000000 000001ff [ 11.907259] iwlwifi 0000:00:14.3: 00000040: 00928010 10000ec0 00100c10 00000000 00000000 00000000 00000000 00000000 [ 11.907336] iwlwifi 0000:00:14.3: 00000060: 00000000 00080812 00000405 00000000 00000000 00000000 00000000 00000000 [ 11.907389] iwlwifi 0000:00:14.3: 00000080: 000f0011 00002000 00003000 00000000 00000000 00000000 00000000 00000000 [ 11.907441] iwlwifi 0000:00:14.3: 000000a0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 [ 11.907494] iwlwifi 0000:00:14.3: 000000c0: 00000000 00000000 c823d001 0d000008 00814005 fee00478 00000000 00000000 [ 11.907546] iwlwifi 0000:00:14.3: 000000e0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 [ 11.907599] iwlwifi 0000:00:14.3: 00000100: 14c00000 ff000000 000000ff 00462031 00000000 00002000 00000000 00000000 [ 11.907652] iwlwifi 0000:00:14.3: 00000120: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 [ 11.907704] iwlwifi 0000:00:14.3: 00000140: 00000000 00000000 00000000 16410018 00000000 0001001e 00481e1f 00000000 [ 11.907755] iwlwifi 0000:00:14.3: iwlwifi device memory mapped registers: [ 11.907814] iwlwifi 0000:00:14.3: 00000000: 18c89002 00000040 00000000 08000000 00000000 00000000 00000000 00000000 [ 11.907868] iwlwifi 0000:00:14.3: 00000020: 00000010 0c000005 00000312 d55555d5 d55555d5 d55555d5 80008040 001f0042 [ 11.907946] iwlwifi 0000:00:14.3: Could not load the [0] uCode section [ 11.907991] iwlwifi 0000:00:14.3: Failed to start INIT ucode: -110 [ 11.908029] iwlwifi 0000:00:14.3: WRT: Collecting data: ini trigger 13 fired (delay=0ms). [ 12.158282] iwlwifi 0000:00:14.3: Not valid error log pointer 0x00000000 for Init uCode [ 12.158301] iwlwifi 0000:00:14.3: IML/ROM dump: [ 12.158308] iwlwifi 0000:00:14.3: 0x00000003 | IML/ROM error/state [ 12.158339] iwlwifi 0000:00:14.3: 0x00000001 | IML/ROM data1 [ 12.158350] iwlwifi 0000:00:14.3: Fseq Registers: [ 12.158374] iwlwifi 0000:00:14.3: 0x14163D33 | FSEQ_ERROR_CODE [ 12.158383] iwlwifi 0000:00:14.3: 0x00000000 | FSEQ_TOP_INIT_VERSION [ 12.158393] iwlwifi 0000:00:14.3: 0xA538284A | FSEQ_CNVIO_INIT_VERSION [ 12.158402] iwlwifi 0000:00:14.3: 0x0000A384 | FSEQ_OTP_VERSION [ 12.158412] iwlwifi 0000:00:14.3: 0x371909C7 | FSEQ_TOP_CONTENT_VERSION [ 12.158421] iwlwifi 0000:00:14.3: 0xB6FEED1F | FSEQ_ALIVE_TOKEN [ 12.158430] iwlwifi 0000:00:14.3: 0x6565DF70 | FSEQ_CNVI_ID [ 12.158439] iwlwifi 0000:00:14.3: 0xA4EAB9C6 | FSEQ_CNVR_ID [ 12.158448] iwlwifi 0000:00:14.3: 0x01000100 | CNVI_AUX_MISC_CHIP [ 12.158460] iwlwifi 0000:00:14.3: 0x01300202 | CNVR_AUX_MISC_CHIP [ 12.158838] iwlwifi 0000:00:14.3: 0x0000485B | CNVR_SCU_SD_REGS_SD_REG_DIG_DCDC_VTRIM [ 12.159245] iwlwifi 0000:00:14.3: 0xA5A5A5A2 | CNVR_SCU_SD_REGS_SD_REG_ACTIVE_VDIG_MIRROR [ 12.159658] iwlwifi 0000:00:14.3: 0x3BF53F5D | FSEQ_PREV_CNVIO_INIT_VERSION [ 12.160056] iwlwifi 0000:00:14.3: 0xE6DA90F4 | FSEQ_WIFI_FSEQ_VERSION [ 12.160471] iwlwifi 0000:00:14.3: 0x50154F5B | FSEQ_BT_FSEQ_VERSION [ 12.160847] iwlwifi 0000:00:14.3: 0x6543892F | FSEQ_CLASS_TP_VERSION [ 12.653870] iwlwifi 0000:00:14.3: Master Disable Timed Out, 100 usec [ 12.665455] iwlwifi 0000:00:14.3: Failed to run INIT ucode: -110 [ 12.678376] iwlwifi 0000:00:14.3: retry init count 0 [ 12.679991] iwlwifi 0000:00:14.3: Detected Intel(R) Wireless-AC 9560 160MHz, REV=0x312 [ 18.050795] iwlwifi 0000:00:14.3: Failed to load firmware chunk! [ 18.052671] iwlwifi 0000:00:14.3: Could not load the [0] uCode section [ 18.054516] iwlwifi 0000:00:14.3: Failed to start INIT ucode: -110 [ 18.056094] iwlwifi 0000:00:14.3: WRT: Collecting data: ini trigger 13 fired (delay=0ms). [ 18.305373] iwlwifi 0000:00:14.3: Not valid error log pointer 0x00000000 for Init uCode [ 18.305769] iwlwifi 0000:00:14.3: IML/ROM dump: [ 18.306161] iwlwifi 0000:00:14.3: 0x00000003 | IML/ROM error/state [ 18.306594] iwlwifi 0000:00:14.3: 0x00000001 | IML/ROM data1 [ 18.307015] iwlwifi 0000:00:14.3: Fseq Registers: [ 18.307461] iwlwifi 0000:00:14.3: 0x14163D33 | FSEQ_ERROR_CODE [ 18.307884] iwlwifi 0000:00:14.3: 0x00000000 | FSEQ_TOP_INIT_VERSION [ 18.308271] iwlwifi 0000:00:14.3: 0xA538284A | FSEQ_CNVIO_INIT_VERSION [ 18.308696] iwlwifi 0000:00:14.3: 0x0000A384 | FSEQ_OTP_VERSION [ 18.309121] iwlwifi 0000:00:14.3: 0x371909C7 | FSEQ_TOP_CONTENT_VERSION [ 18.309558] iwlwifi 0000:00:14.3: 0xB6FEED1F | FSEQ_ALIVE_TOKEN [ 18.309980] iwlwifi 0000:00:14.3: 0x6565DF70 | FSEQ_CNVI_ID [ 18.310400] iwlwifi 0000:00:14.3: 0xA4EAB9C6 | FSEQ_CNVR_ID [ 18.310821] iwlwifi 0000:00:14.3: 0x01000100 | CNVI_AUX_MISC_CHIP [ 18.311207] iwlwifi 0000:00:14.3: 0x01300202 | CNVR_AUX_MISC_CHIP [ 18.311646] iwlwifi 0000:00:14.3: 0x0000485B | CNVR_SCU_SD_REGS_SD_REG_DIG_DCDC_VTRIM [ 18.312098] iwlwifi 0000:00:14.3: 0xA5A5A5A2 | CNVR_SCU_SD_REGS_SD_REG_ACTIVE_VDIG_MIRROR [ 18.312526] iwlwifi 0000:00:14.3: 0x3BF53F5D | FSEQ_PREV_CNVIO_INIT_VERSION [ 18.312939] iwlwifi 0000:00:14.3: 0xE6DA90F4 | FSEQ_WIFI_FSEQ_VERSION [ 18.313313] iwlwifi 0000:00:14.3: 0x50154F5B | FSEQ_BT_FSEQ_VERSION [ 18.313741] iwlwifi 0000:00:14.3: 0x6543892F | FSEQ_CLASS_TP_VERSION [ 18.510910] iwlwifi 0000:00:14.3: Master Disable Timed Out, 100 usec [ 18.522493] iwlwifi 0000:00:14.3: Failed to run INIT ucode: -110 [ 18.535348] iwlwifi 0000:00:14.3: retry init count 1 [ 18.537039] iwlwifi 0000:00:14.3: Detected Intel(R) Wireless-AC 9560 160MHz, REV=0x312 [ 23.682797] iwlwifi 0000:00:14.3: Failed to load firmware chunk! [ 23.684352] iwlwifi 0000:00:14.3: Could not load the [0] uCode section [ 23.685890] iwlwifi 0000:00:14.3: Failed to start INIT ucode: -110 [ 23.688076] iwlwifi 0000:00:14.3: WRT: Collecting data: ini trigger 13 fired (delay=0ms). [ 23.937339] iwlwifi 0000:00:14.3: Not valid error log pointer 0x00000000 for Init uCode [ 23.937743] iwlwifi 0000:00:14.3: IML/ROM dump: [ 23.938118] iwlwifi 0000:00:14.3: 0x00000003 | IML/ROM error/state [ 23.938538] iwlwifi 0000:00:14.3: 0x00000001 | IML/ROM data1 [ 23.939130] iwlwifi 0000:00:14.3: Fseq Registers: [ 23.939589] iwlwifi 0000:00:14.3: 0x14163D33 | FSEQ_ERROR_CODE [ 23.939991] iwlwifi 0000:00:14.3: 0x00000000 | FSEQ_TOP_INIT_VERSION [ 23.940395] iwlwifi 0000:00:14.3: 0xA538284A | FSEQ_CNVIO_INIT_VERSION [ 23.940932] iwlwifi 0000:00:14.3: 0x0000A384 | FSEQ_OTP_VERSION [ 23.941293] iwlwifi 0000:00:14.3: 0x371909C7 | FSEQ_TOP_CONTENT_VERSION [ 23.941783] iwlwifi 0000:00:14.3: 0xB6FEED1F | FSEQ_ALIVE_TOKEN [ 23.942136] iwlwifi 0000:00:14.3: 0x6565DF70 | FSEQ_CNVI_ID [ 23.942526] iwlwifi 0000:00:14.3: 0xA4EAB9C6 | FSEQ_CNVR_ID [ 23.943049] iwlwifi 0000:00:14.3: 0x01000100 | CNVI_AUX_MISC_CHIP [ 23.943441] iwlwifi 0000:00:14.3: 0x01300202 | CNVR_AUX_MISC_CHIP [ 23.943921] iwlwifi 0000:00:14.3: 0x0000485B | CNVR_SCU_SD_REGS_SD_REG_DIG_DCDC_VTRIM [ 23.944328] iwlwifi 0000:00:14.3: 0xA5A5A5A2 | CNVR_SCU_SD_REGS_SD_REG_ACTIVE_VDIG_MIRROR [ 23.944795] iwlwifi 0000:00:14.3: 0x3BF53F5D | FSEQ_PREV_CNVIO_INIT_VERSION [ 23.945148] iwlwifi 0000:00:14.3: 0xE6DA90F4 | FSEQ_WIFI_FSEQ_VERSION [ 23.945541] iwlwifi 0000:00:14.3: 0x50154F5B | FSEQ_BT_FSEQ_VERSION [ 23.946069] iwlwifi 0000:00:14.3: 0x6543892F | FSEQ_CLASS_TP_VERSION [ 24.143873] iwlwifi 0000:00:14.3: Master Disable Timed Out, 100 usec [ 24.155544] iwlwifi 0000:00:14.3: Failed to run INIT ucode: -110 [ 24.169271] iwlwifi 0000:00:14.3: retry init count 2
-
After boot, using
$ nmcli device wifi list
shows nothing.
Fix:
- Enter HP startup menu.
- Select BIOS Setup (F10).
Go to Advanced tab.
Select Built-In Device Options.
Uncheck Wireless Network Device (WLAN). - Boot into NixOS. No iwlwifi logs appear.
- Reboot to enter HP startup menu again.
- Check Wireless Network Device (WLAN).
- Boot into NixOS again.
Wifi works again; using$ nmcli device wifi list
shows that I am connected.
Possible cause:
I did not completely shut down Windows 10 before booting into NixOS. Upon shutting down NixOS and booting into Windows 10, I see that Astrill VPN is still connected. So, Astrill VPN may have been connected while I first booted into NixOS; I disconnected Astrill VPN and shut down Windows 10, but upon booting into NixOS afterwards, the problem persisted.
In configuration.nix
, add:
{ config, lib, pkgs, ... }:
{
imports =
[
./hardware-configuration.nix
];
boot.loader = {
# ...
};
nix.settings.experimental-features = [ "nix-command" "flakes" ];
networking = {
# ...
};
time.timeZone = "America/New_York";
services = {
# ...
};
users = {
users.tim = {
# ...
};
+ defaultUserShell = pkgs.zsh;
};
programs = {
git.enable = true;
+ zsh = {
+ enable = true;
+ autosuggestions.enable = true;
+ };
};
system.stateVersion = "24.05";
}
Connect to internet. Use # nixos-rebuild switch
and reboot. Use $ echo $SHELL
to see /run/current-system/sw/bin/zsh
.
Navigate in the zsh menu to generate /home/tim/.zshrc
:
# Lines configured by zsh-newuser-install
# End of lines configured by zsh-newuser-install
# The following lines were added by compinstall
zstyle :compinstall filename '/home/tim/.zshrc'
autoload -Uz compinit
compinit
# End of lines added by compinstall
Since I don't need to further configure zsh (yet), I do not use Home Manager for zsh.
Using Hyprland
Hyprland can be installed 2 ways:
- From the branch of nixpkgs defined in the flake input.
- From the Hyprland git repository by defining a separate flake input.
Since I am following the nixos-unstable
branch of nixpkgs, the Hyprland package from there will likely be up to date with Hyprland's own git repository; I do not have to define a separate flake input.
Note: There is a distinction between installing a package, and enabling or configuring it. By default, declarations like programs.hyprland.enable = true;
in configuration.nix
and wayland.windowManager.hyprland.enable = true;
in home.nix
installs and enables Hyprland. However, if Hyprland is already installed, either through a nixpkgs branch or through Hyprland's own git repository, I can tell NixOS (programs.hyprland.package = ...
) and Home Manager (wayland.windowManager.hyprland.package = ...
) to use it. Since I am installing Hyprland from nixpkgs, I do not have to explicitly specify the package.
Install Hyprland (and kitty) from nixpkgs for all users:
- In
configuration.nix
, add:kitty is the default terminal emulator. Following wiki, only 1 environment variable is defined.{ config, lib, pkgs, ... }: { imports = [ ./hardware-configuration.nix ]; boot.loader = { # ... }; nix.settings.experimental-features = [ "nix-command" "flakes" ]; networking = { # ... }; time.timeZone = "America/New_York"; services = { # ... }; users = { # ... }; + environment = { + systemPackages = with pkgs; [ + kitty + ]; + sessionVariables.NIXOS_OZONE_WL = "1"; + }; programs = { git.enable = true; zsh = { # ... }; + hyprland.enable = true; }; system.stateVersion = "24.05"; }
XWayland
is enabled by default. - Connect to internet. Use
# nixos-rebuild switch
. - Reboot. Use
$ Hyprland
to see that Hyprland works. No crashes.
Fixing kitty and xdg-desktop-portal:
- In Hyprland, use
$ kitty
to see[0.139] [glfw error 65544]: process_desktop_settings: failed with error: [org.freedesktop.DBus.Error.UnknownMethod] No such interface "org.freedesktop.portal.Settings" on object at path /org/freedesktop/portal/desktop
. A new terminal appears, but as soon as I use ctrl+c in the original terminal, the new terminal disappears. - Using
$ systemctl --user status dbus
shows no abnormalities, but using$ systemctl --user status xdg-desktop-portal.service
shows (incomplete):systemd[1111]: Starting Portal service... .xdg-desktop-po[1240]: Failed to load RealtimeKit property: GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name org.freedesktop.RealtimeKit1 was not provided by any .service files .xdg-desktop-po[1240]: Failed to load RealtimeKit property: GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name org.freedesktop.RealtimeKit1 was not provided by any .service files .xdg-desktop-po[1240]: Failed to load RealtimeKit property: GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name org.freedesktop.RealtimeKit1 was not provided by any .service files .xdg-desktop-po[1187]: No skeleton to export systemd[1111]: Started Portal service.
- Kitty's error can be fixed by adding xdg-desktop-portal-gtk to the system. This can seemingly be done 2 ways: either with
environment.systemPackages
or withxdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
. Both ways install xdg-desktop-portal-gtk, and I choose the second option.
Note: Using$ systemctl --user status xdg-desktop-portal-hyprland.service
shows that the Hyprland version of xdg-desktop-portal is already running without any issues; I guess kitty either is not using this Hyprland version or does not work with it. Although, I do not mind installing the GTK version of xdg-desktop-portal, since it is recommended on the Hyprland wiki. - xdg-desktop-portal's RealtimeKit error can be fixed by adding
security.rtkit.enable = true;
toconfiguration.nix
.No skeleton to export
can also be fixed by adding xdg-desktop-portal-gtk.
After changing these two options, a new error appears when using$ systemctl --user status xdg-desktop-portal.service
(incomplete):This pipewire error can be fixed by addingsystemd[1143]: Starting Portal service... .xdg-desktop-po[1220]: Failed connect to PipeWire: Couldn't connect to PipeWire systemd[1143]: Started Portal service.
services.pipewire.enable = true;
toconfiguration.nix
. After doing so, no xdg-desktop-portal errors occur. - All additions to
configuration.nix
as a result of the errors:{ config, lib, pkgs, ... }: { imports = [ ./hardware-configuration.nix ]; boot.loader = { # ... }; nix.settings.experimental-features = [ "nix-command" "flakes" ]; networking = { # ... }; time.timeZone = "America/New_York"; services = { libinput.enable = true; + pipewire.enable = true; }; + security.rtkit.enable = true; + xdg.portal = { + enable = true; + extraPortals = [ pkgs.xdg-desktop-portal-gtk ]; + }; users = { # ... }; environment = { # ... }; programs = { # ... }; system.stateVersion = "24.05"; }
- Connect to internet. Use
# nixos-rebuild switch
.
Using Home Manager to configure Hyprland:
- Create and edit
/etc/nixos/hslaToRgba.nix
:Hyprland uses hexadecimal RGBA format to configure colors, which is not human readable.{ lib, builtins }: let mod = x: y: x - y * (builtins.floor (x / y)); abs = x: if x < 0 then -x else x; hslaToRgba = hsla: let h = mod hsla.h 360 / 60.0; s = hsla.s; l = hsla.l; a = hsla.a; c = (1 - abs(2 * l - 1)) * s; x = c * (1 - abs (mod h 2 - 1)); m = l - c / 2; rgb' = if h < 1 then { r = c; g = x; b = 0; } else if h < 2 then { r = x; g = c; b = 0; } else if h < 3 then { r = 0; g = c; b = x; } else if h < 4 then { r = 0; g = x; b = c; } else if h < 5 then { r = x; g = 0; b = c; } else { r = c; g = 0; b = x; }; round = x: builtins.floor (x * 255 + 0.5); r = round (rgb'.r + m); g = round (rgb'.g + m); b = round (rgb'.b + m); alpha = round a; toHex = x: let hex = lib.toHexString (lib.min 255 (lib.max 0 x)); in if builtins.stringLength hex == 1 then "0${hex}" else hex; in "${toHex r}${toHex g}${toHex b}${toHex alpha}"; in hslaToRgba
hslaToRgba.nix
converts HSLA to hexadecimal RGBA. - Edit
home.nix
:Since I am using Hyprland from{ config, lib, pkgs, ... }: +let + hslaToRgba = import ./hslaToRgba.nix { inherit lib builtins; }; + formatRgba = color: "rgba(${hslaToRgba color})"; + borderGradientDegree = 45; + borderActive1 = { h = 0; s = 0.0; l = 1.0; a = 1; }; + borderActive2 = { h = 0; s = 0.0; l = 1.0; a = 0.65; }; + borderInactive = { h = 210; s = 0.16; l = 0.5; a = 0.5; }; + shadowActive = { h = 185; s = 0.5; l = 0.6; a = 0.1; }; + shadowInactive = { h = 0; s = 0.0; l = 0.2; a = 0.1; }; +in { home = { # ... }; + wayland.windowManager.hyprland = { + enable = true; + settings = { + bind = [ + "ALT, TAB, cyclenext" + "ALT, TAB, alterzorder, top" + "SUPER, T, exec, kitty" + "SUPER, W, killactive" + "SUPER, Q, togglefloating" + "SUPER, F, fullscreenstate, 2 0" + "SUPER, K, exit" + "SUPER, tab, workspace, e+1" + "SUPER_SHIFT, tab, movetoworkspace, e+1" + "SUPER, E, movetoworkspace, emptyn" + ]; + bindm = [ + "SHIFT, mouse:272, movewindow" + "CTRL, mouse:272, resizewindow" + ]; + bezier = [ + "linear, 0.5, 0.5, 0.5, 0.5" + "snappyOut1, 0, 0.85, 0, 1" + "snappyOut2, 0, 0.6, 0.15, 1" + "expoOut, 0.16, 1, 0.3, 1" + ]; + animation = [ + "windowsIn, 1, 5, snappyOut1, popin 20%" + "windowsOut, 1, 8, snappyOut2, popin 80%" + "windowsMove, 1, 5, snappyOut1" + "fadeOut, 1, 4, expoOut" + "borderangle, 1, 40, linear, loop" + "workspaces, 1, 3, snappyOut1, slide" + ]; + general = { + border_size = 2; + gaps_in = 4; + gaps_out = 10; + "col.active_border" = "${formatRgba borderActive1} ${formatRgba borderActive2} ${toString borderGradientDegree}deg"; + "col.inactive_border" = formatRgba borderInactive; + resize_on_border = true; + }; + decoration = { + rounding = 8; + shadow = { + range = 6; + render_power = 1; + color = formatRgba shadowActive; + color_inactive = formatRgba shadowInactive; + }; + blur = { + size = 6; + passes = 3; + }; + }; + input = { + repeat_delay = 500; + sensitivity = "0.3"; + accel_profile = "flat"; + touchpad = { + disable_while_typing = false; + natural_scroll = true; + tap-and-drag = false; + }; + }; + gestures = { + workspace_swipe = true; + }; + misc = { + disable_hyprland_logo = true; + disable_splash_rendering = true; + animate_manual_resizes = true; + animate_mouse_windowdragging = true; + background_color = 000000; + middle_click_paste = false; + }; + }; + }; programs.home-manager.enable = true; }
hyprland.pkgs
, I do not need to specifywayland.windowManager.hyprland.package
for Home Manager.
Options that have syntax similar to Nix need to be wrapped in""
.
Bind and flag(s) = modifier key(s), other key(s), action, parameter(s).
Although trackpad (libinput) configuration can be done throughconfiguration.nix
, that doesn't work for me (/etc/X11/xorg.conf
isn't generated), so I use Hyprland's options instead.
On the Hyprland wiki,touch-and-drag
's default is marked asfalse
, but in reality it's default is actuallytrue
, so I explicitly set it. - Connect to internet. Use
# nixos-rebuild switch
.
An error occurs since a configuration file for Hyprland was automatically generated when installing Hyprland. Home Manager will not overwrite this existing configuration file. - Use
$ rm ~/.config/hypr/hyprland.conf
, then# nixos-rebuild switch
again.
Now, the configurations fromhome.nix
appear.
Note: Home Manager creates a symlink at~/.config/hypr/hyprland.conf
. I can remove this symlink, and when I use# nixos-rebuild switch
, Home Manager will generate the symlink according tohome.nix
again.
Using Home Manager to configure kitty:
- Edit
home.nix
:The{ config, lib, pkgs, ... }: let # ... in { home = { # ... }; wayland.windowManager.hyprland = { # ... }; + programs.kitty = { + enable = true; + settings = { + font_size = "9.5"; + cursor_shape = "beam"; + cursor_shape_unfocused = "beam"; + cursor_stop_blinking_after = 0; + scrollback_fill_enlarged_window = true; + mouse_hide_wait = -1; + show_hyperlink_targets = true; + clear_all_mouse_actions = true; + enable_audio_bell = false; + confirm_os_window_close = 0; + background_opacity = "0.3"; + selection_background = "#ffffff"; + clear_all_shortcuts = true; + }; + extraConfig = '' + mouse_map left press ungrabbed mouse_selection normal + mouse_map left doublepress ungrabbed mouse_selection word + mouse_map left triplepress ungrabbed mouse_selection line + map ctrl+c copy_or_interrupt + map ctrl+x copy_and_clear_or_interrupt + map ctrl+v paste_from_clipboard + map ctrl+equal change_font_size all +1.0 + map ctrl+minus change_font_size all -1.0 + ''; + }; programs.home-manager.enable = true; }
programs.kitty.shellIntegration.enableZshIntegration
Home Manager option is not set because it does not actually achieve shell integration. Although kitty uses"yes"
and"no"
, Home Manager convertstrue
andfalse
to the strings.''
defines multi-line strings in nix. - Connect to internet. Use
# nixos-rebuild switch
.
In nixpkgs, *-bin
means precompiled binary; *-unwrapped
means not wrapped by NixOS. Installing firefox-bin
instead of the normal non-precompiled version does not seem to make a difference during configuration with Home Manager or configuration.nix
.
- To install
firefox-bin
for all users, editconfiguration.nix
:Policies (view in Firefox internal page with URL{ config, lib, pkgs, ... }: { imports = [ ./hardware-configuration.nix ]; boot.loader = { # ... }; nix.settings.experimental-features = [ "nix-command" "flakes" ]; networking = { # ... }; time.timeZone = "America/New_York"; services = { # ... }; security.rtkit.enable = true; xdg.portal = { # ... }; users = { # ... }; environment = { # ... }; programs = { git.enable = true; zsh = { # ... }; hyprland.enable = true; + firefox = { + enable = true; + package = pkgs.firefox-bin; + policies = { + DisablePocket = true; + ExtensionSettings = ; + FirefoxHome = { + Search = false; + TopSites = false; + SponsoredTopSites = false; + Highlights = false; + Pocket = false; + SponsoredPocket = false; + }; + Homepage = { + URL = "https://redacted.myschoolapp.com/app/student"; + StartPage = "previous-session"; + }; + OverrideFirstRidePage = ""; + Permissions = ; + Preferences = { + "browser.tabs.tabmanager.enabled" = { + Value = false; + Status = "user"; + }; + "browser.tabs.inTitlebar" = { + Value = 0; + Status = "user"; + }; + "browser.uidensity" = { + Value = 1; + Status = "user"; + }; + "browser.urlbar.shortcuts.tabs" = { + Value = false; + Status = "user"; + }; + "browser.urlbar.suggest.engines" = { + Value = false; + Status = "user"; + }; + "browser.urlbar.suggest.topsites" = { + Value = false; + Status = "user"; + }; + "browser.urlbar.suggest.calculator" = { + Value = true; + Status = "user"; + }; + "browser.urlbar.unitConversion.enabled" = { + Value = true; + Status = "user"; + }; + "browser.vpn_promo.enabled" = { + Value = false; + Status = "user"; + }; + }; + }; + }; }; system.stateVersion = "24.05"; }
about:policies
; stored in file(s) in/nix/store/
) are usually declared to allow administrators to set and lock browser settings.programs.firefox.policies
is declared inconfiguration.nix
because the Home Manager optionprograms.firefox.policies
does not work. Other profile specific Home Manager options inprograms.firefox.profiles
work.
Note: The Firefox policyNoDefaultBookmarks
seems good, but actually breaks Home Manager'sprograms.firefox.profiles.<name>.bookmarks
option. When any option underprograms.firefox.profiles
(likeprograms.firefox.profiles.<name>.bookmarks
) fails, all other options underprograms.firefox.profiles
fail; no error messages are displayed, but the configurations have no effect. Whenprograms.firefox.profiles.<name>.bookmarks
works, it silently overrides the default Firefox bookmarks.
programs.firefox.preferences
declare configuration options mostly viewable in Firefox internal pageabout:config
; in testing, this option seems to be equivalent toprograms.firefox.policies = { Preferences = {} }
, since thePreferences
policy can be seen inabout:policies
. Home Manager's optionprograms.firefox.profiles.<name>.settings
also modify options viewable inabout:config
, but the modifications are user specific; the modifications are stored in~/.mozilla/firefox/<name>/user.js
, which defines overrides to~/.mozilla/firefox/<name>/prefs.js
(Firefox modifiesprefs.js
when options are changed directly throughabout:config
). So, to modifyabout:config
for all users, using a policy is the only option, and to modifyabout:config
for a specific user, using Home Manager's optionprograms.firefox.profiles.<name>.settings
is the only option (there is no option for modifyingprefs.js
directly, but modifyinguser.js
achieves the same result). Also, Home Manager's optionprograms.firefox.profiles.<name>.extraConfig
modifiesuser.js
as well, as seen in Home Manager'smkFirefoxModule.nix
.
Note: Nearly all Firefox configuration options hidden or shown inabout:config
can be found infirefox.js
,all.js
,StaticPrefList.yaml
, and MozillaZine.
Note: Firefox View (about:firefoxview
) cannot be disabled with any configuration options, and can only be hidden. When openingabout:firefoxview
, the tab manager button appears, even though thebrowser.tabs.tabmanager.enabled
value is already set tofalse
. - Connect to internet. Use
# nixos-rebuild switch
.
Use$ firefox
to see that Firefox works.
In the terminal, minor error messages appear:Although Hyprland has Hyprcursor which is superior to XCursor, some applications like Firefox don't support Hyprcursor and will fall back to XCursor. I don't have any Hyprcursor themes installed, so Hyprland is also falling back to XCursor. I don't have any custom XCursor themes installed. To customize the cursor in XCursor, edit[Parent 4325, Main Thread] WARNING: ../gdk/wayland/gdkcursor-wayland.c:243 cursor image size (9x16) not an integermultiple of scale (2): 'glib warning', file /builds/worker/checkouts/gecko/toolkit/xre/nsSigHandlers.cpp:187 (firefox:4325): Gdk-WARNING **: 05:23:33.059: ../gdk/wayland/gdkcursor-wayland.c:243 cursor image size (9x16) not an integermultiple of scale (2) Gdk-Message: 05:23:36.908: Unable to load pointer from the cursor theme Gdk-Message: 05:27:02.544: Unable to load col-resize from the cursor theme
configuration.nix
:And edit{ config, lib, pkgs, ... }: { imports = [ ./hardware-configuration.nix ]; boot.loader = { # ... }; nix.settings.experimental-features = [ "nix-command" "flakes" ]; networking = { # ... }; time.timeZone = "America/New_York"; services = { # ... }; security.rtkit.enable = true; xdg.portal = { # ... }; users = { # ... }; environment = { systemPackages = with pkgs; [ kitty + capitaine-cursors ]; sessionVariables.NIXOS_OZONE_WL = "1"; }; programs = { # ... }; system.stateVersion = "24.05"; }
home.nix
:{ config, lib, pkgs, ... }: let # ... in { home = { username = "tim"; homeDirectory = "/home/tim"; stateVersion = "24.05"; + pointerCursor = { + package = pkgs.capitaine-cursors; + name = "capitaine-cursors"; + size = 22; + gtk.enable = true; + x11.enable = true; + x11.defaultCursor = "default"; + }; }; + gtk = { + enable = true; + }; wayland.windowManager.hyprland = { # ... }; programs.kitty = { # ... }; programs.home-manager.enable = true; }
home.pointerCursor
sets up many cursor configurations; it sets upXCURSOR
environment variables which configure the cursor on Hyprland without Hyprcursor. Configuring environment variables need a reboot to apply.
home.pointerCursor.package
must be declared because it doesn't have a default.
For programs like Firefox that use GDK (backbone of GTK, the GUI toolkit), cursor configurations must be configured through GTK. GTK configuration can be done through graphical apps likenwg-look
, but there are Home Manager options for GTK. GTK cursor configurations (home.pointerCursor.gtk.enable = true;
) only apply whengtk.enable = true;
.
Althoughpkgs.capitaine-cursors
includes light and dark versions, the dark version seems to be the default, so I don't configure that manually.
After connecting to internet and using# nixos-rebuild switch
, running Firefox shows no error messages. - To use Home Manager to configure Firefox, edit
home.nix
:The default for{ config, lib, pkgs, ... }: let # ... in { home = { # ... }; gtk = { # ... }; wayland.windowManager.hyprland = { # ... }; programs.kitty = { # ... }; + programs.firefox = { + enable = true; + package = pkgs.firefox-bin; + profiles.tim1 = { + name = "School"; + id = 0; + bookmarks = [ + { + toolbar = true; + bookmarks = [ + { + name = "Gmail"; + url = "https://mail.google.com"; + keyword = "m"; + } + { + name = "Drive"; + url = "https://drive.google.com/drive/u/0/my-drive"; + keyword = "d"; + } + { + name = "Claude"; + url = "https://claude.ai/chats"; + keyword = "c"; + } + ]; + } + ]; + extensions = ; + settings = { + "middlemouse.paste" = false; + "findbar.highlightAll" = true; + }; + extraConfig = '' + ''; + search.engines = { + "Bing CN" = { + urls = [{ template = "https://cn.bing.com/search?q={searchTerms}&ensearch=1"; }]; + definedAliases = [ "@b" ]; + iconURL = "https://img.icons8.com/fluency/48/bing--v4.png"; + }; + "Bing".metaData.hidden = true; + "DuckDuckGo".metaData.hidden = true; + "Wikipedia (en)".metaData.hidden = true; + }; + userChrome = '' + ''; + userContent = '' + ''; + }; + profiles.test = { + id = 1; + }; + }; programs.home-manager.enable = true; }
programs.firefox.package
ispkgs.firefox
, notpkgs.firefox-bin
, so if the option is not set, Home Manager will try to installpkgs.firefox
instead of usingpkgs.firefox-bin
that's already installed through configuration inconfiguration.nix
.
Note: When I first used# nixos-rebuild switch
, a download of a Firefox package began, even though I specifiedprograms.firefox.package = pkgs.firefox-bin
, matching the package inconfiguration.nix
. I updated/etc/nixos/flake.lock
, used# nixos-rebuild switch
without any Firefox configurations inhome.nix
, and then used# nixos-rebuild switch
with Firefox configurations includingprograms.firefox.package = pkgs.firefox-bin
inhome.nix
; during this rebuild no Firefox package was downloaded. Usingnix-store -q --references /run/current-system/sw | grep firefox
shows only one Firefox. A possible explanation could be that Home Manager queries a different version of the unstable branch of nixpkgs than the OS; Home Manager follows the same branch as the OS, as defined inflake.nix
home-manager.inputs.nixpkgs.follows = "nixpkgs";
, but a different version of the branch. So, during rebuild, Home Manager sees that in its version of the nixos-unstable branch of nixpkgs there ispkgs.firefox-bin
of a different version than thepkgs.firefox-bin
already installed in the system, so Home Manager tries to install the newerpkgs.firefox-bin
from the version of the nixos-unstable branch of nixpkgs that it follows. So, when I update the version of the nixos-unstable branch of nixpkgs that the OS follows by updating/etc/nixos/flake.lock
to possibly match the version that Home Manager is following, Home Manager does not install another Firefox anymore. One reason to suspect this is that before/etc/nixos/flake.lock
was updated, Firefox version 127.x.x was installed, and after updating, it changed to version 128.0.3.
Firefox generates profiles on first launch, not instillation. This means that if I delete the profile directories and use# nixos-rebuild switch
without modifyinghome.nix
, reopening Firefox will generate the default profile instead of profiles defined inprograms.firefox.profiles
.
programs.firefox.profiles.<name>.id
must be declared when multiple profiles are declared.
The syntax insideprograms.firefox.profiles.<name>.bookmarks
does not allow;
's after{}
's. Thetoolbar
option defines the sub-bookmarks within the bookmark (functioning as directory) as toolbar bookmarks. This is the pseudo-structure:profileBookmarks = { menuBookmark1, menuBookmark2, toolbarBookmarks = { toolbarBookmark1, toolbarBookmark2, ... }, menuBookmark3, ... }
. Thekeyword
option redirects typing the string in the address bar to the bookmark.
Configurations insideprograms.firefox.profiles.<name>.settings
are all configurations not available through the Preferences policy inconfiguration.nix
.
programs.firefox.profiles.<name>.search.force
does not function as described in the documentation; the default search engines (Google, Bing, DuckDuckGo, Wikipedia (en)) still appear with the option set totrue
. On seemingly every launch, Firefox regenerates the file~/.mozilla/firefox/<name>/search.json.mozlz4
, replacing Home Manager's symlink, adding the default search engines back into the file; the issue is not resolved. TheSearchEngines
policy exists for Firefox ESR, and for security reasons it will not be supported for rapid release. Default search engines are hidden with metadata attributes inhome.nix
; default engines cannot be removed completely, although uninstalling them through extension related policies could work.programs.firefox.profiles.<name>.search.privateDefault
does not work, but the default is Google.
Remove the directories~/.mozilla
and~/.cache/mozilla
. Connect to internet. Use# nixos-rebuild switch
.
Packages like light
and brightnessctl
work on Wayland and make changing screen brightness easy, but there is a simpler way to change screen brightness. The file /sys/class/backlight/intel_backlight/brightness
contains an integer that defines the screen brightness. Use $ cat /sys/class/backlight/intel_backlight/max_brightness
to see the max brightness is 24000 (a number <188 makes the backlight flicker or turn off). When the file brightness
is modified, the screen brightness changes accordingly. However, the file brightness
has permissions -rw-r--r--
(file type, permissions(owner, group, others)), so only the root user can modify it. Use $ sudo tee /sys/class/backlight/intel_backlight/brightness <<< MY_NUMBER
to modify the file manually.
Notes: Using $ sudo echo MY_NUMBER > /sys/class/backlight/intel_backlight/max_brightness
does not work because sudo
elevates the command that follows it (echo
in this case), not the redirector operator >
which is handled by the command shell (zsh for me). sudo
here does not affect the command shell's operations; >
is supposed to write the output of echo MY_NUMBER
to the file brightness
but it's operated by the command shell which doesn't have permission. Using # echo MY_NUMBER > /sys/class/backlight/intel_backlight/max_brightness
works because while using commands as root, all operations, including the command shell's operations, are performed with root privileges. Also, to use the command without root, use $ sudo sh -c 'echo MY_NUMBER > /sys/class/backlight/intel_backlight/max_brightness'
. <<<
(here string) is also a command shell operation, but in $ sudo tee /sys/class/backlight/intel_backlight/brightness <<< MY_NUMBER
tee
actually does the writing, and tee
has elevated privileges. <<<
only passes the string to tee
for tee
to modify the file brightness
.
- To allow modification of the file
brightness
withoutsudo
for all users, editconfiguration.nix
:{ config, lib, pkgs, ... }: { imports = [ ./hardware-configuration.nix ]; boot.loader = { # ... }; nix.settings.experimental-features = [ "nix-command" "flakes" ]; networking = { # ... }; time.timeZone = "America/New_York"; services = { libinput.enable = true; pipewire.enable = true; + udev.extraRules = '' + ACTION=="add", SUBSYSTEM=="backlight", KERNEL=="intel_backlight", MODE="0666", RUN+="${pkgs.coreutils}/bin/chmod a+w /sys/class/backlight/%k/brightness" + ''; }; security.rtkit.enable = true; xdg.portal = { # ... }; users = { # ... }; environment = { # ... }; programs = { # ... }; system.stateVersion = "24.05"; }
udev
is enabled by default.
After connecting to internet and using# nixos-rebuild switch
, and then rebooting,/sys/class/backlight/intel_backlight/brightness
has permissions-rw-rw-rw-
. - To bind dynamic commands to keybinds to change screen brightness in Hyprland, edit
home.nix
:{ config, lib, pkgs, ... }: let # ... in { home = { # ... }; gtk = { # ... }; wayland.windowManager.hyprland = { enable = true; settings = { bind = [ # ... ]; + binde = [ + "SUPER, MINUS, exec, val=$(< /sys/class/backlight/intel_backlight/brightness); tee /sys/class/backlight/intel_backlight/brightness <<< $((val <= 4188 ? 188 : val - 4000))" + "SUPER, EQUAL, exec, val=$(< /sys/class/backlight/intel_backlight/brightness); tee /sys/class/backlight/intel_backlight/brightness <<< $((val >= 20000 ? 24000 : val + 4000))" + ]; bindm = [ # ... ]; # ... }; }; programs.kitty = { # ... }; programs.firefox = { # ... }; programs.home-manager.enable = true; }
- Connect to internet. Use
# nixos-rebuild switch
.
Since I only have one user and one window manager or desktop environment, I do not need a graphical display manager, or any display manager at all.
- To automate typing in the username, edit
configuration.nix
:{ config, lib, pkgs, ... }: { imports = [ ./hardware-configuration.nix ]; boot.loader = { # ... }; nix.settings.experimental-features = [ "nix-command" "flakes" ]; networking = { # ... }; time.timeZone = "America/New_York"; services = { libinput.enable = true; pipewire.enable = true; udev.extraRules = '' # ... ''; + getty.extraArgs = [ "--skip-login" "--login-options" "tim" ]; }; security.rtkit.enable = true; xdg.portal = { # ... }; users = { # ... }; environment = { # ... }; programs = { # ... }; system.stateVersion = "24.05"; }
getty
(get-tty) manages TTYs.
services.getty.autologinUser
is not used because it skips the password too. - To start Hyprland automatically after login, edit
home.nix
:Note: Options similar to{ config, lib, pkgs, ... }: let # ... in { home = { # ... }; gtk = { # ... }; wayland.windowManager.hyprland = { # ... }; programs.kitty = { # ... }; programs.firefox = { # ... }; + programs.zsh = { + enable = true; + profileExtra = '' + if [ -z "''${DISPLAY}" ] && [ "''${XDG_VTNR}" -eq 1 ]; then + exec Hyprland + fi + ''; + }; programs.home-manager.enable = true; }
programs.zsh.profileExtra
exist forconfiguration.nix
, but they are system wide.
Zsh executes a few files in a specific order on startup. the.zprofile
file is executed on all login startups.
-z
checks for zero length; if Hyprland is already running,${DISPLAY}
will have length. In nix,$
s inside multi-line strings can be escaped with''
.${XDG_VTNR}
indicates TTY#;-eq
means "equal".
Remove/home/tim/.zshrc
, then connect to internet and use# nixos-rebuild switch
.
The swww wallpaper manager does not have a configuration file; all configurations are done through commands.
-
To install swww, edit
configuration.nix
:{ config, lib, pkgs, ... }: { imports = [ ./hardware-configuration.nix ]; boot.loader = { # ... }; nix.settings.experimental-features = [ "nix-command" "flakes" ]; networking = { # ... }; time.timeZone = "America/New_York"; services = { # ... }; security.rtkit.enable = true; xdg.portal = { # ... }; users = { # ... }; environment = { systemPackages = with pkgs; [ kitty capitaine-cursors + swww ]; sessionVariables.NIXOS_OZONE_WL = "1"; }; programs = { # ... }; system.stateVersion = "24.05"; }
-
Use
$ mkdir /home/tim/Wallpapers
to create a directory for the wallpapers. -
To autostart swww and automatically randomize wallpapers, edit
home.nix
:{ config, lib, pkgs, ... }: let # ... in { home = { username = "tim"; homeDirectory = "/home/tim"; stateVersion = "24.05"; pointerCursor = { # ... }; + file = { + ".swwwRandomizer" = { + enable = true; + executable = true; + text = '' + #!/usr/bin/env zsh + used=() + while :; do + all=(''$1/*) + [[ ''$#used -eq ''$#all ]] && used=(''$selected) + unused=(''${all:|used}) + selected=''${unused[''$RANDOM % ''$#unused + 1]} + random_pos=(''$(seq 0.1 .1 0.9 | shuf)) + swww img ''$selected \ + --resize crop \ + -t grow \ + --transition-pos ''$random_pos[1],''$random_pos[2] \ + --transition-duration 4 \ + --transition-fps 60 \ + -f Nearest + used+=(''$selected) + sleep ''$2 + done + ''; + }; + }; }; gtk = { # ... }; wayland.windowManager.hyprland = { enable = true; settings = { # ... misc = { # ... }; + exec-once = [ + "swww-daemon --no-cache" + "swww clear 000000 && ~/.swwwRandomizer /home/tim/Wallpapers 3600" + ]; }; }; programs.kitty = { # ... }; programs.firefox = { # ... }; programs.zsh = { # ... }; programs.home-manager.enable = true; }
Home Manager's
home.file.<name>.target
option defines the path and name of the generated symlink or file relative to~
. This option defaults to~/<name>
when undefined.
Although the zsh script can be run as a one-line command with$ zsh -c "command"
, using Hyprland'sexec-once
to execute the command on Hyprland startup does not seem to work. Also, the NixOS optionwriteShellApplication
might be worth exploring for system wide scripts.
Pseudocode for the script:- Shebang for NixOS.
- Define
used
as an empty array.
Putting spaces before and after the equal sign=
would result in a syntax error. - While true, loop:
:
stands fortrue
. Semicolons;
are mandatory for compacting the script into a single line; they are optional with newlines.- Define
all
as an array of files inside$1/*
.$
indicates a variable. The variable1
is the first argument passed to the script when it is run, like so:$ ~/.swwwRandomizer first_argument
. Using$ ~/.swwwRandomizer /home/tim/Wallpapers
simplifies to(/home/tim/Wallpapers/*)
. The wildcard*
lists all files in the directory. - Length of
used
equals length ofall
and redefineused
as an array with onlyselected
.
Double brackets[[ ]]
are used for testing conditions.#
tests for the length of the array variable.&&
, the logical AND, only runs the second command if the first returnstrue
.selected
is defined later in the script; putting it here will never cause an error unlessall
is defined as an empty array. Puttingselected
ensures that images never get picked twice in a row after all images have been used.
Note:$#var
works in zsh, but not bash. In bash, curly braces{}
are required:${#var}
. - Define
unused
as an array ofall
withoutused
.
{}
are required for zsh to group commands.:|
removes anything inside the second array from the first array.:|
needs to be inside the parameter expansion${}
. Otherwise,:|
inunused=($all:|$used)
would be interpreted as a pipe operator followed by a colon. - Define
selected
as the path of the (($RANDOM
modulo length ofunused
) + 1)th file ofunused
.
$RANDOM
is a pre-defined command shell variable that returns a random integer between 0 and 32767. The modulo operator%
returns the remainder from dividing$RANDOM
by the length ofunused
. Since zsh indexing start at one, not zero, one is added to the remainder to accurately calculate the index, which is denoted with brackets[]
. - Define
random_pos
as the array of the sequence of 0.1 to 0.9 with step 0.1 shuffled.
The set of inner parentheses$()
capture command substitution. The pipe operator|
feeds the output of the first command as input to the second command. - Execute
swww img
with the image with pathselected
.
Back slashes\
are used to separate one line commands to multiple lines. Useswww img --help
to see all image display and transition options.--resize fit
shrinks the image until the entire image is displayed;--resize crop
enlarges the image until the screen is filled.-t grow
transition animation type is a growing circle.-t any
randomizes the position of the circle, but it also randomizes betweengrow
andouter
(shrinking circle) animations, so it is not used.--transition-pos
values separated by commas are float percentage values; arbitrarily the first and second floats of the shuffledrandom_pos
array are used.-f Nearest
is the fastest filter; best for pixel art. - Append
selected
to theused
array. - Pause for variable
2
seconds.
- Define
- End of loop.
The
--no-cache
flag is declared when startingswww-daemon
because swww does not yet remember options such as filter and resize for cached images.
Using$ swww-daemon
for the first time on instillation or using$ swww-daemon --no-cache
(to clear cache, use$ swww clear-cache
) and then using$ swww img /path/to/any/image
displays a black wallpaper. Using$ swww query
shows that swww has attempted to display an image. Using any swww command to attempt to display something again fixes the black wallpaper. So,swww clear 000000
is executed once in the start to arbitrarily display black. Puttingswww clear 000000
right after the shebang inside the script yields inconsistent results, indicating that the command is run too quickly, maybe before swww daemon has completely started, so&&
is necessary inexec-once
.
Connect to internet. Use# nixos-rebuild switch
.
Oh My Posh is used for making shells look better.
- To install Oh My Posh, edit
configuration.nix
:{ config, lib, pkgs, ... }: { imports = [ ./hardware-configuration.nix ]; boot.loader = { # ... }; nix.settings.experimental-features = [ "nix-command" "flakes" ]; networking = { # ... }; time.timeZone = "America/New_York"; services = { # ... }; security.rtkit.enable = true; xdg.portal = { # ... }; users = { # ... }; environment = { systemPackages = with pkgs; [ kitty capitaine-cursors swww + oh-my-posh ]; sessionVariables.NIXOS_OZONE_WL = "1"; }; programs = { # ... }; system.stateVersion = "24.05"; }
- Connect to internet. Use
# nixos-rebuild switch
. - To use Home Manager to configure Oh My Posh, edit
home.nix
:Note: While Oh My Posh's documentation suggests to edit{ config, lib, pkgs, ... }: let # ... in { home = { # ... }; gtk = { # ... }; wayland.windowManager.hyprland = { # ... }; programs.kitty = { # ... }; programs.firefox = { # ... }; programs.zsh = { # ... }; + programs.oh-my-posh = { + enable = true; + settings = { + "$schema" = "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json"; + final_space = true; + blocks = [ + { + type = "prompt"; + alignment = "left"; + segments = [ + { + type = "session"; + style = "plain"; + foreground = "white"; + template = "{{ .UserName }}"; + } + { + type = "path"; + style = "plain"; + foreground = "white"; + properties = { + style = "full"; + }; + } + { + type = "text"; + style = "plain"; + foreground = "white"; + template = "❱"; + } + ]; + } + { + type = "rprompt"; + alignment = "right"; + overflow = "break"; + segments = [ + { + type = "executiontime"; + style = "plain"; + foreground = "white"; + } + ]; + } + ]; + }; + }; programs.home-manager.enable = true; }
.zshrc
, Home Manager automatically does that.❱
is\u2771
; use$ echo "\u2771"
to see the symbol. - Connect to internet. Use
# nixos-rebuild switch
.
For Linux systems, PipeWire is used for managing audio. PipeWire is more modern compared to PulseAudio and JACK. While services.pipewire.enable = true;
is already in my configuration.nix
, it is recommended to add some extra options.
BlueZ is the official standard bluetooth package.
- Edit
configuration.nix
:WirePlumber is PipeWire's session manager, a daemon that manages PipeWire.{ config, lib, pkgs, ... }: { imports = [ ./hardware-configuration.nix ]; boot.loader = { # ... }; nix.settings.experimental-features = [ "nix-command" "flakes" ]; networking = { # ... }; time.timeZone = "America/New_York"; services = { libinput.enable = true; - pipewire.enable = true; + pipewire = { + enable = true; + wireplumber.enable = true; + pulse.enable = true; + alsa.enable = true; + alsa.support32Bit = true; + }; udev.extraRules = '' # ... ''; # ... }; + hardware = { + bluetooth = { + enable = true; + powerOnBoot = true; + }; + }; security.rtkit.enable = true; xdg.portal = { # ... }; users = { # ... }; environment = { # ... }; programs = { # ... }; system.stateVersion = "24.05"; }
services.pipewire.pulse.enable = true;
allows PulseAudio applications to work with PipeWire. Likewise, ALSA configurations allow ALSA compatibility.
hardware.bluetooth
configures BlueZ. To use bluetooth, use$ bluetoothctl
; use[bluetooth]# scan on
,[bluetooth]# pair F8:4E:17:D3:E7:4A
, and[bluetooth]# connect F8:4E:17:D3:E7:4A
to connect toF8:4E:17:D3:E7:4A
. Use[bluetooth]# trust F8:4E:17:D3:E7:4A
to automatically connect. Using[bluetooth]# quit
will not terminate the connection. Use$ bluetoothctl devices [Paired/Bonded/Trusted/Connected]
to see paired, bonded, trusted, or connected devices. - Connect to internet. Use
# nixos-rebuild switch
. - To bind the buttons XF86AudioMute, XF86AudioLowerVolume, and XF86AudioRaiseVolume to WirePlumber commands to manage volume through Hyprland, edit
home.nix
:Note:{ config, lib, pkgs, ... }: let # ... in { home = { # ... }; gtk = { # ... }; wayland.windowManager.hyprland = { enable = true; settings = { bind = [ # ... ]; binde = [ "SUPER, MINUS, exec, val=$(< /sys/class/backlight/intel_backlight/brightness); tee /sys/class/backlight/intel_backlight/brightness <<< $((val <= 4188 ? 188 : val - 4000))" "SUPER, EQUAL, exec, val=$(< /sys/class/backlight/intel_backlight/brightness); tee /sys/class/backlight/intel_backlight/brightness <<< $((val >= 20000 ? 24000 : val + 4000))" + ", XF86AudioMute, exec, wpctl set-mute @DEFAULT_SINK@ toggle" + ", XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_SINK@ 2%-" + ", XF86AudioRaiseVolume, exec, wpctl get-volume @DEFAULT_SINK@ | awk '{if ($2 < 2.20) system(\"wpctl set-volume @DEFAULT_SINK 2%+\")}'" ]; bindm = [ # ... ]; # ... }; }; programs.kitty = { # ... }; programs.firefox = { # ... }; programs.zsh = { # ... }; programs.oh-my-posh = { # ... }; programs.home-manager.enable = true; }
wpctl get-volume @DEFAULT_SINK@ | awk '{if ($2 < 2.20) system(\"wpctl set-volume @DEFAULT_SINK 2%+\")}'
or$ wpctl get-volume @DEFAULT_SINK@ | awk '{if ($2 < 2.20) system("wpctl set-volume @DEFAULT_SINK@ 2%+")}'
raises the volume by 0.02 if the volume is lower than 2.20. Through testing, it seems that while values can go above 2.20 to infinity, values above 2.20 do not actually make the speakers louder. - Connect to internet. Use
# nixos-rebuild switch
.
- Edit
configuration.nix
:{ config, lib, pkgs, ... }: { imports = [ ./hardware-configuration.nix ]; boot.loader = { # ... }; nix.settings.experimental-features = [ "nix-command" "flakes" ]; networking = { # ... }; time.timeZone = "America/New_York"; services = { # ... }; security.rtkit.enable = true; xdg.portal = { # ... }; users = { # ... }; environment = { # ... }; + fonts = { + enableDefaultPackages = false; + packages = with pkgs; [ + nerd-fonts.go-mono + nerd-fonts.roboto-mono + nerd-fonts.lilex + nerd-fonts.dejavu-sans-mono + noto-fonts + twemoji-color-font + ]; + fontconfig.defaultFonts = { + serif = [ "Noto Serif" ]; + sansSerif = [ "Noto Sans" ]; + monospace = [ "DejaVuSansM Nerd Font Mono" ]; + emoji = [ "Twitter Color Emoji" ]; + }; + }; programs = { # ... }; system.stateVersion = "24.05"; }
fonts.enableDefaultPackages
installs some fonts like DejaVu; DejaVu was the font used by kitty before this configuration was set tofalse
(use$ kitty +list-fonts
to see the fonts available to kitty). If this configuration was set tofalse
and no other fonts are infonts.packages
, then kitty's font rendering breaks.
Names infonts.fontconfig.defaultFonts
are found by finding the TrueType file and using$ fc-query font.ttf | grep '^\s\+family:' | cut -d'"' -f2
. To find the location of the TrueType file, use# find / -iname "*font*"
.
Note: Many symbols in Nerd Fonts have\Uxxxxx
unicodes like\Uf00af
. Using$ echo "\uf00af"
does not work since there are more than 4 characters inf00af
. To see it in the terminal, either use$ echo "\Uf00af"
(with uppercaseU
) or convertf00af
. This is a python script that converts Nerd Font unicodes:Fortry: hex_input = input("Enter code from Nerd Fonts (like 'f00af'): ").strip().lower() try: hex_input = int(hex_input, 16) char = chr(hex_input) except ValueError as e: raise ValueError(f"Invalid code point: {hex_input}") from e utf8_bytes = char.encode('utf-8') print(''.join([f'\\x{byte:02x}' for byte in utf8_bytes])) except ValueError as e: print(f"Error: {e}")
f00af
, the script should output\xf3\xb0\x82\xaf
. Use$ echo "\xf3\xb0\x82\xaf"
and the symbol should render. - Connect to internet. Use
# nixos-rebuild switch
.
Using Waybar (WIP)
- To install Waybar, edit
configuration.nix
:{ config, lib, pkgs, ... }: { imports = [ ./hardware-configuration.nix ]; boot.loader = { # ... }; nix.settings.experimental-features = [ "nix-command" "flakes" ]; networking = { # ... }; time.timeZone = "America/New_York"; services = { # ... }; security.rtkit.enable = true; xdg.portal = { # ... }; users = { # ... }; environment = { # ... }; fonts = { # ... }; programs = { # ... firefox = { # ... }; + waybar.enable = true; }; system.stateVersion = "24.05"; }
- Connect to internet. Use
# nixos-rebuild switch
. - To use Home Manager to configure Waybar, edit
home.nix
:Note:{ config, lib, pkgs, ... }: let # ... in { home = { # ... }; gtk = { # ... }; wayland.windowManager.hyprland = { # ... }; programs.kitty = { # ... }; programs.firefox = { # ... }; programs.zsh = { # ... }; programs.oh-my-posh = { # ... }; + programs.waybar = { + enable = true; + settings.bar = { + layer = "top"; + position = "top"; + modules-left = [ "" ]; + modules-right = [ "" ]; + spacing = 0; + }; + style = '' + + ''; + }; programs.home-manager.enable = true; }
bar
inprograms.waybar.settings.bar
is an arbitrary name for the bar; Waybar supports having multiple bars at the same time, but I only need one bar. Waybar automatically starts on startup since it is inside$ systemctl --user list-units
, so there needs to be neither Hyprland nor zsh configuration for autostarting Waybar. Automatically starting through systemctl though means that it does not have proper$PATH
, meaning that it must use the full path ofbluetoothctl
(/run/current-system/sw/bin/bluetoothctl
) to findbluetoothctl
.
\Uf057e \Uf0e08 is the muted icon. \Uf091f, \Uf0922,5,8, \Uf029e no wifi \Uf00af is the bluetooth icon, \Uf00b2 disabled, \Uf007a-f, \Uf0080-2, \Uf0079 are battery icons - Connect to internet. Use
# nixos-rebuild switch
.
Using Python Environment Python and Python packages can be installed system wide, but using nix shells is recommended. Nix shells can:
- Create isolated environments. Packages installed through the shell cannot be accessed outside the shell and are deleted when
# nix-collect-garbage -d
is used. Nix shells only effect packages and environment variables. - Create reproducible environments. Shells can be shared to create identical environments on different NixOS machines.
Nix shells can be started with commands ($ nix shell
in flake systems) or more declaratively with shell.nix
files for more configuration options.
Note: Nix shells are different from command shells (zsh, bash, etc...); they are all called shells because they function as wrappers.
Flakes can be used with shell.nix
to define the input nixpkgs channel.
All things in NixOS are packages. The system is a package that depends on whatever packages you install (like Firefox). Packages are built with stdenv.mkDerivation. mkShell is just a wrapper of stdenv.mkDerivation.
# nix-collect-garbage -d
deletes generations and store objects.
$ nix-collect-garbage -d
deletes home manager generations? https://discourse.nixos.org/t/home-manager-and-garbage-collection/41715
Finish Firefox config: stuff in about:preferences(included in about:config?) about:addons about:logins about:policies(done?) about:config, every rebuild home manager fails and have to remove .mozilla; fixable with https://discourse.nixos.org/t/way-to-automatically-override-home-manager-collisions/33038/6
Firefox css: https://www.reddit.com/r/FirefoxCSS/top/?t=all https://firefoxcss-store.github.io/index.html https://support.mozilla.org/en-US/kb/customize-your-new-tab-page#firefox:linux:fx129 https://support.mozilla.org/en-US/kb/customize-firefox-controls-buttons-and-toolbars#firefox:linux:fx129
Minimizing windows in Hyprland or just using workspaces? Minimizing: hyprwm/Hyprland#995 https://github.com/DreamMaoMao/hych/tree/main hyprwm/Hyprland#8281 https://wiki.hyprland.org/Configuring/Uncommon-tips--tricks/#minimize-windows-using-special-workspaces
Finish hyprland animation customization (layers, etc...)\
finish waybar config: TOOLTIPS CAN BE STYLED \
Properly manage colors:
Pywal alternative
https://sw.kovidgoyal.net/kitty/conf/#the-color-table
https://github.com/Misterio77/flavours
https://github.com/warpwm/lule + https://github.com/Misterio77/nix-colors?
https://github.com/danth/stylix is a bit magical, it might interfere with transparency settings and it sets the wallpaper, font, and cursor too? \
Home manage git
Zsh frameworks? oh my zsh, prezto, zinit, antigen,
Zsh plugins (plugin managers as well?)
Packages for terminal: fonts, improved ls find grep cat man etc...,
git integration?
terminal file manager (any file manager)?
system monitoring?
Microphone Control:
Keyboard Language Control: English, Chinese, Spanish. Remember to add bar indicator https://github.com/Alexays/Waybar/wiki/Module:-Hyprland#language Chinese needs an IME, https://discourse.nixos.org/t/how-to-setup-an-input-method-for-cjk-users/9533/3 https://discourse.nixos.org/t/pinyin-input-method-in-hyprland-wayland-for-simplified-chinese/49186/2 https://nixos.wiki/wiki/Fcitx5
Camera Control:
Clipboard Manager:
Screenshot Utility:
Text / Code Editor: Micro, neovim, helix, vscodium
Calculator:
Media Player:
Image Viewer:
WeChat
Stremio
Mullvad
Screen Locker:
Notification Daemon:
Application Launcher:
Authentication Agent: Starting method: manual (exec-once) Authentication agents are the things that pop up a window asking you for a password whenever an app wants to elevate its privileges.
https://gitlab.com/christosangel/ascii-matrix
Find wallpapers
Customize Grub