Add agent skills

This commit is contained in:
2026-02-05 18:47:42 +00:00
parent bc3350f501
commit 89aba25e23
13 changed files with 2681 additions and 0 deletions

View File

@@ -0,0 +1,323 @@
---
title: Common Configuration Mistakes
impact: HIGH
impactDescription: Prevents the most frequently made configuration errors
tags: mistakes,pitfalls,errors,checklist
---
## Why This Matters
Understanding common mistakes helps avoid them, saving time and preventing configuration errors.
## Mistake 1: Overlay in Wrong Location
### Symptom
Package not found even though overlay is defined.
### Cause
Overlay defined in `home.nix` when `useGlobalPkgs = true`.
### Solution
Move overlay to host's home-manager configuration block.
```nix
# ❌ WRONG
# home-manager/home.nix
{
nixpkgs.overlays = [ inputs.overlay.overlays.default ];
}
# ✅ CORRECT
# hosts/home/default.nix
{
home-manager.nixpkgs.overlays = [ inputs.overlay.overlays.default ];
}
```
**See:** [overlay-scope.md](overlay-scope.md)
## Mistake 2: Forgetting specialArgs
### Symptom
`undefined variable 'inputs'` error.
### Cause
Not passing `inputs` via `specialArgs`.
### Solution
Add `specialArgs = { inherit inputs; }`.
```nix
# ❌ WRONG
outputs = { self, nixpkgs, home-manager }:
{
nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
modules = [ ./hosts/myhost ];
};
}
# ✅ CORRECT
outputs = { self, nixpkgs, home-manager, ... }@inputs:
{
nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
specialArgs = { inherit inputs; };
modules = [ ./hosts/myhost ];
};
}
```
**See:** [flakes-structure.md](flakes-structure.md)
## Mistake 3: Editing hardware-configuration.nix
### Symptom
Hardware changes lost after running `nixos-generate-config`.
### Cause
Manually editing generated file.
### Solution
Put custom config in `default.nix`, not `hardware-configuration.nix`.
```nix
# ❌ WRONG: Editing hardware-configuration.nix
# hosts/laptop/hardware-configuration.nix
{ config, lib, pkgs, modulesPath, ... }:
{
# My custom kernel parameters (will be lost!)
boot.kernelParams = [ "intel_iommu=on" ];
# Generated hardware config...
}
# ✅ CORRECT: Custom config in default.nix
# hosts/laptop/default.nix
{
imports = [ ./hardware-configuration.nix ];
# Custom kernel parameters (safe!)
boot.kernelParams = [ "intel_iommu=on" ];
}
```
**See:** [host-organization.md](host-organization.md)
## Mistake 4: Duplicate Package Declarations
### Symptom
Package installed multiple times or conflicts.
### Cause
Same package in both system and Home Manager config.
### Solution
Install in appropriate location only.
```nix
# ❌ WRONG: Same package in both places
# hosts/base.nix
environment.systemPackages = with pkgs; [ firefox ];
# home-manager/home.nix
home.packages = with pkgs; [ firefox ]; # Duplicate!
# ✅ CORRECT: Choose one location
# User apps in Home Manager
home.packages = with pkgs; [ firefox ];
```
**See:** [package-installation.md](package-installation.md)
## Mistake 5: Not Following nixpkgs
### Symptom
Slow builds, inconsistent packages.
### Cause
Multiple independent nixpkgs instances.
### Solution
Use `.follows` for dependency inputs.
```nix
# ❌ WRONG: Independent nixpkgs
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
home-manager.url = "github:nix-community/home-manager/release-25.05";
# home-manager will use its own nixpkgs!
};
# ✅ CORRECT: Follow nixpkgs
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
home-manager.url = "github:nix-community/home-manager/release-25.05";
home-manager.inputs.nixpkgs.follows = "nixpkgs";
};
```
**See:** [flakes-structure.md](flakes-structure.md)
## Mistake 6: Mixing System and User Concerns
### Symptom
User-specific config in system files or vice versa.
### Cause
Not understanding NixOS vs Home Manager responsibilities.
### Solution
System config in NixOS, user config in Home Manager.
```nix
# ❌ WRONG: User config in system
# hosts/base.nix
{
# User's git config (should be in Home Manager)
programs.git = {
enable = true;
userName = "john";
userEmail = "john@example.com";
};
}
# ✅ CORRECT: User config in Home Manager
# home-manager/home.nix
{
programs.git = {
enable = true;
userName = "john";
userEmail = "john@example.com";
};
}
```
**See:** [package-installation.md](package-installation.md)
## Mistake 7: Forgetting to Rebuild
### Symptom
Changes don't appear after editing config.
### Cause
Editing config but not running rebuild.
### Solution
Always rebuild after config changes.
```bash
# After editing NixOS config
sudo nixos-rebuild switch --flake .#hostname
# After editing Home Manager config (standalone)
home-manager switch --flake .#hostname
# When using NixOS-integrated Home Manager
sudo nixos-rebuild switch --flake .#hostname
```
## Mistake 8: Overriding systemPackages Multiple Times
### Symptom
Some packages disappear after adding others.
### Cause
Multiple `environment.systemPackages` assignments.
### Solution
Use single list or mkBefore/mkAfter.
```nix
# ❌ WRONG: Multiple assignments
environment.systemPackages = with pkgs; [ vim git ];
environment.systemPackages = with pkgs; [ htop ]; # Overwrites!
# ✅ CORRECT: Single list
environment.systemPackages = with pkgs; [
vim
git
htop
];
# ✅ ALSO CORRECT: Use mkBefore/mkAfter
environment.systemPackages = with pkgs; [ vim git ];
environment.systemPackages = mkAfter [ pkgs.htop ];
```
## Mistake 9: Hardcoding Paths
### Symptom
Config breaks on different machines.
### Cause
Using absolute paths instead of Nix paths.
### Solution
Use relative paths or Nix constructs.
```nix
# ❌ WRONG: Absolute path
{ pkgs, ... }:
{
environment.systemPackages = [
"/home/john/my-app/bin/my-app" # Only works for john!
];
}
# ✅ CORRECT: Use Nix package
{ pkgs, ... }:
{
environment.systemPackages = [ pkgs.my-app ];
}
# ✅ OR: Use path from flake
{ ... }:
{
environment.systemPackages = [
(pkgs.callPackage ./local-packages/my-app { })
];
}
```
## Mistake 10: Not Using Flake References
### Symptom
Can't use packages from flake inputs.
### Cause
Not passing inputs or using wrong reference.
### Solution
Use `inputs.*` syntax.
```nix
# ❌ WRONG: Trying to use input package
{ pkgs, ... }:
{
environment.systemPackages = [
unfire-overlay # Where does this come from?
];
}
# ✅ CORRECT: Use input reference
{ pkgs, inputs, ... }:
{
environment.systemPackages = [
inputs.unfire-overlay.packages.${pkgs.system}.default
];
}
```
## Quick Checklist
Before committing config changes:
- [ ] Overlay in correct location for useGlobalPkgs setting
- [ ] inputs passed via specialArgs if needed
- [ ] Not editing hardware-configuration.nix
- [ ] No duplicate package declarations
- [ ] Following nixpkgs for dependency inputs
- [ ] System config separate from user config
- [ ] Tested with rebuild
- [ ] Using Nix paths, not absolute paths
- [ ] Correct input references for flake packages

View File

@@ -0,0 +1,188 @@
---
title: Flakes Configuration Structure
impact: CRITICAL
impactDescription: Foundation of flake-based NixOS configurations
tags: flakes,special-args,inputs,multiple-hosts
---
## Why This Matters
A well-structured flake.nix makes it easy to manage multiple hosts, share common configurations, and maintain the codebase. Poor structure leads to duplication and confusion.
## Core Structure
```nix
{
description = "My NixOS configuration";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
home-manager.url = "github:nix-community/home-manager/release-25.05";
home-manager.inputs.nixpkgs.follows = "nixpkgs";
# Add other flake inputs here
};
outputs = { self, nixpkgs, home-manager, ... }@inputs: {
nixosConfigurations.hostname = nixpkgs.lib.nixosSystem {
specialArgs = { inherit inputs; };
modules = [ ./hosts/hostname ];
};
};
}
```
## Special Args Pattern
Pass `inputs` via `specialArgs` to make flake inputs available in modules:
```nix
# ❌ WRONG: Forgetting specialArgs
outputs = { self, nixpkgs, home-manager }:
{
nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
modules = [ ./hosts/myhost ]; # inputs not available!
};
}
# ✅ CORRECT: Using specialArgs
outputs = { self, nixpkgs, home-manager, ... }@inputs:
{
nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
specialArgs = { inherit inputs; };
modules = [ ./hosts/myhost ]; # inputs available!
};
}
```
Then use in modules:
```nix
# hosts/myhost/default.nix
{ inputs, pkgs, ... }:
{
# Can now use inputs.*
imports = [
inputs.home-manager.nixosModules.home-manager
];
}
```
## Input Following
Set `inputs.nixpkgs.follows` to avoid duplicate nixpkgs instances:
```nix
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
# ❌ WRONG: Doesn't follow, creates duplicate nixpkgs
home-manager.url = "github:nix-community/home-manager/release-25.05";
# ✅ CORRECT: Follows nixpkgs, uses same instance
home-manager.url = "github:nix-community/home-manager/release-25.05";
home-manager.inputs.nixpkgs.follows = "nixpkgs";
};
```
## Multiple Hosts Pattern
```nix
outputs = { self, nixpkgs, home-manager, ... }@inputs: {
# Define multiple hosts
nixosConfigurations.laptop = nixpkgs.lib.nixosSystem {
specialArgs = { inherit inputs; };
modules = [ ./hosts/laptop ];
};
nixosConfigurations.desktop = nixpkgs.lib.nixosSystem {
specialArgs = { inherit inputs; };
modules = [ ./hosts/desktop ];
};
nixosConfigurations.server = nixpkgs.lib.nixosSystem {
specialArgs = { inherit inputs; };
modules = [ ./hosts/server ];
};
};
```
## System-Specific Packages
Pass system-specific args like `pkgs-stable`:
```nix
outputs = { self, nixpkgs, nixpkgs-stable, home-manager, ... }@inputs:
let
system = "x86_64-linux";
in
{
nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
specialArgs = {
inherit inputs system;
pkgs-stable = import inputs.nixpkgs-stable {
inherit system;
config.allowUnfree = true;
};
};
modules = [ ./hosts/myhost ];
};
};
```
Usage in host config:
```nix
# hosts/myhost/default.nix
{ inputs, pkgs, pkgs-stable, system, ... }:
{
environment.systemPackages = with pkgs; [
unstable-package # From nixos-unstable
];
# Or use stable version
environment.systemPackages = with pkgs-stable; [
stable-package
];
}
```
## Common Mistakes
1. **Not using @inputs pattern**: Forgetting to capture all inputs in a set makes it impossible to reference new inputs without updating the function signature.
2. **Missing specialArgs**: Inputs won't be available in modules without `specialArgs = { inherit inputs; }`.
3. **Hardcoded system**: Avoid hardcoding `x86_64-linux` multiple times. Define once and reuse.
4. **Not following nixpkgs**: Leads to multiple nixpkgs evaluations, slower builds, and potential inconsistencies.
## Quick Template
```nix
{
description = "NixOS configuration";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-25.05";
home-manager.url = "github:nix-community/home-manager/release-25.05";
home-manager.inputs.nixpkgs.follows = "nixpkgs";
# Add more inputs here
};
outputs = { self, nixpkgs, home-manager, ... }@inputs: {
nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
specialArgs = {
inherit inputs;
system = "x86_64-linux";
pkgs-stable = import inputs.nixpkgs-stable {
inherit system;
config.allowUnfree = true;
};
};
modules = [ ./hosts/myhost ];
};
};
}
```

View File

@@ -0,0 +1,296 @@
---
title: Host Configuration Organization
impact: HIGH
impactDescription: Prevents configuration chaos across multiple hosts
tags: hosts,modules,base-config,directory-structure
---
## Why This Matters
Proper host configuration organization prevents duplication, makes maintenance easier, and ensures consistency across multiple machines.
## Directory Structure
```
nixos-config/
├── flake.nix # Top-level flake
├── hosts/
│ ├── laptop/
│ │ ├── default.nix # Host-specific config
│ │ ├── hardware-configuration.nix # Generated (don't edit)
│ │ └── home.nix # Home Manager config
│ ├── desktop/
│ │ ├── default.nix
│ │ ├── hardware-configuration.nix
│ │ └── home.nix
│ └── base.nix # Shared by all hosts (optional)
├── modules/ # Reusable NixOS modules
├── overlays/ # Custom overlays
├── home-manager/ # Shared Home Manager configs
│ ├── shell/
│ ├── applications/
│ └── common.nix
└── secrets/ # Age-encrypted secrets
```
## Host Configuration Pattern
### Incorrect: Everything in one file
```nix
# hosts/laptop/default.nix
{ config, pkgs, ... }:
{
# Hardware config (copied from hardware-configuration.nix)
boot.initrd.availableKernelModules = [ "xhci_pci" "nvme" "usb_storage" ];
# ... 50 lines of hardware config ...
# Network config
networking.hostName = "laptop";
networking.networkmanager.enable = true;
# User config
users.users.john = {
isNormalUser = true;
extraGroups = [ "wheel" "networkmanager" ];
};
# Packages
environment.systemPackages = with pkgs; [ vim git wget ];
# Services
services.openssh.enable = true;
# Home Manager
imports = [
./home.nix # Or inline the entire home config
];
}
```
**Problems:**
- Hardware config duplicated (should import hardware-configuration.nix)
- User config duplicated across hosts
- No shared configuration
- Hard to maintain
### Correct: Modular structure
```nix
# hosts/laptop/default.nix
{ inputs, pkgs, pkgs-stable, system, ... }:
{
imports = [
./hardware-configuration.nix # Import hardware config
../base.nix # Import shared config
inputs.home-manager.nixosModules.home-manager
{
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.users.john = import ./home.nix;
home-manager.extraSpecialArgs = {
inherit inputs pkgs-stable system;
};
nixpkgs.overlays = [ inputs.some-overlay.overlays.default ];
}
];
# Host-specific config only
networking.hostName = "laptop";
}
```
## Shared Base Configuration
```nix
# hosts/base.nix
{ config, pkgs, inputs, ... }:
{
# Network
networking.networkmanager.enable = true;
# Time and locale
time.timeZone = "America/New_York";
i18n.defaultLocale = "en_US.UTF-8";
# Users (shared across all hosts)
users.users.john = {
isNormalUser = true;
extraGroups = [ "wheel" "networkmanager" ];
};
# Common packages
environment.systemPackages = with pkgs; [
vim
git
wget
tmux
];
# Common services
services.openssh.enable = true;
# Nix settings
nix.settings.experimental-features = [ "nix-command" "flakes" ];
}
```
## Hardware Configuration
```nix
# hosts/laptop/default.nix
{ ... }:
{
imports = [
./hardware-configuration.nix # Generated by nixos-generate-config
../base.nix
# ...
];
networking.hostName = "laptop";
}
```
**Important:** Don't edit `hardware-configuration.nix` manually. It's generated by `nixos-generate-config` and should be replaced when hardware changes.
## Home Manager Configuration
### Host-specific home.nix
```nix
# hosts/laptop/home.nix
{ config, pkgs, inputs, ... }:
{
imports = [
../../home-manager/shell
../../home-manager/applications
../../home-manager/common.nix
];
# Host-specific user config
home.packages = with pkgs; [
laptop-specific-package
];
}
```
### Shared Home Manager configs
```nix
# home-manager/shell/default.nix
{ config, pkgs, ... }:
{
imports = [
./fish
./neovim
./git
];
}
# home-manager/common.nix
{ config, pkgs, ... }:
{
home.packages = with pkgs; [
jq
ripgrep
fzf
];
programs.git.enable = true;
programs.git.userName = "John Doe";
programs.git.userEmail = "john@example.com";
}
```
## Multiple Hosts Example
```nix
# flake.nix
outputs = { self, nixpkgs, home-manager, ... }@inputs: {
nixosConfigurations.laptop = nixpkgs.lib.nixosSystem {
specialArgs = { inherit inputs; };
modules = [ ./hosts/laptop ];
};
nixosConfigurations.desktop = nixpkgs.lib.nixosSystem {
specialArgs = { inherit inputs; };
modules = [ ./hosts/desktop ];
};
nixosConfigurations.server = nixpkgs.lib.nixosSystem {
specialArgs = { inherit inputs; };
modules = [ ./hosts/server ];
};
};
```
Each host uses the same `base.nix` but can override settings:
```nix
# hosts/server/default.nix
{ ... }:
{
imports = [ ../base.nix ./hardware-configuration.nix ];
# Override time zone for server
time.timeZone = "UTC";
# Add server-specific packages
environment.systemPackages = with pkgs; [
htop
iotop
];
}
```
## Module Pattern
For reusable functionality, create modules:
```nix
# modules/docker.nix
{ config, pkgs, ... }:
{
virtualisation.docker = {
enable = true;
enableOnBoot = true;
};
users.users.john.extraGroups = [ "docker" ];
}
```
Use in host config:
```nix
# hosts/laptop/default.nix
{ ... }:
{
imports = [
../base.nix
../../modules/docker # Import module
./hardware-configuration.nix
];
}
```
## Common Mistakes
1. **Editing hardware-configuration.nix**: Changes are lost when regenerating. Put host-specific config in `default.nix` instead.
2. **Duplicating config across hosts**: Use `base.nix` or modules for shared configuration.
3. **Not separating host-specific and user-specific**: Keep host config in `hosts/*/default.nix`, user config in `home.nix` or `home-manager/`.
4. **Mixing concerns**: Don't put shell config in system packages. Use Home Manager for user-level packages.
## Quick Checklist
- [ ] Each host imports hardware-configuration.nix
- [ ] Shared config in base.nix or modules
- [ ] Home Manager configured in host file
- [ ] Host-specific settings only in host's default.nix
- [ ] User config in home.nix or home-manager/
- [ ] No duplication of hardware config
- [ ] No duplication of user config

View File

@@ -0,0 +1,132 @@
---
title: Overlay Scope and useGlobalPkgs
impact: CRITICAL
impactDescription: The most common issue: overlays don't apply with useGlobalPkgs=true
tags: overlay,useglobalpkgs,home-manager,scope
---
## Why This Matters
When using Home Manager with NixOS, the `useGlobalPkgs` setting determines where overlay definitions must be placed. Defining overlays in the wrong location means they simply don't apply, leading to "package not found" errors even when the overlay syntax is correct.
## The Problem
When `useGlobalPkgs = true`, Home Manager uses NixOS's global `pkgs` instance. Overlays defined in `home.nix` are ignored because Home Manager isn't creating its own `pkgs` - it's using the system one.
## Incorrect: Overlay in home.nix with useGlobalPkgs=true
```nix
# hosts/home/default.nix
{
home-manager.useGlobalPkgs = true; # Using system pkgs
home-manager.useUserPackages = true;
home-manager.users.chumeng = import ./home.nix;
}
# home-manager/home.nix
{ config, pkgs, inputs, ... }:
{
# ❌ This overlay is IGNORED when useGlobalPkgs = true!
nixpkgs.overlays = [ inputs.claude-code.overlays.default ];
home.packages = with pkgs; [
claude-code # Error: attribute 'claude-code' not found
];
}
```
**Why it fails:** When `useGlobalPkgs = true`, the `nixpkgs.overlays` line in `home.nix` has no effect. Home Manager isn't creating its own `pkgs`, so it can't apply overlays to one.
## Correct: Overlay in host home-manager block
```nix
# hosts/home/default.nix
{
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.users.chumeng = import ./home.nix;
home-manager.extraSpecialArgs = { inherit inputs pkgs-stable system; };
# ✅ Overlay defined HERE affects the global pkgs
nixpkgs.overlays = [ inputs.claude-code.overlays.default ];
}
# home-manager/home.nix
{ config, pkgs, ... }:
{
# No overlay definition needed here
home.packages = with pkgs; [
claude-code # ✅ Works! Found via overlay
];
}
```
**Why it works:** The overlay is defined where Home Manager configures the `pkgs` instance it will use. When `useGlobalPkgs = true`, this means the overlay is applied to the system's package set.
## Alternative: Set useGlobalPkgs=false
If you want to define overlays in `home.nix`, set `useGlobalPkgs = false`:
```nix
# hosts/home/default.nix
{
home-manager.useGlobalPkgs = false; # Home Manager creates own pkgs
home-manager.useUserPackages = true;
home-manager.users.chumeng = import ./home.nix;
}
# home-manager/home.nix
{ pkgs, inputs, ... }:
{
# ✅ This works when useGlobalPkgs = false
nixpkgs.overlays = [ inputs.claude-code.overlays.default ];
home.packages = with pkgs; [
claude-code # ✅ Works! Found via overlay
];
}
```
**Trade-off:** This creates a separate package set for Home Manager, which means packages are built twice (once for system, once for Home Manager). Only use this when you truly need separate package sets.
## Decision Matrix
| Your Need | useGlobalPkgs | Overlay Location |
|-----------|---------------|------------------|
| Single-user system, efficiency | `true` | Host home-manager block |
| Multi-user, different packages per user | `false` | User's home.nix |
| Custom packages system-wide | `true` | System nixpkgs.overlays |
| Quick prototype | `false` | User's home.nix |
## Verification
After adding an overlay, verify it works:
```bash
# Build the configuration
nixos-rebuild build --flake .#hostname
# Check if package is available
./result/sw/bin/package-name --version
# Or use nix repl to verify
nix repl
nix-repl> :l flake.nix
nix-repl> homeConfigs.hostname.config.home-manager.users.username.pkgs.package-name
```
## Common Mistakes
1. **Adding overlay both places**: Don't define the same overlay in both host config AND home.nix. It will apply twice and may cause conflicts.
2. **Forgetting to pass inputs**: If your overlay needs `inputs.*`, ensure `inputs` is in `extraSpecialArgs`:
```nix
home-manager.extraSpecialArgs = { inherit inputs; };
```
3. **Not rebuilding system**: Overlays defined in host config require full system rebuild, not just `home-manager switch`.
## References
- [Home Manager Manual - useGlobalPkgs](https://nix-community.github.io/home-manager/options.html#opt-home-manager.useGlobalPkgs)
- [NixOS Manual - Overlays](https://nixos.org/manual/nixos/stable/options#opt-nixpkgs.overlays)

View File

@@ -0,0 +1,264 @@
---
title: Package Installation Best Practices
impact: HIGH
impactDescription: Avoids conflicts and confusion about where to install packages
tags: packages,system,user,home-manager
---
## Why This Matters
Knowing where and how to install packages prevents conflicts, ensures proper updates, and maintains separation between system and user packages.
## System vs User Packages
### System Packages (NixOS)
Use for:
- System services (servers, daemons)
- Packages needed by all users
- Hardware-related packages (drivers, firmware)
- System-wide utilities
```nix
# hosts/base.nix or host-specific default.nix
{ config, pkgs, ... }:
{
environment.systemPackages = with pkgs; [
vim # Available to all users
git
wget
tmux
];
}
```
### User Packages (Home Manager)
Use for:
- User-specific applications
- Desktop applications
- Development tools (user-specific)
- Shell configurations
```nix
# home-manager/home.nix or sub-configs
{ config, pkgs, ... }:
{
home.packages = with pkgs; [
vscode # User-specific
chrome
slack
];
}
```
## Installing from Different Nixpkgs Channels
### Using unstable packages
```nix
# flake.nix - default is unstable
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-25.05";
};
# Host config
{ pkgs, pkgs-stable, ... }:
{
environment.systemPackages = with pkgs; [
vim # From unstable (default)
];
environment.systemPackages = with pkgs-stable; [
vim # From stable
];
}
```
### Using overlays for custom packages
```nix
# hosts/home/default.nix
{
nixpkgs.overlays = [
inputs.custom-overlay.overlays.default
];
}
# Now packages from overlay are available
{ pkgs, ... }:
{
home.packages = with pkgs; [
custom-package # From overlay
];
}
```
## Conditional Package Installation
### Based on host
```nix
# hosts/laptop/default.nix
{ config, pkgs, ... }:
{
environment.systemPackages = with pkgs; [
powertop # Laptop-specific
];
}
```
### Based on GUI environment
```nix
# hosts/base.nix
{ config, pkgs, ... }:
{
environment.systemPackages = with pkgs;
(if config.services.xserver.enable then [
firefox
dmenu
] else [
tmux
htop
]);
}
```
### Based on architecture
```nix
{ config, pkgs, ... }:
{
environment.systemPackages = with pkgs;
(if pkgs.system == "x86_64-linux" then [
docker-compose
] else [
podman
]);
}
```
## Wrapper Scripts
Modify package behavior with wrappers:
```nix
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
(symlinkJoin {
name = "google-chrome-with-flags";
paths = [ google-chrome ];
buildInputs = [ makeWrapper ];
postBuild = ''
wrapProgram $out/bin/google-chrome-stable \
--add-flags "--disable-gpu" \
--add-flags "--disable-features=UseChromeOSDirectVideoDecoder"
'';
})
];
}
```
## Common Mistakes
### Installing user packages system-wide
```nix
# ❌ WRONG: User-specific package in system config
environment.systemPackages = with pkgs; [
vscode # Should be in Home Manager
slack # Should be in Home Manager
];
# ✅ CORRECT: User packages in Home Manager
# home-manager/home.nix
home.packages = with pkgs; [
vscode
slack
];
```
### Installing packages in wrong location
```nix
# ❌ WRONG: System package in Home Manager
# home-manager/home.nix
home.packages = with pkgs; [
docker # Should be system package (needs service)
];
# ✅ CORRECT: System package in system config
# hosts/base.nix
environment.systemPackages = with pkgs; [
docker
];
virtualisation.docker.enable = true;
```
### Not using lists for multiple packages
```nix
# ❌ WRONG: Individual statements
environment.systemPackages = [ pkgs.vim ];
environment.systemPackages = [ pkgs.git ]; # Overwrites previous!
# ✅ CORRECT: Single list
environment.systemPackages = with pkgs; [
vim
git
];
```
## Package Updates
### Update all packages
```bash
nix flake update
nixos-rebuild switch --flake .#hostname
```
### Update specific input
```bash
nix flake lock update-input nixpkgs
nixos-rebuild switch --flake .#hostname
```
### Pin to specific version
```nix
# flake.nix
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-25.05"; # Pinned to release
# Or specific commit:
# nixpkgs.url = "github:nixos/nixpkgs/a1b2c3d...";
};
```
## Finding Packages
```bash
# Search for package
nix search nixpkgs package-name
# Get package info
nix eval nixpkgs#legacyPackages.x86_64-linux.package-name.meta.description
# Check what package provides a file
nix-locate bin/vim
```
## Quick Reference
| Package Type | Location | Example |
|-------------|----------|---------|
| System service | system config | `virtualisation.docker.enable = true` |
| System utility | system config | `environment.systemPackages = [ vim ]` |
| User app | Home Manager | `home.packages = [ vscode ]` |
| Development tool | Either (user usually) | `home.packages = [ nodejs ]` |
| Driver/firmware | system config | `hardware.graphics.enable = true` |

View File

@@ -0,0 +1,326 @@
---
title: Troubleshooting Configuration Issues
impact: MEDIUM
impactDescription: Systematic debugging approach for configuration issues
tags: debugging,errors,troubleshooting,verification
---
## Why This Matters
Knowing how to systematically debug NixOS configurations saves hours of frustration and prevents making random changes hoping something works.
## General Approach
Follow this order when debugging:
1. **Read error messages completely** - They usually tell you exactly what's wrong
2. **Verify syntax** - Check for missing brackets, quotes, commas
3. **Validate config** - Use `nixos-rebuild test` first
4. **Check scope** - Is overlay/module in correct location?
5. **Trace dependencies** - Are required inputs/imports present?
## Common Error Patterns
### "undefined variable 'inputs'"
**Cause:** `inputs` not passed via `specialArgs`.
**Fix:**
```nix
# flake.nix
outputs = { self, nixpkgs, ... }@inputs:
{
nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
specialArgs = { inherit inputs; }; # Add this
modules = [ ./hosts/myhost ];
};
};
```
### "attribute 'package-name' not found"
**Cause:** Package doesn't exist, or overlay not applied.
**Debug:**
```bash
# Check if package exists in nixpkgs
nix search nixpkgs package-name
# Check if overlay is defined
nix eval .#nixosConfigurations.myhost.config.nixpkgs.overlays
# Verify package in your config's pkgs
nix repl
nix-repl> :l flake.nix
nix-repl> myhost.config.environment.systemPackages
```
**Fix:**
- If overlay issue: Move to correct location (see [overlay-scope.md](overlay-scope.md))
- If missing package: Use correct package name or add overlay
### "error: The option 'some.option' does not exist"
**Cause:** Typo in option name, or option not available in your nixpkgs version.
**Debug:**
```bash
# Search for option
nixos-options | grep some-option
# Check option in current config
nix eval .#nixosConfigurations.myhost.config.some.option
```
**Fix:**
- Check option name spelling
- Verify nixpkgs version has this option
- Read option documentation for correct usage
### "infinite recursion"
**Cause:** Circular dependency in config.
**Debug:**
```bash
# Use --show-trace to see where
nixos-rebuild build --flake .#hostname --show-trace
```
**Fix:**
- Look for mutual dependencies
- Use `mkBefore`/`mkAfter` for ordering
- Break circular reference
### "hash mismatch" in flake.lock
**Cause:** Local changes or outdated lock file.
**Fix:**
```bash
# Update flake lock
nix flake update
# Or update specific input
nix flake lock update-input nixpkgs
```
## Overlay Not Applied
**Symptom:** Package from overlay not found.
**Debug steps:**
1. Check overlay definition:
```bash
nix eval .#nixosConfigurations.myhost.config.nixpkgs.overlays
```
2. Check overlay location:
```bash
# If useGlobalPkgs = true, overlay should be here:
grep -r "nixpkgs.overlays" hosts/myhost/default.nix
# NOT here:
grep -r "nixpkgs.overlays" home-manager/home.nix
```
3. Verify overlay input:
```bash
nix flake metadata
# Look for your overlay input
```
**Fix:** See [overlay-scope.md](overlay-scope.md)
## Configuration Changes Not Applying
**Symptom:** Edit config, rebuild, but nothing changes.
**Debug steps:**
1. Verify rebuild ran successfully:
```bash
sudo nixos-rebuild switch --flake .#hostname
# Look for "success" message
```
2. Check current generation:
```bash
sudo nix-env --list-generations --profile /nix/var/nix/profiles/system
```
3. Verify new generation is active:
```bash
sudo nixos-version
# Should show timestamp of recent rebuild
```
4. Check if option actually changed:
```bash
nix eval .#nixosConfigurations.myhost.config.some.option
```
**Fix:**
- Ensure rebuild succeeded
- Check if service needs restart: `systemctl restart service-name`
- For Home Manager: `home-manager switch` (or `sudo nixos-rebuild switch` if integrated)
## Build Fails with "store collision"
**Symptom:** Multiple packages trying to write to same path.
**Cause:** Usually duplicate package declarations or conflicting modules.
**Fix:**
- Remove duplicate package declarations
- Check for conflicting modules
- Use `--show-trace` to identify conflicting packages
## Verification Commands
### Check configuration without building
```bash
# Check syntax
nix flake check
# Dry run build
nixos-rebuild build --flake .#hostname --dry-run
# Evaluate specific option
nix eval .#nixosConfigurations.myhost.config.environment.systemPackages
```
### Test configuration safely
```bash
# Build without activating
nixos-rebuild build --flake .#hostname
# Test configuration (rollback on reboot)
nixos-rebuild test --flake .#hostname
# Switch (persistent)
nixos-rebuild switch --flake .#hostname
```
### Compare generations
```bash
# List system generations
sudo nix-env --list-generations --profile /nix/var/nix/profiles/system
# List Home Manager generations
home-manager generations
# Compare configurations
sudo nix diff-closures /nix/var/nix/profiles/system-*-link
```
## Useful Tools
### nix repl
```bash
nix repl
nix-repl> :l flake.nix # Load flake
nix-repl> myhost.config.environment.systemPackages # Access config
nix-repl> :b myhost.config.system.build.toplevel # Build
```
### nixos-version
```bash
# Check current system version
nixos-version
# Should show something like:
# 25.05.20250123.abc1234
```
### journalctl
```bash
# Check service logs for failures
sudo journalctl -xe
# Check NixOS rebuild logs
sudo journalctl -u nixos-rebuild
```
## Getting Help
When asking for help, provide:
1. **Full error message** (not just "it doesn't work")
2. **Minimal reproducible example**
3. **NixOS version**: `nixos-version`
4. **Relevant config files**
5. **What you've tried**
6. **Expected vs actual behavior**
Useful commands:
```bash
# Show system info
nixos-version
uname -a
# Show flake info
nix flake metadata
# Export config for sharing
nixos-rebuild build --flake .#hostname
nix-store -qR result > system-closure
```
## Common Debugging Workflows
### Package not found
```bash
# 1. Search for package
nix search nixpkgs package-name
# 2. Check if it's available for your system
nix eval nixpkgs#legacyPackages.x86_64-linux.package-name
# 3. Check your overlays
nix eval .#nixosConfigurations.myhost.config.nixpkgs.overlays
# 4. Check if overlay provides it
nix eval .#packages.x86_64-linux.package-name
```
### Overlay not applying
```bash
# 1. Verify overlay is defined
grep -r "overlays" hosts/myhost/
# 2. Check useGlobalPkgs setting
grep "useGlobalPkgs" hosts/myhost/default.nix
# 3. Evaluate overlay
nix eval .#nixosConfigurations.myhost.config.nixpkgs.overlays
# 4. Test package directly
nix build .#packages.x86_64-linux.package-name
```
### Service not starting
```bash
# 1. Check service status
systemctl status service-name
# 2. View service logs
journalctl -xeu service-name
# 3. Check service config
nixos-rebuild build --flake .#hostname --show-trace
# 4. Test service manually
/path/to/service-binary --verbose
```