Bootstrap to Activation
This tutorial guides you through setting up a new machine with this infrastructure, teaching you the concepts behind each step so you can confidently work with the system going forward.
What you will learn
Section titled “What you will learn”By the end of this tutorial, you will understand:
- How Nix flakes provide reproducible, declarative system configuration
- What the deferred module composition pattern is and why we organize modules by aspect rather than by host
- How direnv automatically activates your development environment
- What happens during system activation and how to verify success
- How to explore your machine’s configuration and make sense of the module structure
Prerequisites
Section titled “Prerequisites”Before starting, you need:
- Physical or SSH access to a macOS or NixOS machine
- Administrator privileges (sudo access)
- Git installed and configured with your credentials
- Internet connectivity for downloading packages
No prior Nix experience is required, but familiarity with command-line basics helps.
Estimated time
Section titled “Estimated time”45-60 minutes for your first run through. Subsequent machines take 15-20 minutes once you understand the concepts.
Understanding the architecture
Section titled “Understanding the architecture”Before touching the keyboard, let’s understand what we’re building toward.
Why Nix?
Section titled “Why Nix?”Traditional system configuration involves installing packages manually, editing configuration files in /etc/, and hoping you remember what you changed when something breaks.
Nix takes a different approach: your entire system configuration lives in version-controlled files, and the system state is derived from those files deterministically.
This means:
- Reproducibility: The same configuration produces the same system, every time
- Rollback: Every change creates a new generation you can roll back to
- Declarative: You describe what you want, not how to get there
The four-layer architecture
Section titled “The four-layer architecture”This infrastructure combines four complementary technologies:
- Flake-parts provides the foundation, organizing everything as composable modules
- Deferred module composition organizes modules by aspect (what they do) rather than by host (where they run)
- Clan-core coordinates multi-machine deployments with inventory-based service assignment
- Overlays provide stable fallbacks through multi-channel nixpkgs access
Module system foundation: The deferred module composition pattern uses deferred modules that delay evaluation until fixpoint computation. This enables the cross-cutting configuration patterns you’ll see below. See Deferred Module Composition for conceptual explanation.
You don’t need to understand all of this deeply right now. The key insight is that your machine configuration is just one piece of a larger, well-organized system.
For deeper understanding, see Architecture overview.
Deferred module composition organization
Section titled “Deferred module composition organization”Traditional nix configs often organize by host: all of stibnite’s configuration in one place, all of blackphos’s in another.
This leads to duplication when multiple machines need similar features.
The deferred module composition pattern instead organizes by aspect:
modules/├── machines/ # Machine-specific configurations│ ├── darwin/ # macOS hosts│ └── nixos/ # NixOS hosts├── home/ # User environment modules│ ├── users/ # Per-user configurations│ └── all/ # Shared user features├── nixpkgs/ # Package customizations└── clan/ # Multi-machine coordinationEach feature (git configuration, shell setup, development tools) lives in its own module. Machines compose these modules to build their complete configuration.
For the full explanation, see Deferred Module Composition.
Step 1: Clone the repository
Section titled “Step 1: Clone the repository”Let’s start by getting the configuration onto your machine.
cd ~/projects # Or wherever you keep your codegit clone https://github.com/cameronraysmith/vanixiets.gitcd vanixietsTake a moment to explore the structure:
ls -laYou’ll see:
flake.nix- The entry point defining all outputsmodules/- The deferred module composition hierarchysecrets/- Encrypted secrets (we’ll cover this in the secrets tutorial)justfile- Task runner with common operationsMakefile- Bootstrap automation
The flake.nix file is intentionally minimal because most logic lives in the auto-discovered modules.
This is the deferred module composition pattern at work.
Step 2: Bootstrap Nix and direnv
Section titled “Step 2: Bootstrap Nix and direnv”The bootstrap process installs Nix (if needed) and sets up direnv for automatic environment activation.
make bootstrapThis command:
- Checks if Nix is installed, installs it via the Determinate Systems installer if not
- Installs direnv for automatic development shell activation
- Configures your shell to use direnv
Why the Determinate Systems installer? It provides a cleaner installation with better macOS integration than the official installer, particularly for multi-user setups and Apple Silicon Macs.
Why direnv?
When you enter a directory with a .envrc file, direnv automatically activates the appropriate environment.
You get the right tools, environment variables, and shell configuration without remembering to run anything.
After bootstrap completes, restart your shell or run:
source ~/.zshrc # or ~/.bashrcStep 3: Allow direnv
Section titled “Step 3: Allow direnv”Now activate the development environment:
direnv allowThe first time takes a few minutes as Nix downloads and builds the development shell. You’ll see output as packages are fetched from the cache or built locally.
Once complete, your prompt may change (depending on your shell configuration), and you’ll have access to all the tools defined in the flake’s devShells.
Verify the environment:
which justwhich darwin-rebuild # On macOSwhich nixos-rebuild # On NixOSThese commands should point to paths inside /nix/store/, confirming the development shell is active.
Step 4: Explore your machine configuration
Section titled “Step 4: Explore your machine configuration”Before activating, let’s understand what configuration will be applied.
Find your machine
Section titled “Find your machine”Machines are defined in the clan inventory and have corresponding module directories:
# Darwin machinesls modules/machines/darwin/
# NixOS machinesls modules/machines/nixos/The current fleet includes:
- Darwin: stibnite, blackphos, rosegold, argentum
- NixOS: cinnabar, electrum, galena, scheelite
Find your machine’s directory. If your machine isn’t listed, you’ll need to create a configuration first; see the Host Onboarding Guide.
Understand the module structure
Section titled “Understand the module structure”Open your machine’s main configuration file.
For a darwin machine like stibnite:
cat modules/machines/darwin/stibnite/default.nixYou’ll see imports of various modules. These imports follow the deferred module composition pattern, pulling in features from across the module hierarchy rather than defining everything inline.
Notice how the file is relatively short. Most configuration comes from:
- Aggregate modules that bundle related features
- User modules that define personal environments
- Shared modules that all machines inherit
Trace an import
Section titled “Trace an import”Pick one import and follow it. For example, if you see an import of an aggregate module:
cat modules/home/users/crs58/default.nixThis shows how a user’s environment is composed from smaller, focused modules. Each module handles one concern (git, shell, development tools), making the system easier to understand and modify.
Step 5: Validate before activating
Section titled “Step 5: Validate before activating”Always validate your configuration builds before activating:
For darwin machines:
nix build .#darwinConfigurations.stibnite.system --dry-runReplace stibnite with your hostname.
The --dry-run flag shows what would be built without actually building.
For NixOS machines:
nix build .#nixosConfigurations.cinnabar.config.system.build.toplevel --dry-runIf validation succeeds with no errors, you’re ready to activate.
Step 6: Activate your configuration
Section titled “Step 6: Activate your configuration”Now apply the configuration to your system.
For darwin machines:
darwin-rebuild switch --flake .#stibniteOr use the just task:
just activateThe just activate command auto-detects your platform and hostname.
For NixOS machines managed by clan:
clan machines update cinnabarWhat happens during activation?
Section titled “What happens during activation?”The activation process:
- Builds the complete system configuration from your flake
- Creates a new system generation in
/nix/store - Switches symlinks to point to the new generation
- Runs activation scripts (creating users, starting services, etc.)
This is a transactional operation. If something fails, your previous generation remains intact.
Verify activation
Section titled “Verify activation”After activation completes:
# Check the current generationdarwin-rebuild --list-generations | head -5 # macOSnixos-rebuild --list-generations | head -5 # NixOS
# Verify a package is availablewhich gitgit --version
# Check home-manager status (if you have user configuration)home-manager generations | head -3If you configured zerotier, verify network connectivity:
sudo zerotier-cli listnetworksWhat you’ve learned
Section titled “What you’ve learned”You’ve now completed your first bootstrap-to-activation cycle. Along the way, you learned:
- Nix flakes provide reproducible, declarative system configuration
- Deferred module composition groups modules by aspect, reducing duplication
- direnv automatically activates your development environment
- Validation before activation catches errors before they affect your system
- Generations provide rollback safety for every change
Next steps
Section titled “Next steps”Now that your machine is activated, you should:
-
Set up secrets if you haven’t already. The Secrets Setup Tutorial walks you through secrets management with clan vars and legacy sops-nix.
-
Understand your user configuration by reading through your user module in
modules/home/users/. -
Explore the guides for operational tasks:
- Getting Started Guide for quick command reference
- Host Onboarding Guide for adding new machines
-
Deepen your understanding with the concepts documentation:
- Deferred Module Composition for module organization
- Clan Integration for multi-machine coordination
Troubleshooting
Section titled “Troubleshooting”direnv not activating
Section titled “direnv not activating”If your prompt doesn’t change after direnv allow:
# Ensure direnv hook is in your shell configgrep direnv ~/.zshrc # or ~/.bashrc
# If missing, add itecho 'eval "$(direnv hook zsh)"' >> ~/.zshrcsource ~/.zshrcBuild fails with hash mismatch
Section titled “Build fails with hash mismatch”This usually means a flake input was updated but not locked:
nix flake updatenix flake checkdarwin-rebuild not found
Section titled “darwin-rebuild not found”Ensure your development shell is active:
cd /path/to/infradirenv allowwhich darwin-rebuildPermission denied during activation
Section titled “Permission denied during activation”You need administrator privileges:
sudo darwin-rebuild switch --flake .#hostnameFor comprehensive troubleshooting, see the Host Onboarding Guide.