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(0should appear)
> set_network 0 ssid "CU_FS6D"(network calledCU_FS6D)
> set_network 0 psk "redacted"(using passwordredactedforCU_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_cliusing> quit.
Note: Also use# ping www.baidu.comto 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/sdais my USB;/dev/nvme0n1is my SSD drive. Using# parted /dev/nvme0n1 printonly shows non-free partitions, which are all numbered and named. Using# parted /dev/nvme0n1 print freeshows 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 SpaceThis 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 512MBand# 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/nvme0n1already 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 -10GBfor creating the root partition.
I use# parted /dev/nvme0n1 -- mkpart swap linux-swap -10GB 510GBfor 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 use510GBinstead of511GBfor the swap partition.
After partitioning,# parted /dev/nvme0n1 print freeshows (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/nvme0n1p5to my format my root partition (number 5).
I use# mkswap -L swap /dev/nvme0n1p6to format my swap partition (number 6).
Note: I still use-Lto 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 freeshows (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 /mntto 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, themountcommand 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/bootthen# mount -o umask=077 /dev/nvme0n1p1 /mnt/bootto mount Windows' EFI system partition to/mnt/boot.-o umask=077specifies 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/swapto enable swap. Equivalent to# swapon /dev/nvme0n1p6for me. -
Follow manual: Configure NixOS and install.
Generate the NixOS configuration file using# nixos-generate-config --root /mnt.
Note: Using# ls /mnt/etc/nixosnow 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:{ 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.nixand 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
rootforZHAN login:and my root password forPassword:.
Use# passwd timto set the password fortimas 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 listto 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:{ pkgs, ... }: { # ... + nix.settings.experimental-features = [ "nix-command" "flakes" ]; + programs = { + git.enable = true; + }; # ... } - Connect to internet. Use
# nixos-rebuild switch.
Switch system configuration to a flake:
- Use
$ cd /etc/nixosthen# nix flake initto create or initialize a flake file in/etc/nixos.
Note: Use$ lsto 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 = { nixpkgs, ... }: { nixosConfigurations.ZHAN = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; modules = [ ./configuration.nix ]; }; }; }
nixosConfigurationsofZHAN.ZHANis my hostname; with the flakes experimental feature enabled,# nixos-rebuild switchby default looks for the file/etc/nixos/flake.nixand builds thenixosConfigurationsitem 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.nixis 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.lockfile is generated in/etc/nixos; use$ lsto 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 = { nixpkgs, ... }: { + outputs = { 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-unstablebranch used forconfiguration.nix.useGlobalPkgsanduseUserPackagesexplained here. Since Home Manager is insidemodulesof ``nixosSystem, Home Manager will be rebuilt whenever the system is rebuilt, which is an effect of installing Home Manager as a NixOS module.\ Note: To install Home Manager standalone with flakes,homeConfigurations.ZHAN = home-manager.lib.homeManagerConfiguration { # ... }` would be used inside `flake.nix` right beside `nixosConfigurations.ZHAN = nixpkgs.lib.nixosSystem { # ... }`. - Create and edit
/etc/nixos/home.nix(unlike non-flake setups,home.nixmust be present before the flake is built):Note:{ pkgs, ... }: { home = { username = "tim"; homeDirectory = "/home/tim"; stateVersion = "24.05"; }; programs.home-manager.enable = true; }
home.nixis in the same directory asflake.nixbecauseimport ./home.nixis specified in the flake. - Connect to internet. Use
# nixos-rebuild switch.
flake.lockis automatically updated and now contains version information about bothnixpkgsandhome-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 listshows 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 listshows 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:
{ pkgs, ... }:
{
# ...
users = {
# ...
+ defaultUserShell = pkgs.zsh;
};
programs = {
# ...
+ zsh = {
+ enable = true;
+ autosuggestions.enable = true;
+ };
};
# ...
}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 compinstallSince 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.{ pkgs, ... }: { # ... + environment = { + systemPackages = with pkgs; [ + kitty + ]; + sessionVariables.NIXOS_OZONE_WL = "1"; + }; programs = { # ... + hyprland.enable = true; }; # ... }XWaylandis enabled by default.
Note: Notice the{ pkgs, ... }at the start ofconfiguration.nixandhome.nix. Nix is a functional language;configuration.nixandhome.nixare both functions, andpkgsand...are parameters. NixOS passesconfiguration.nixandhome.nixthe parameters during rebuild....lets Nix know to have any parameters that might be needed, whilepkgsis specifically included so thatpkgsis defined when it is used insystemPackages = with pkgs; [ # ... ]. Ashome.nixdoes not have any usage ofpkgsso far, technically, the first line ofhome.nixcan be stripped down to just{ ... }:; however,pkgswill very likely be used inhome.nixat some point. For more information about the Nix language, see here. - Connect to internet. Use
# nixos-rebuild switch. - Reboot. Use
$ Hyprlandto see that Hyprland works. No crashes.
Fixing kitty and xdg-desktop-portal:
- In Hyprland, use
$ kittyto 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 dbusshows no abnormalities, but using$ systemctl --user status xdg-desktop-portal.serviceshows (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.systemPackagesor 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.serviceshows 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 exportcan 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.nixas a result of the errors:{ pkgs, ... }: { # ... services = { # ... + pipewire.enable = true; }; + security.rtkit.enable = true; + xdg.portal = { + enable = true; + extraPortals = [ pkgs.xdg-desktop-portal-gtk ]; + }; # ... } - Connect to internet. Use
# nixos-rebuild switch.
Using Home Manager to configure Hyprland:
- Edit
home.nix:Since I am using Hyprland from{ pkgs, ... }: { # ... + 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" + "fadeLayers, 1, 4, expoOut" + "border, 1, 4, expoOut" + "borderangle, 1, 6, expoOut, once" + "workspaces, 1, 3, snappyOut1, slide" + ]; + general = { + border_size = 2; + gaps_in = 4; + gaps_out = 10; + "col.active_border" = "rgba(225,225,225,1) rgba(255,255,255,0.65) 45deg"; + "col.inactive_border" = "rgba(107,127,148,0.5)"; + resize_on_border = true; + }; + decoration = { + rounding = 8; + shadow = { + range = 6; + render_power = 1; + color = "rgba(102,196,204,0.1)"; + color_inactive = "rgba(51,51,51,0.1)"; + }; + blur = { + size = 4; + passes = 3; + }; + }; + input = { + repeat_delay = 500; + sensitivity = "0.3"; + accel_profile = "flat"; + touchpad = { + disable_while_typing = false; + natural_scroll = true; + tap-and-drag = false; + scroll_factor = 0.15; + }; + }; + 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; + }; + windowrule = [ + "scrolltouchpad 1.0, class:kitty" + ]; + }; + }; # ... }pkgs.hyprland, I do not need to specifywayland.windowManager.hyprland.packagefor Home Manager.
Options that have syntax similar to Nix need to be wrapped in"".
When defining colors withrgba(), there must be no whitespace.
Although trackpad (libinput) configuration can be done throughconfiguration.nix, that doesn't work for me (/etc/X11/xorg.confisn'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.
Thewindowruleparametertitle:[regex]is not specified because Kitty changes the title based on the previous command visible through using$ hyprctl clients. - 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 switchagain.
Now, the configurations fromhome.nixappear.
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.nixagain.
Using Home Manager to configure kitty:
- Edit
home.nix:The{ pkgs, ... }: { # ... + 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.kitty.shellIntegration.enableZshIntegrationHome Manager option is not set because it does not actually achieve shell integration. Although kitty uses"yes"and"no", Home Manager convertstrueandfalseto 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.
- To install
firefoxfor all users, editconfiguration.nix:Policies (view in Firefox internal page with URL{ pkgs, ... }: { # ... programs = { # ... + firefox = { + enable = true; + 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" = false; + "browser.tabs.inTitlebar" = 0; + "browser.uidensity" = 1; + "browser.urlbar.shortcuts.tabs" = false; + "browser.urlbar.suggest.engines" = false; + "browser.urlbar.suggest.topsites" = false; + "browser.urlbar.suggest.calculator" = true; + "browser.urlbar.unitConversion.enabled" = true; + "browser.vpn_promo.enabled" = false; + }; + preferencesStatus = "user"; + }; }; # ... }about:policies; stored in file(s) in/nix/store/) are usually declared to allow administrators to set and lock browser settings.programs.firefox.policiesis declared inconfiguration.nixbecause the Home Manager optionprograms.firefox.policiesdoes not work. Other profile specific Home Manager options inprograms.firefox.profileswork.
Note: The Firefox policyNoDefaultBookmarksseems good, but actually breaks Home Manager'sprograms.firefox.profiles.<name>.bookmarksoption. When any option underprograms.firefox.profiles(likeprograms.firefox.profiles.<name>.bookmarks) fails, all other options underprograms.firefox.profilesfail; no error messages are displayed, but the configurations have no effect. Whenprograms.firefox.profiles.<name>.bookmarksworks, it silently overrides the default Firefox bookmarks.
Theprograms.firefox.preferencesoption is equivalent toprograms.firefox.policies = { Preferences = {} }; the definedpreferencespolicy can be seen inabout:policies. The preferences policy is a way of configuring the options viewable inabout:config; a user specific way of configuring options inabout:configis through Home Manager'sprograms.firefox.profiles.<name>.settings, which stores options in~/.mozilla/firefox/<name>/user.js.user.jsdefines overrides to~/.mozilla/firefox/<name>/prefs.js; Firefox modifiesprefs.jswhen options are changed directly throughabout:config. So, to modifyabout:configoptions for all users, using a policy throughconfiguration.nixis the only way, and to modifyabout:configoptions for a specific user, using Home Manager's optionprograms.firefox.profiles.<name>.settingsis the only way (there is no option for modifyingprefs.jsdirectly). Also, Home Manager's optionprograms.firefox.profiles.<name>.extraConfigmodifiesuser.jsas well, as seen in Home Manager'smkFirefoxModule.nix.
Note: While not all options are viewable inabout:config, nearly all Firefox options are 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.enabledvalue is already set tofalse. - Connect to internet. Use
# nixos-rebuild switch.
Use$ firefoxto 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 themeconfiguration.nix:And edit{ pkgs, ... }: { # ... environment = { systemPackages = with pkgs; [ # ... + capitaine-cursors ]; # ... }; # ... }home.nix:{ pkgs, ... }: { home = { # ... + pointerCursor = { + package = pkgs.capitaine-cursors; + name = "capitaine-cursors"; + size = 22; + gtk.enable = true; + x11.enable = true; + x11.defaultCursor = "default"; + }; }; + gtk = { + enable = true; + }; # ... }home.pointerCursorsets up many cursor configurations; it sets upXCURSORenvironment variables which configure the cursor on Hyprland without Hyprcursor. Configuring environment variables need a reboot to apply.
home.pointerCursor.packagemust 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-cursorsincludes 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:Note: Installing{ pkgs, ... }: { # ... + programs.firefox = { + enable = true; + 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; + }; + }; # ... }firefox-bininstead offirefoxdoes not seem to interfere with its configuration through Home Manager. I specifiedprograms.firefox.package = pkgs.firefox-bininhome.nix, matching the package inconfiguration.nix; yet, when I first used# nixos-rebuild switch, a download of a Firefox package began. I updated/etc/nixos/flake.lock, used# nixos-rebuild switchwithout any Firefox configurations inhome.nix, and then used# nixos-rebuild switchwith Firefox configurations includingprograms.firefox.package = pkgs.firefox-bininhome.nix; during this rebuild no Firefox package was downloaded. Using$ nix-store -q --references /run/current-system/sw | grep firefoxshows 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.nixhome-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-binof a different version than thepkgs.firefox-binalready installed in the system, so Home Manager tries to install the newerpkgs.firefox-binfrom 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.lockto 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.lockwas 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 switchwithout modifyinghome.nix, reopening Firefox will generate the default profile instead of the profiles defined inprograms.firefox.profiles.
programs.firefox.profiles.<name>.idmust be declared when multiple profiles are declared.
The syntax insideprograms.firefox.profiles.<name>.bookmarksdoes not allow;'s after{}'s. Thetoolbaroption 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, ... }. Thekeywordoption redirects typing the string in the address bar to the bookmark.
Configurations insideprograms.firefox.profiles.<name>.settingsare all configurations not available through the preferences policy inconfiguration.nix.
programs.firefox.profiles.<name>.search.forcedoes 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. TheSearchEnginespolicy 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.privateDefaultdoes not work, but the default is Google.
Remove the directories~/.mozillaand~/.cache/mozilla. Connect to internet. Use# nixos-rebuild switch.
Since the nixos-rebuild command allows using a flake from remote locations, not just /etc/nixos, all files in /etc/nixos can be moved to a GitHub repository for the system to rebuild from. To do this, upload all the files (flake.nix flake.lock configuration.nix hardware-configuration.nix home.nix) in /etc/nixos to a GitHub repository. From now on, use # nixos-rebuild switch --flake github:0dpe/Linux-Journey#ZHAN --refresh instead of just # nixos-rebuild switch, and rebuilds always require internet access. All files in /etc/nixos can be removed.
Note: The --refresh flag is required for nixos-rebuild to use the repository all the time. Without the flag, nixos-rebuild only checks the repository once in a one hour duration.
For shortening the command, add in configuration.nix:
{ pkgs, ... }:
{
# ...
environment = {
# ...
+ shellAliases = {
+ rebuild = "sudo nixos-rebuild switch --flake github:0dpe/Linux-Journey#ZHAN --refresh";
+ };
};
# ...
}Note: environment.shellAliases requires a reboot to take effect.
To automatically update the flake.lock file in the GitHub repository, add a GitHub action to the repository. Create and edit .github/workflows/Update Flake Lock.yml:
name: Update Flake Lock
on:
workflow_dispatch:
schedule:
- cron: '0 0 * * 0'
jobs:
update-flake-lock:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Install Nix
uses: DeterminateSystems/nix-installer-action@main
- name: Update flake.lock
uses: DeterminateSystems/update-flake-lock@main
with:
pr-title: "Update Flake Lock"Note: To manually update the flake.lock file, use $ nix flake update --flake github:0dpe/Linux-Journey --output-lock-file ~/flake.lock and replace the old flake.lock in the repository with the new ~/flake.lock.
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
brightnesswithoutsudofor all users, editconfiguration.nix:{ pkgs, ... }: { # ... services = { # ... + udev.extraRules = '' + ACTION=="add", SUBSYSTEM=="backlight", KERNEL=="intel_backlight", MODE="0666", RUN+="${pkgs.coreutils}/bin/chmod a+w /sys/class/backlight/%k/brightness" + ''; }; # ... }udevis enabled by default.
After rebuild the system and then rebooting,/sys/class/backlight/intel_backlight/brightnesshas permissions-rw-rw-rw-. - To bind dynamic commands to keybinds to change screen brightness in Hyprland, edit
home.nix:{ pkgs, ... }: { # ... wayland.windowManager.hyprland = { # ... settings = { # ... + 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))" + ]; # ... }; }; # ... } - Rebuild the system.
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:{ pkgs, ... }: { # ... services = { # ... + getty.extraArgs = [ "--skip-login" "--login-options" "tim" ]; }; # ... }getty(get-tty) manages TTYs.
services.getty.autologinUseris not used because it skips the password too. - To start Hyprland automatically after login, edit
home.nix:Note: Options similar to{ pkgs, ... }: { # ... + programs.zsh = { + enable = true; + profileExtra = '' + if [ -z "''${DISPLAY}" ] && [ "''${XDG_VTNR}" -eq 1 ]; then + exec Hyprland + fi + ''; + }; # ... }programs.zsh.profileExtraexist forconfiguration.nix, but they are system wide.
Zsh executes a few files in a specific order on startup. the.zprofilefile is executed on all login startups.
-zchecks 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#;-eqmeans "equal".
Remove/home/tim/.zshrc, then rebuild the system.
The swww wallpaper manager does not have a configuration file; all configurations are done through commands.
-
To install swww, edit
configuration.nix:{ pkgs, ... }: { # ... environment = { systemPackages = with pkgs; [ # ... + swww ]; # ... }; # ... } -
Use
$ mkdir /home/tim/Wallpapersto create a directory for the wallpapers. -
To autostart swww and automatically randomize wallpapers, edit
home.nix:{ pkgs, ... }: { home = { # ... + 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 + ''; + }; + }; }; # ... wayland.windowManager.hyprland = { # ... settings = { # ... + exec-once = [ + "swww-daemon --no-cache" + "swww clear 000000 && ~/.swwwRandomizer /home/tim/Wallpapers 3600" + ]; }; }; # ... }Home Manager's
home.file.<name>.targetoption 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-onceto execute the command on Hyprland startup does not seem to work. Also, the NixOS optionwriteShellApplicationmight be worth exploring for system wide scripts.
Pseudocode for the script:- Shebang for NixOS.
- Define
usedas 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
allas an array of files inside$1/*.$indicates a variable. The variable1is the first argument passed to the script when it is run, like so:$ ~/.swwwRandomizer first_argument. Using$ ~/.swwwRandomizer /home/tim/Wallpaperssimplifies to(/home/tim/Wallpapers/*). The wildcard*lists all files in the directory. - Length of
usedequals length ofalland redefineusedas 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.selectedis defined later in the script; putting it here will never cause an error unlessallis defined as an empty array. Puttingselectedensures that images never get picked twice in a row after all images have been used.
Note:$#varworks in zsh, but not bash. In bash, curly braces{}are required:${#var}. - Define
unusedas an array ofallwithoutused.
{}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
selectedas the path of the (($RANDOMmodulo length ofunused) + 1)th file ofunused.
$RANDOMis a pre-defined command shell variable that returns a random integer between 0 and 32767. The modulo operator%returns the remainder from dividing$RANDOMby 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_posas 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 imgwith the image with pathselected.
Back slashes\are used to separate one line commands to multiple lines. Useswww img --helpto see all image display and transition options.--resize fitshrinks the image until the entire image is displayed;--resize cropenlarges the image until the screen is filled.-t growtransition animation type is a growing circle.-t anyrandomizes the position of the circle, but it also randomizes betweengrowandouter(shrinking circle) animations, so it is not used.--transition-posvalues separated by commas are float percentage values; arbitrarily the first and second floats of the shuffledrandom_posarray are used.-f Nearestis the fastest filter; best for pixel art. - Append
selectedto theusedarray. - Pause for variable
2seconds.
- Define
- End of loop.
The
--no-cacheflag is declared when startingswww-daemonbecause swww does not yet remember options such as filter and resize for cached images.
Using$ swww-daemonfor 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/imagedisplays a black wallpaper. Using$ swww queryshows 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 000000is executed once in the start to arbitrarily display black. Puttingswww clear 000000right 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.
Rebuild the system.
Oh My Posh is used for making shells look better.
- To install Oh My Posh, edit
configuration.nix:{ pkgs, ... }: { # ... environment = { systemPackages = with pkgs; [ # ... + oh-my-posh ]; # ... }; # ... } - To use Home Manager to configure Oh My Posh, edit
home.nix:While Oh My Posh's documentation suggests to edit{ pkgs, ... }: { # ... + 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"; + } + ]; + } + ]; + }; + }; # ... }.zshrc, Home Manager automatically does that.❱is\u2771; use$ echo "\u2771"to see the symbol. - Rebuild the system.
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, adding some extra options is recommended.
BlueZ is the official standard bluetooth package.
- Edit
configuration.nix:WirePlumber is PipeWire's session manager, a daemon that manages PipeWire.{ pkgs, ... }: { # ... services = { # ... - pipewire.enable = true; + pipewire = { + enable = true; + wireplumber.enable = true; + pulse.enable = true; + alsa.enable = true; + alsa.support32Bit = true; + }; # ... }; + hardware = { + bluetooth = { + enable = true; + powerOnBoot = true; + }; + }; # ... }
services.pipewire.pulse.enable = true;allows PulseAudio applications to work with PipeWire. Likewise, ALSA configurations allow ALSA compatibility.
hardware.bluetoothconfigures 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:4Ato connect toF8:4E:17:D3:E7:4A. Use[bluetooth]# trust F8:4E:17:D3:E7:4Ato automatically connect. Using[bluetooth]# quitwill not terminate the connection. Use$ bluetoothctl devices [Paired/Bonded/Trusted/Connected]to see paired, bonded, trusted, or connected devices. - To bind the buttons XF86AudioMute, XF86AudioLowerVolume, and XF86AudioRaiseVolume to WirePlumber commands to manage volume through Hyprland, edit
home.nix:Note:{ pkgs, ... }: { # ... wayland.windowManager.hyprland = { # ... settings = { # ... binde = [ # ... + ", 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%+\")}'" ]; # ... }; }; # ... }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. - Rebuild the system.
- Edit
configuration.nix:{ pkgs, ... }: { # ... + fonts = { + enableDefaultPackages = false; + packages = with pkgs; [ + nerd-fonts.go-mono + nerd-fonts.roboto-mono + nerd-fonts.lilex + nerd-fonts.jetbrains-mono + 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" ]; + }; + }; # ... }fonts.enableDefaultPackagesinstalls some fonts like DejaVu; DejaVu was the font used by kitty before this configuration was set tofalse(use$ kitty +list-fontsto see the fonts available to kitty). If this configuration was set tofalseand no other fonts are infonts.packages, then kitty's font rendering breaks.
Names infonts.fontconfig.defaultFontsare 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\Uxxxxxunicodes 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. - Rebuild the system.
Nix Colors exposes color schemes in the Base16 framework for use in .nix files. Each Base16 theme contains 16 colors; there are many hand crafted themes, and Nix Colors has functionality for generating Base16 themes from images or wallpapers.
- Nix Colors is not in nixpkgs, so to install it, edit
flake.nix:{ 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"; + nix-colors.url = "github:misterio77/nix-colors"; }; - outputs = { nixpkgs, home-manager, ... }: { + outputs = { nixpkgs, home-manager, ... }@inputs: { nixosConfigurations.ZHAN = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; + specialArgs = { inherit inputs; }; 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.extraSpecialArgs = { inherit inputs; }; } ]; }; }; }@inputshere puts all the parameters in{ nixpkgs, home-manager, ... }insideinputs.specialArgsis a set of arguments passed to themodules; includinginputsinsidespecialArgspassesinputstoconfiguration.nix. Home Manager's version ofspecialArgsnamedextraSpecialArgspassesinputstohome.nix.
Note: Trying to useinputsinhome.nixwithoutextraSpecialArgsinflake.nixresults in an infinite recursion error for some reason. Trying to useinputsinhome.nixwithoutspecialArgsinflake.nixresults in no error. Trying to useinputsinconfiguration.nixwithoutspecialArgsinflake.nixalso results in the same infinite recursion error. - Edit
home.nixto use Nix Colors:-{ pkgs, ... }: +{ pkgs, inputs, config, lib, ... }: +let + hexToRgba = color: opacity: + let + r = lib.fromHexString (builtins.substring 0 2 color); + g = lib.fromHexString (builtins.substring 2 2 color); + b = lib.fromHexString (builtins.substring 4 2 color); + in + "${builtins.toString r},${builtins.toString g},${builtins.toString b}"; +in { + imports = [ + inputs.nix-colors.homeManagerModules.default + ]; + colorScheme = inputs.nix-colors.colorSchemes.tokyo-night-terminal-dark; # ... wayland.windowManager.hyprland = { # ... settings = { # ... general = { # ... - "col.active_border" = "rgba(225,225,225,1) rgba(255,255,255,0.650) 45deg"; + "col.active_border" = "rgba(${hexToRgba config.colorScheme.palette.base07},1) rgba(${hexToRgba config.colorScheme.palette.base07},0.65) 45deg"; - "col.inactive_border" = "rgba(107,127,148,0.5)"; + "col.inactive_border" = "rgba(${hexToRgba config.colorScheme.palette.base03},0.6)"; # ... }; decoration = { # ... shadow = { # ... - color = "rgba(102,196,204,0.1)"; + color = "rgba(${hexToRgba config.colorScheme.palette.base05},0.2)"; - color_inactive = "rgba(51,51,51,0.1)"; + color_inactive = "rgba(${hexToRgba config.colorScheme.palette.base03},0.2)"; }; }; # ... }; }; # ... programs.oh-my-posh = { # ... settings = { # ... blocks = [ { type = "prompt"; alignment = "left"; segments = [ { type = "session"; style = "plain"; - foreground = "white"; + foreground = "#${config.colorScheme.palette.base0D}"; template = "{{ .UserName }}"; } { type = "path"; style = "plain"; - foreground = "white"; + foreground = "#${config.colorScheme.palette.base0C}"; properties = { style = "full"; }; } { type = "text"; style = "plain"; - foreground = "white"; + foreground = "#${config.colorScheme.palette.base05}"; template = "❱"; } ]; } { type = "rprompt"; alignment = "right"; overflow = "break"; segments = [ { type = "executiontime"; style = "plain"; - foreground = "white"; + foreground = "#${config.colorScheme.palette.base04}"; } ]; } ]; }; }; # ... }
- Update
flake.lockand rebuild the system.
Using Waybar
- To install Waybar, edit
configuration.nix:{ pkgs, ... }: { # ... programs = { # ... + waybar.enable = true; }; # ... } - To use Home Manager to configure Waybar, edit
home.nix:Waybar is a layer; use{ pkgs, inputs, config, ... }: # ... { # ... wayland.windowManager.hyprland = { # ... settings = { # ... + layerrule = [ + "blur, waybar" + "ignorealpha 0, waybar" + ]; # ... }; }; # ... + programs.waybar = { + enable = true; + settings.bar = { + reload_style_on_change = true; + layer = "top"; + position = "top"; + modules-left = [ "hyprland/workspaces" ]; + modules-right = [ "wireplumber" "bluetooth" "network" "battery" "clock" ]; + spacing = 0; + "hyprland/workspaces" = { + show-special = true; + format = ""; + }; + wireplumber = { + format = "{volume}%<span size='80%'> </span><span size='135%' line_height='0.1' rise='-1200'></span>"; + format-muted = "{volume}%<span size='80%'> </span><span size='135%' line_height='0.1' rise='-1200'></span>"; + on-click = "/run/current-system/sw/bin/wpctl set-mute @DEFAULT_SINK@ toggle"; + scroll-step = "0.1"; + tooltip = false; + }; + bluetooth = { + format-disabled = "Controller Disabled"; + format-off = "<span size='120%' line_height='0.1' rise='-6800'></span>"; + format-on = ""; + format-connected = "{device_alias} "; + on-click-right = "/run/current-system/sw/bin/bluetoothctl power $(bluetoothctl show | grep -q 'Powered: yes' && echo off || echo on)"; + on-click = "/run/current-system/sw/bin/bluetoothctl connect F8:4E:17:D3:E7:4A"; + tooltip-format-off = "{controller_alias} {status}"; + tooltip-format-on = "{controller_alias} {status}"; + tooltip-format-connected = "{controller_alias} {status}\n{device_enumerate}"; + tooltip-format-enumerate-connected = "{device_alias} {device_address}"; + }; + network = { + interval = 10; + format-wifi = "{essid}<span size='80%'> </span><span size='135%' line_height='0.1' rise='-1200'>{icon}</span>"; + format-disconnected = "<span size='135%' line_height='0.1' rise='-6000'></span>"; + format-icons = [ "" "" "" "" ]; + tooltip-format-wifi = "{bandwidthUpBytes} \n{bandwidthDownBytes} "; + tooltip-format-disconnected = "Disconnected"; + }; + battery = { + interval = 10; + bat = "BAT0"; + full-at = 97; + format = "{capacity}%<span size='80%'> </span><span size='92%' line_height='0.1' rise='500'>{icon}</span>"; + format-charging = "{capacity}%<span size='80%'> </span><span size='92%' line_height='0.1' rise='500'>{icon}</span><span size='20%'> </span><span size='90%' line_height='0.1' rise='600'></span>"; + format-icons = [ "" "" "" "" "" "" "" "" "" "" ]; + states = { + low = 20; + }; + tooltip = false; + }; + clock = { + format = "{:%R}"; + format-alt = "{:%b %d %R}"; + tooltip-format = "{calendar}"; + calendar = { + mode = "month"; + format = { + today = "<u><b>{}</b></u>"; + }; + }; + }; + }; + style = '' + * { + all: unset; + font: 12px "JetBrainsMonoNL Nerd Font Mono", monospace; + } + tooltip { + background: rgba(${hexToRgba config.colorScheme.palette.base00}, 0.3); + text-shadow: #${config.colorScheme.palette.base00} 0em 0em 0.4em; + border-radius: 9px; + } + .modules-right { + color: #${config.colorScheme.palette.base07}; + background: rgba(${hexToRgba config.colorScheme.palette.base00}, 0.3); + text-shadow: rgba(${hexToRgba config.colorScheme.palette.base00}, 0.4) 0em 0em 0.4em; + margin: 7px 9px 0px 0px; + padding-top: 0.45em; + padding-bottom: 0.45em; + border-radius: 9px; + } + .modules-left { + color: rgba(${hexToRgba config.colorScheme.palette.base07}, 0.4); + background: rgba(${hexToRgba config.colorScheme.palette.base00}, 0.3); + text-shadow: rgba(${hexToRgba config.colorScheme.palette.base00}, 0.4) 0em 0em 0.4em; + margin: 7px 0px 0px 9px; + padding-top: 0.45em; + padding-bottom: 0.45em; + border-radius: 9px; + } + #workspaces { + padding-right: 0.45em; + padding-left: 0.45em; + } + #workspaces button { + padding-right: 0.45em; + padding-left: 0.45em; + transition: all 0.1s linear; + } + #workspaces button:hover { + text-shadow: rgba(${hexToRgba config.colorScheme.palette.base07}, 0.7) 0em 0em 0.4em; + } + #workspaces button.active { + color: #${config.colorScheme.palette.base07}; + } + #workspaces button.urgent { + color: #${config.colorScheme.palette.base08}; + } + #wireplumber { + padding-right: 0.9em; + padding-left: 0.9em; + transition: text-shadow 0.1s linear; + border-image-source: linear-gradient(180deg, transparent 0%, rgba(${hexToRgba config.colorScheme.palette.base07}, 0.15) 25%, rgba(${hexToRgba config.colorScheme.palette.base07}, 0.15) 75%, transparent 100%); + border-image-width: 0.13em; + border-image-slice: 0% 100% 0% 0%; + } + #wireplumber:hover { + text-shadow: rgba(${hexToRgba config.colorScheme.palette.base07}, 0.7) 0em 0em 0.4em; + } + #bluetooth { + padding-right: 0.9em; + padding-left: 0.9em; + transition: text-shadow 0.1s linear; + border-image-source: linear-gradient(180deg, transparent 0%, rgba(${hexToRgba config.colorScheme.palette.base07}, 0.15) 25%, rgba(${hexToRgba config.colorScheme.palette.base07}, 0.15) 75%, transparent 100%); + border-image-width: 0.13em; + border-image-slice: 0% 100% 0% 0%; + } + #bluetooth:hover { + text-shadow: rgba(${hexToRgba config.colorScheme.palette.base07}, 0.7) 0em 0em 0.4em; + } + #network { + padding-right: 0.9em; + padding-left: 0.9em; + border-image-source: linear-gradient(180deg, transparent 0%, rgba(${hexToRgba config.colorScheme.palette.base07}, 0.15) 25%, rgba(${hexToRgba config.colorScheme.palette.base07}, 0.15) 75%, transparent 100%); + border-image-width: 0.13em; + border-image-slice: 0% 100% 0% 0%; + } + #battery { + padding-right: 0.9em; + padding-left: 0.9em; + transition: color 0.1s linear; + border-image-source: linear-gradient(180deg, transparent 0%, rgba(${hexToRgba config.colorScheme.palette.base07}, 0.15) 25%, rgba(${hexToRgba config.colorScheme.palette.base07}, 0.15) 75%, transparent 100%); + border-image-width: 0.13em; + border-image-slice: 0% 100% 0% 0%; + } + #battery.discharging.low { + color: #${config.colorScheme.palette.base08}; + } + #clock { + padding-right: 0.9em; + padding-left: 0.9em; + transition: text-shadow 0.1s linear; + } + #clock:hover { + text-shadow: rgba(${hexToRgba config.colorScheme.palette.base07}, 0.7) 0em 0em 0.4em; + } + ''; + }; # ... }$ hyprctl layersto seenamespace: waybarincluded.
barinprograms.waybar.settings.baris 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 ofwpctlandbluetoothctlto find them.
Inprograms.waybar.style, although colors are often repeated, CSS variables cannot be declared.
Nerd Fonts symbols used in the order inhome.nix:- Workspaces:
\uf111 - Wireplumber:
\Uf057e\Uf0e08 - Bluetooth:
\Uf00af\Uf00b2 - Network:
\Uf092e\Uf091f\Uf0922\Uf0925\Uf0928\Uf0552\Uf01da - Battery:
\Uf140b\Uf007a-f\Uf0080\Uf0081\Uf0082\Uf0079
- Workspaces:
- Rebuild the system.
VSCodium is VSCode built without telemetry.
- To install VSCodium, edit
configuration.nix:{ pkgs, ... }: { # ... environment = { systemPackages = with pkgs; [ # ... + vscodium ]; # ... }; # ... }vscodium-fhssacrifices purity for convenience; it is not needed a for purely declarative configuration. - To use Home Manager to configure VSCodium, edit
home.nix:The profile name must be{ pkgs, inputs, config, ... }: # ... { # ... + programs.vscode = { + enable = true; + package = pkgs.vscodium; + mutableExtensionsDir = false; + profiles.default = { + enableExtensionUpdateCheck = true; + enableUpdateCheck = true; + extensions = with pkgs.vscode-extensions; [ + bbenoist.nix + beirner.github-markdown-preview + streetsidesoftware.code-spell-checker + ]; + userSettings = { + "window.dialogStyle" = "custom"; + "window.titleBarStyle" = "custom"; + "editor.minimap.enabled" = false; + "cSpell.maxNumberOfProblems" = 10000; + "markdown.preview.scrollPreviewWithEditor" = false; + }; + }; + }; # ... }defaultsince the optionsprograms.vscode.profiles.<name>.enableExtensionUpdateCheckandprograms.vscode.profiles.<name>.enableUpdateCheckare invalid for all profiles exceptdefault.
Launching with$ codiumshows warning messages withis not in the list of known options, but still passed to Electron/Chromium. This is not an issue.
Similar to Firefox's~/.mozilla, the directory~/.vscode-ossmust be removed in every rebuild if it has been changed by VSCodium for the Home Manager environment to successfully start. - Rebuild the system.
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 -dis 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 same problem with VSCodium's ./vscode-oss
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\
VSCode title bar minimize maximize close buttons can crash VSCode but they can't be hidden?
Finish hyprland animation customization (layers, etc...)
https://github.com/alexhulbert/Hyprchroma
https://github.com/hyprland-community/awesome-hyprland/blob/main/README.md
Home manage git
Zsh frameworks? oh my zsh, prezto, zinit, antigen,
Zsh plugins (plugin managers as well?)
Packages for terminal: 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:
Terminal Text / Code Editor: Micro, neovim, helix
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 (also libreboot.org)?
Minimizing windows in Hyprland: 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
https://github.com/danihek/hellwal https://github.com/kayxean/oblique-cursor