❄️ NixOS & Home Manager Configurations
This repository contains a Nix Flake for configuring my computers and home environment. These are the computers this configuration currently manages:
Hostname | OEM | Model | OS | Kind | Status |
---|---|---|---|---|---|
g-xps |
Dell | XPS 15 7590 | ❄️ | 💻 | 🔜 |
g-aero |
Gigabyte | Aero 15 | ❄️ | 💻 | 🛠️ |
g-mac |
Apple | Macbook Pro 15 2013 | 🍎 | 💻 | 🔜 |
Not forked but shamelessly and heavily borrowed from Wimpy’s NixOS & Home Manager Configurations ❄️.
.
├── .keys 👈 hosts public GPG keys
├── home 👈 home-manager configurations
├── hosts 👈 NixOS configurations
├── lib 👈 helpers to make hosts and users home
├── overlays 👈 nixpkgs overlays
└── pkgs 👈 custom packages
This directory contains all configured hosts public GPG keys which are derived from their SSH RSA key. It is required for new installations since all secrets are re-encrypted with the new host public GPG key, therefore all other hosts public keys are needed as well.
For further details, read the secrets handling section.
This directory contains the home-manager configurations of users.
Note
There is a weak dependency between hosts users and home-manager users configuration, since home-manager does not create users. Therefore, users should first be created in hosts/common/users
and then configured here.
TODO: fill when home-manager configurations are up.
.
├── common 👈 Common on-the-shelf host configuration
├── iso-console 👈 ISO configuration for console installations
├── iso-gnome -> iso-console 👈 Symlink to console configuration for desktops ISOs
└── default.nix 👈 Common base host configuration
This directory contains the hosts configurations as well as composited configurations based on the arguments defined in flake.nix
.
All hosts share a base configuration which defines common boot loader parameters, default system packages, networking setup, keyboard layout, locale settings, programs, services and more… In short: stuff that should be configured whatever the host is.
Each host is defined in its own directory and mainly contains hardware specific configuration (with or without nixos-hardware), disks configuration (using Bash script or disko) and on-the-shelf configuration settings.
Additionally, ISO configurations can be found in this directory.
These configurations, located in the hosts/common
directory, are shared across multiple hosts but are entirely optional. Some on-the-shelf configurations are consumed automatically, given the arguments defined in flake.nix
. Others must be explicitly consumed by hosts which needs them.
These are consumed automatically:
About desktops
All desktops share a common base configuration which configures usual desktop stuff like pretty boot (splashscreen), fonts, browser, audio, bluetooth, graphics and more…
Each desktop is defined in its own directory and only contains configuration specific to this desktop.
Desktop configuration is automatically consumed by hosts which define a desktop
argument.
--
About users
These configurations must not configure the users home directory, packages and so on. They are only here to create the users, assign their groups, define their password… With the exception of nixos
user (read further).
User configuration is automatically consumed by hosts which define a username
argument.
There are two special users in this directory: root
and nixos
.
The root
user is the superuser definition for all hosts and is always consumed by configurations.
The nixos
user is the user used by ISO configurations. It is the only user which configures more than its basic definition. It comes with a Bash script to install NixOS on a given host.
--
These are explicitly consumed by hosts:
About networks
Since this flake takes a fully declarative approach, the NetworkManager service is disabled in order to be able to configure wireless networks declaratively with wpa_supplicant.
Multiple networks are available for consumption, they contain the wireless networks authentication details stored as sops secrets as well as their NixOS configuration.
For hosts to consume networks, they need to add the network configuration to their imports
list and enable networking.wireless.enable
.
imports = [ ../common/networks/<network-name> ];
networking.wireless.enable = true;
--
About printers
Similarly to wireless networks, printers configuration can be consumed by hosts which needs these printers.
Each printer definition should install the printer drivers and define the printer configuration.
For hosts to consume printers, they need to add the printer configuration to their imports
list and enable services.printing.enable
(automatically enabled on desktops).
imports = [ ../common/printers/<printer-name> ];
services.printing.enable = true; # Only required on servers
--
This directory contains some helper functions which are used to craft host and home-manager configurations:
mkHome
: generates an attrset for home-manager configuration of usersmkHost
: generates an attrset for NixOS configuration of hosts (both installs and ISOs)forAllSystems
: generates a list of all supported systems by this flake
This directory contains Nix Overlays which allow to override packages definitions.
A good use case example of an overlay is to update a package if its latest version is not available in nixpkgs.
This directory contains custom packages which are not yet in nixpkgs.
A good use case example of a custom package is to work on packaging an application before contributing it back to nixpkgs.
To generate an ISO of this flake, run one of the following commands from a Nix-enabled system:
# ISO with Gnome desktop
nix build '.#nixosConfigurations.iso-gnome.config.system.build.isoImage'
# ISO with console only
nix build '.#nixosConfigurations.iso-console.config.system.build.isoImage'
This ISO can then be used from a USB stick to install NixOS.
In order to provision a new host, its configuration must be present in this flake. Follow the steps below to add a new host.
Create a new directory under hosts
, named after the host. For example:
mkdir hosts/new-host
Create a basic hardware configuration in hosts/new-host/default.nix
:
{ inputs, ... }:
{
imports = [ /* ... */ ];
boot = { /* ... */ };
# ...
}
Tip
To generate a configuration for the new host, boot off a NixOS ISO and run:
nixos-generate-config --dir /tmp
Then copy the bare minimum from the generated /tmp/hardware-configuration.nix
(usually the boot
section) into hosts/new-host/default.nix
.
Note
As a convention, add info about the machine at the top of the host hardware configuration file :
# Brand: Dell, HP, etc…
# Model: Model name/number
# CPU : Model (Number of physical cores) @ CPU frequency
# RAM : Amount
# GPU : Brand, model and RAM amount
# Disk : Brand, model and size
For the disks configuration, two paths are available:
- use disko
- use a Bash script
Depending on the chosen path, a disks.nix
or a disks.sh
file must be created under hosts/new-host
.
It is also possible to have additional disks-*.nix
files which will be applied after the main disks.nix
file.
Declare the host in flake.nix
:
{
# ...
outputs = {
# ...
nixosConfigurations = {
# ...
new-host = libx.mkHost { hostname = "new-host"; username = "nicolas"; desktop = "gnome"; };
}
}
}
The username
argument must match one of the subdirectories of hosts/common/users
.
The desktop
argument must match one of the subdirectories of hosts/common/desktop
.
Failing to provide a valid username
or desktop
will not prevent the installation to succeed. However, without a username
only the root
user will be present on the installed system and without a desktop
the installed system will not have a graphical interface.
TODO: fill when home-manager configurations are up.
There are two installation method provided on the desktop ISO:
- Run
install-system
from a terminal (recommended, only install option for the console ISO) - Use the graphical Calamares installer (basic NixOS installation, not using this flake)
The install-system
command is a binary wrapping the install Bash script defined in a Nix file. Learn how to use it by reading its help message:
install-system -h
In a nutshell, the script will:
- use disko (or a Bash script) to automatically partition and format the disks
- prepare the host gpg identity
- install NixOS from this flake
- copy this flake to the target user’s home directory in
~/nixstrap
- apply home-manager configuration if it exists
Important
In order to proceed with the installation, a GPG private key known to the sops config is required to be in the local keyring.
gpg --import <gpg-private-key>
See the secrets handling section to learn more about why.
If not done already, clone this repo to ~/nixstrap
:
git clone git@github.com:nicolas-goudry/nix-config.git ~/nixstrap
# Or with curl + tar
curl -sL https://github.com/nicolas-goudry/nix-config/archive/main.tar.gz
tar xzf nix-config-main.tar.gz
mv nix-config-main ~/nixstrap
Then the NixOS or home-manager configurations can be rebuilt. Note that this flake takes the approach to split both configurations, therefore changes are applied separately. This is mainly for separation of concern and to avoid rebuilding the whole system every time, but also because some hosts are non-NixOS.
sudo nixos-rebuild switch --flake '.#<host>'
home-manager switch -b backup --flake '.#<username@host>'
To handle secrets management, this flake uses sops-nix. To avoid stuffing all secrets in a single secrets file, multiple secrets files are scattered across directories. The goal is to keep secrets that belong together in a single secrets file (ie. all wireless networks authentication details are in hosts/common/networks/secrets.yaml
, users password and sensitive files are in hosts/common/users/<user>/secrets.yaml
, …).
This flake uses GPG keys to handle secrets. There is a main GPG key for physical users and a GPG key derived from SSH for each host. All secrets files are encrypted with the users GPG public keys and hosts GPG public keys. To decrypt the secrets, at least one valid GPG private key is required to be in the host keyring.
When installing NixOS on a new host, the install-system
script handles the creation of the new host GPG key, stores it under the .keys
directory, adds it to the sops config file and re-encrypt all secrets afterward.
If a new host were to be added without the install-system
script, the following operations should be done manually:
-
derive new host GPG public key from its SSH RSA key
sudo nix run 'nixpkgs#ssh-to-pgp' -- -i /etc/ssh/ssh_host_rsa_key -o ./.keys/<hostname>.pub
-
add the key fingerprint to
.sops.yaml
keys: hosts: - &new-host <fingerprint> creation_rules: - key_groups: - pgp: - *new-host
-
import all hosts and users public keys to local keyring
gpg --import .keys/*.pub gpg --import <path-to-users-keys>
-
re-encrypt all secrets
find . -type f -name 'secrets.y*ml' -exec sops updatekeys -y {} \;
-
commit and push changes to repository
- Work configuration
- ❓ Impermanence on
/home
- Configure nixvim ➡️ typecraft course | understanding neovim
- Hosts
- Fix ISO image
.gnupg
directory ofnixos
user owned byroot
(see Discourse post) - Fix NVIDIA GPU not used (see Discourse post)
- Write a
disks.sh
script to format g-xps disk while keeping Windows dual boot
- Fix ISO image
- Home
- Finish adding and configuring programs
- ❓ aria2 HM
- ❓ atuin HM
- awscli HM
- borgmatic HM
- broot HM / fd HM / fzf HM / yazi HM
- chromium HM
- git HM
- work-specific configuration
- ❓ gpg HM
- k9s HM
- lazygit HM
- mpv HM
- mr HM
- ❓ ncspot HM
- nix-index HM
- rbw HM
- ripgrep HM
- ❓ ssh HM
- tealdeer HM - replaces tldr
- thefuck HM
- ❓ thunderbird HM
- tmux HM / zellij HM
- ❓ vscode HM
- ❓ yt-dlp HM
- zoxide HM
- zsh HM
- user
dirHashes
- user
- Finish adding and configuring programs