Machine definitions for multiple hosts using NixOS, nix-darwin
, and
home-manager
with flakes.
As someone who has put off truly learning how Nix (the language) works by rifling through blogs, open-source repositories, issue trackers, et al, I attempt to pay that effort forward by heavily commenting the configurations themselves and providing minimal documentation explaining the how and why to serve as a basic reference for others.
lib/mksystem.nix
is used to define hosts inflake.nix
.- Sets
specialArgs
for OS and home-manager modules to propagate information about the current user and system to children modules. - Adds required modules from flake inputs based on host configuration (e.g.,
disko
if the host provides a disk configuration).
- Sets
- Hosts can optionally provide a homie configuration, allowing user-specific configuration to be reused across multiple hosts.
- Non-critical secrets (
k3s
server token) are managed with ryantm/agenix. Critical secrets (tailscale
reusable auth key, private keys) are managed using Bitwarden, outside of Nix.
While the structure and approach of this repository have more-or-less settled,
it is still very much an early stage WIP. TODOs are tracked in
TODO.md and # TODO
comments scribbled throughout.
Host Nix files in hosts/
define attribute sets that are used by
lib/mksystem.nix
to instantiate the appropriate system configuration in the
root flake.nix
, e.g.:
# hosts/example.nix
{
system = "aarch64-darwin"; # The system architecture.
user = "shimmerjs"; # The system's main user.
# Optional user-specific configuration that can be shared across hosts,
# see more info below.
homie = import ../homies/shimmerjs;
# OS config, which will be evaluated by nix-darwin or NixOS depending on the
# value for 'system' above.
systemConfig = import ./configuration.nix;
# home-manager configuration for this host's main user as defined above.
home = import ./home.nix;
# diskConfig is an optional attribute that allows Nix to also manage the
# disk setup via disko
diskConfig = import ../../modules/nixos/disko/simple-gpt-lvm.nix {
disk = "/dev/nvme0n1";
};
}
Can then be instantiated in flake.nix
by doing:
# flake.nix
outputs = inputs@{ self, nixpkgs, home-manager, darwin, ... }:
let
mkSystem = import ./lib/mksystem.nix { inherit nixpkgs inputs; };
in
{
darwinConfigurations = {
example = mkSystem "example";
};
};
};
# [...]
User-specific configurations that can be layered on top of a host's system and home-manager config. The concept of homies allows separating the concerns of configuring my user and configuring a specific host.
A homie is structured as such:
# homies/dennis/default.nix
{
# home-manager module defining cross-platform userland for our homie dennis.
# This sould be configuration that dennis always wants to apply to his hosts.
home = import ./home;
# darwin and nixos are both attribute sets that define a system config
# module and an optional additional home-manager module that is added
# if this homie is imported into a system of that type.
darwin = {
systemConfig = { pkg, lib, config, ... }: { };
home = { pkg, lib, config, ... }: {};
};
nixos = {
systemConfig = { pkg, lib, config, ... }: { };
home = { pkg, lib, config, ... }: {};
};
}
Create hosts/$HOSTNAME.nix
or hosts/$HOSTNAME/default.nix
with the desired
system configuration.
Initialize system without cloning the repo:
# Install XCode tools
xcode-select --install
# Install Homebrew
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Install Nix
sh <(curl -L https://releases.nixos.org/nix/nix-${NIX_VERSION:-'2.22.1'}/install)
# Initialize system
nix run nix-darwin \
--extra-experimental-features nix-command \
--extra-experimental-features flakes \
-- switch --flake "github:shimmerjs/.universe#${HOSTNAME:-$(hostname)}"
To set up the ~/.universe
repo for pulling more updates and applying them by
hand, or tweaking that hosts config:
# Will prompt installation of XCode CLI tools
git clone https://github.com/shimmerjs/.universe $HOME/.universe && cd $HOME/.universe
hack/switch.sh
- https://github.com/mitchellh/nixos-config provided great inspiration and an initial foothold for general layout and approach in a flakey world. Still hate Terraform, though.
- Activating
nix-darwin
settings on switch instead of next login