Advanced Nix Workflows
This reference consolidates advanced Nix workflows that are used less frequently but remain valuable for specific situations.
Core workflows (used frequently) are in separate workflow files:
- Build (workflows/Build.md)
- Develop (workflows/Develop.md)
- Flakes (workflows/Flakes.md)
- Package (workflows/Package.md)
- Secrets (workflows/Secrets.md)
- Deploy (workflows/Deploy.md)
Debug - Debugging Nix Expressions and Builds
Debug Nix expressions, evaluation errors, and build failures.
When to Use
- “debug nix expression”
- “nix evaluation error”
- “troubleshoot nix build”
- “nix error messages”
Quick Commands
Evaluation Debugging
# Show evaluation trace
nix eval .#package --show-trace
# Evaluate with verbosity
nix eval .#package -vvv
# Show derivation
nix show-derivation .#package
# Inspect attribute path
nix eval .#nixosConfigurations.hostname.config.services
Build Debugging
# Build with full logs
nix build .#package -L
nix build .#package --print-build-logs
# Keep failed build directory
nix build .#package --keep-failed
# Show trace on error
nix build .#package --show-trace
# Maximum verbosity
nix build .#package -vvv --show-trace -L
Interactive Debugging
# Enter build environment
nix develop .#package
# Enter failed build directory
cd /tmp/nix-build-*
# Run phases manually
unpackPhase
patchPhase
configurePhase
buildPhase
Understanding Error Messages
Infinite Recursion
error: infinite recursion encountered
Cause: Circular dependency or self-referencing attribute
Debug:
# Problem
{
x = y;
y = x; # Infinite recursion!
}
# Fix: Break the cycle
{
x = lib.mkDefault value;
y = config.x;
}
Attribute Not Found
error: attribute 'foo' missing
Debug:
# Check what attributes exist
nix eval .#nixosConfigurations.hostname --apply builtins.attrNames
# Check nested attributes
nix eval .#nixosConfigurations.hostname.config --apply "x: builtins.attrNames x.services"
# Use --show-trace to see where error originates
nix eval .#package --show-trace
Type Errors
error: value is a set while a string was expected
Debug:
# Check type of value
nix eval .#value --apply builtins.typeOf
# Print value for inspection
nix eval .#value --apply "x: builtins.trace x x"
# Show detailed type error
nix eval .#value --show-trace
Hash Mismatches
error: hash mismatch in fixed-output derivation
got: sha256-AAAA...
wanted: sha256-BBBB...
Fix:
# Copy the "got" hash to your expression
# Or use nix-prefetch for correct hash
nix-prefetch-url https://example.com/file.tar.gz
nix-prefetch-github owner repo --rev commit-hash
Debugging Techniques
Trace Values
# Simple trace
value = builtins.trace "Debug: ${toString someValue}" someValue;
# Trace with lib
value = lib.traceVal someValue;
value = lib.traceValSeq "message" someValue;
# Trace attribute names
value = lib.traceSeq (builtins.attrNames attrs) attrs;
# Deep trace
value = lib.traceValSeqN 3 someNestedValue;
Evaluate Expressions
# Evaluate simple expression
nix eval --expr '1 + 1'
# Evaluate with nixpkgs
nix eval --expr 'with import <nixpkgs> {}; lib.version'
# Evaluate flake attribute
nix eval .#nixosConfigurations.hostname.config.networking.hostName
# Evaluate and show as JSON
nix eval .#package --json
# Evaluate and show as XML
nix eval .#package --xml
Check Configuration
# Check NixOS configuration validity
nixos-rebuild build --flake .#hostname --dry-run
# Show configuration options
nix eval .#nixosConfigurations.hostname.options
# Check if option exists
nix eval .#nixosConfigurations.hostname.options.services.nginx.enable.defined
# Show option documentation
nixos-option services.nginx.enable
Debugging Build Failures
Inspect Build Environment
# Enter build environment
nix develop .#package
# Check environment variables
env | grep -i nix
printenv
# Check build tools available
which gcc make cmake
# Check paths
echo $PATH
echo $PKG_CONFIG_PATH
Manual Build Steps
# Enter development shell
nix develop .#package
# Run phases manually
unpackPhase
ls -la
cd $sourceRoot
patchPhase
configurePhase
# Fix any configuration issues
buildPhase
# Fix build errors
checkPhase
installPhase
Inspect Failed Build
# Build with --keep-failed
nix build .#package --keep-failed
# Failed build kept at:
cd /tmp/nix-build-package-*.drv-0/
# Examine source
ls -la
find . -type f -name "*.log"
# Check build log
cat build.log
# Re-run failed command manually
./configure
make
Debug Build Script
# Show builder script
nix show-derivation .#package | jq '.[].env.builder'
# Show full derivation
nix derivation show .#package
# Print build environment
nix develop .#package --command printenv
Debugging Evaluation Errors
Stack Traces
# Show full stack trace
nix eval .#package --show-trace
# Example output:
# error: undefined variable 'foo'
#
# at /path/to/file.nix:42:5:
# 41| bar = {
# 42| baz = foo;
# | ^
# 43| };
Find Definition Location
# Find where option is defined
nix eval .#nixosConfigurations.hostname.options.services.nginx.enable.definitionsWithLocations
# Find where value is set
nix eval .#nixosConfigurations.hostname.options.services.nginx.enable.files
Check Module Evaluation
# Evaluate specific module
nix eval -f ./module.nix
# Check module with config
nix eval --expr 'import ./module.nix { lib = import <nixpkgs/lib>; }'
# Show module errors
nix-instantiate --eval --strict ./module.nix
Debugging Package Builds
Check Dependencies
# Show build dependencies
nix-store -q --references $(nix-build -A package)
# Show runtime dependencies
nix-store -q --requisites $(nix-build -A package)
# Show dependency tree
nix-store -q --tree $(nix-build -A package)
# Why is package kept?
nix-store --query --roots $(nix-build -A package)
Missing Dependencies
# Check what's needed
ldd result/bin/program
# Patch with nix
nix develop -c ldd ./program
# Auto-patch with autoPatchelfHook
nativeBuildInputs = [ autoPatchelfHook ];
Wrong Version Built
# Check what will be built
nix-build '<nixpkgs>' -A package --dry-run
# Check version in store
nix-store -q --hash $(nix-build -A package)
# Force specific version
nix build nixpkgs/nixos-23.11#package
Debugging NixOS Configurations
Configuration Evaluation
# Build configuration
nixos-rebuild build --flake .#hostname --show-trace
# Dry build to see what changes
nixos-rebuild dry-build --flake .#hostname
# Evaluate specific option
nix eval .#nixosConfigurations.hostname.config.system.stateVersion
Module Conflicts
error: The option `services.foo.enable' is defined multiple times
Debug:
# Find all definitions
nix eval .#nixosConfigurations.hostname.options.services.foo.enable.definitionsWithLocations
# Check module imports
nix eval .#nixosConfigurations.hostname.options._module.args --apply "x: builtins.attrNames x"
Service Failures
# Check service status after deployment
systemctl status servicename
# Check service logs
journalctl -u servicename -n 50
# Check generated config
systemctl cat servicename
# Verify config file
cat /etc/systemd/system/servicename.service
Debugging Flakes
Flake Evaluation
# Check flake
nix flake check
# Show flake outputs
nix flake show
# Evaluate flake metadata
nix flake metadata
# Lock file issues
nix flake lock --update-input nixpkgs
Input Problems
# Check inputs
nix flake metadata | grep -A 10 Inputs
# Update specific input
nix flake update nixpkgs
# Show input derivation
nix flake metadata --json | jq .locks
Pure Evaluation Errors
error: access to absolute path '/home/...' is forbidden in pure eval mode
Fix:
# Don't use absolute paths
# Bad
path = /home/user/file.nix;
# Good
path = ./file.nix;
# Or use --impure flag (not recommended)
nix build --impure
Advanced Debugging
Debug with nix repl
# Start repl
nix repl
# Load flake
:lf .
# Explore outputs
outputs.packages.x86_64-linux
# Load nixpkgs
:l <nixpkgs>
# Test expressions
lib.version
pkgs.hello
# Tab completion works
outputs.nixosConf[TAB]
Profile Evaluation
# Time evaluation
time nix eval .#package
# Show evaluation statistics
nix eval .#package --show-stats
# Profile build
nix build .#package --profile /tmp/profile
Debug with breakpoints
# In your expression
value = builtins.break (someExpression);
# Build will pause, entering debugger
# Commands:
# :continue - Continue evaluation
# :quit - Abort evaluation
# :env - Show environment
# :value - Show current value
Common Debug Patterns
Print and Return
# Debug helper
debug = msg: val: builtins.trace msg val;
# Usage
result = debug "Processing ${name}" (processValue value);
Conditional Debugging
# Only debug when flag is set
let
debugFlag = false;
debug = msg: val:
if debugFlag
then builtins.trace msg val
else val;
in
debug "Value" someValue
Assert Debugging
# Use assertions to catch errors early
{ ... }:
assert someCondition; {
# Your config
}
# Better with message
{ lib, ... }:
lib.assertMsg someCondition "Error: condition not met"
Debugging Tools
nix-tree
# Install
nix-shell -p nix-tree
# Explore dependencies interactively
nix-tree $(nix-build -A package)
nix-diff
# Compare two derivations
nix-diff $(nix-build -A package1) $(nix-build -A package2)
nix-du
# Analyze disk usage
nix-du -s=500MB
# Show largest paths
nix-du | head -20
Debugging Best Practices
- Use –show-trace: Always show full stack traces
- Keep failed builds: Use
--keep-failedto inspect - Enable verbose logs: Use
-Lflag for build logs - Use nix repl: Interactive exploration is powerful
- Check documentation: Many options have examples
- Test in isolation: Build packages separately
- Use nix develop: Debug in build environment
- Check flake.lock: Ensure inputs are correct
Emergency Debugging
System Won’t Boot
# Boot to previous generation (at boot menu)
# Or from rescue system:
# Mount nixos
mount /dev/sdX /mnt
mount /dev/sdY /mnt/boot
# Chroot
nixos-enter
# List generations
nix-env --list-generations --profile /nix/var/nix/profiles/system
# Rollback
/nix/var/nix/profiles/system-42-link/bin/switch-to-configuration switch
Out of Disk Space
# Clean old generations
nix-collect-garbage -d
# Delete specific generation
nix-env --delete-generations 10 11 12
# Optimize store
nix-store --optimize
# Find large paths
du -sh /nix/store/* | sort -h | tail -20
Resources
Security - Security Best Practices
Harden NixOS systems with security best practices and configurations.
When to Use
- “harden nixos”
- “nixos security”
- “security hardening”
- “apparmor nixos”
Quick Commands
Enable Hardened Profile
# Import hardened profile
imports = [
<nixpkgs/nixos/modules/profiles/hardened.nix>
];
Basic Security Configuration
# Firewall
networking.firewall.enable = true;
# AppArmor
security.apparmor.enable = true;
# Disable coredumps
systemd.coredump.enable = false;
Hardened Profile
What It Enables
The NixOS hardened profile provides:
- Hardened Linux kernel with security patches
- Scudo memory allocator for heap protection
- Kernel module loading prevention after boot
- Kernel image protection
- AppArmor mandatory access control
- Restricted filesystem module loading
- Disabled simultaneous multithreading (SMT)
- Forced page table isolation
Enable Hardened Profile
{ config, pkgs, ... }:
{
imports = [
<nixpkgs/nixos/modules/profiles/hardened.nix>
];
# The hardened profile is opinionated
# You may need to override some defaults
}
In Flakes
{
nixosConfigurations.hostname = nixpkgs.lib.nixosSystem {
modules = [
"${nixpkgs}/nixos/modules/profiles/hardened.nix"
./configuration.nix
];
};
}
Selective Hardening
# If full hardened profile is too restrictive
# Enable specific hardening features
{
# Hardened kernel
boot.kernelPackages = pkgs.linuxPackages_hardened;
# Memory allocator
environment.memoryAllocator.provider = "scudo";
# Lock kernel modules
security.lockKernelModules = true;
# Protect kernel image
security.protectKernelImage = true;
# AppArmor
security.apparmor.enable = true;
}
Firewall Configuration
Default Deny
networking.firewall = {
enable = true;
# Block all by default
allowedTCPPorts = [ ];
allowedUDPPorts = [ ];
# Allow specific services
# allowedTCPPorts = [ 22 80 443 ];
};
Service-Specific Rules
networking.firewall = {
enable = true;
# SSH
allowedTCPPorts = [ 22 ];
# HTTP/HTTPS
allowedTCPPorts = [ 80 443 ];
# Custom application
allowedTCPPorts = [ 8080 ];
allowedUDPPorts = [ 5353 ]; # mDNS
# Port ranges
allowedTCPPortRanges = [
{ from = 8000; to = 8100; }
];
# Allow specific interfaces
interfaces."eth0".allowedTCPPorts = [ 80 ];
};
Advanced Firewall
networking.firewall = {
enable = true;
# Reject instead of drop (faster for local testing)
rejectPackets = true;
# Allow ping
allowPing = true;
# Custom firewall rules
extraCommands = ''
# Rate limit SSH connections
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 -j DROP
# Log dropped packets
iptables -A INPUT -j LOG --log-prefix "FIREWALL-DROP: "
'';
};
AppArmor
Enable AppArmor
{
security.apparmor = {
enable = true;
# Kill unconfined but confinable programs
killUnconfinedConfinables = true;
# Load extra profiles
packages = with pkgs; [
apparmor-profiles
];
};
}
Custom AppArmor Profiles
{
security.apparmor = {
enable = true;
# Define custom profiles
policies = {
"myapp" = {
enable = true;
enforce = true;
profile = ''
#include <tunables/global>
/usr/bin/myapp {
#include <abstractions/base>
# Allow reading config
/etc/myapp/** r,
# Allow writing logs
/var/log/myapp/** w,
# Network access
network inet stream,
# Deny everything else
}
'';
};
};
};
}
Check AppArmor Status
# View loaded profiles
sudo aa-status
# View profile status
sudo aa-enabled
# Complain mode (log instead of enforce)
sudo aa-complain /path/to/program
# Enforce mode
sudo aa-enforce /path/to/program
User and Authentication Security
Strong Password Policies
{
security.pam.services = {
# Require strong passwords
passwd.text = ''
password required pam_pwquality.so retry=3 minlen=12 dcredit=-1 ucredit=-1 ocredit=-1 lcredit=-1
'';
};
# Password aging
security.pam.loginLimits = [
{ domain = "*"; type = "hard"; item = "maxlogins"; value = "3"; }
];
}
Sudo Configuration
{
# Require password for sudo
security.sudo = {
enable = true;
# Timeout for password (in minutes)
extraConfig = ''
Defaults timestamp_timeout=5
# Require password for every command
Defaults !authenticate
# Log all sudo commands
Defaults logfile=/var/log/sudo.log
'';
};
# Limit sudo to wheel group
security.sudo.wheelNeedsPassword = true;
}
SSH Hardening
{
services.openssh = {
enable = true;
settings = {
# Disable root login
PermitRootLogin = "no";
# Disable password authentication
PasswordAuthentication = false;
# Only allow key-based auth
PubkeyAuthentication = true;
# Disable empty passwords
PermitEmptyPasswords = false;
# Disable X11 forwarding
X11Forwarding = false;
# Use strong ciphers only
Ciphers = [ "chacha20-poly1305@openssh.com" "aes256-gcm@openssh.com" ];
KexAlgorithms = [ "curve25519-sha256" "curve25519-sha256@libssh.org" ];
Macs = [ "hmac-sha2-512-etm@openssh.com" "hmac-sha2-256-etm@openssh.com" ];
# Limit authentication attempts
MaxAuthTries = 3;
# Client timeout
ClientAliveInterval = 300;
ClientAliveCountMax = 2;
};
# Allow specific users only
allowUsers = [ "user1" "user2" ];
};
}
Systemd Service Hardening
Service Isolation
{
systemd.services.myservice = {
serviceConfig = {
# User/Group isolation
DynamicUser = true;
User = "myservice";
Group = "myservice";
# Filesystem isolation
ProtectSystem = "strict";
ProtectHome = true;
PrivateTmp = true;
ReadOnlyPaths = [ "/etc" ];
ReadWritePaths = [ "/var/lib/myservice" ];
# Network isolation
PrivateNetwork = false; # Set true to disable network
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
# Kernel isolation
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectKernelLogs = true;
ProtectControlGroups = true;
# Capabilities
CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ];
AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
NoNewPrivileges = true;
# System calls
SystemCallFilter = [ "@system-service" "~@privileged" ];
SystemCallArchitectures = "native";
# Devices
PrivateDevices = true;
DevicePolicy = "closed";
# Memory protection
MemoryDenyWriteExecute = true;
LockPersonality = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
# Namespace
RestrictNamespaces = true;
};
};
}
Analyze Service Security
# Check service security score
systemd-analyze security myservice.service
# Show detailed security analysis
systemd-analyze security --no-pager myservice.service
Application Sandboxing
Firejail
{
# Install firejail
environment.systemPackages = with pkgs; [ firejail ];
# Wrap applications with firejail
programs.firejail = {
enable = true;
# Wrap browsers
wrappedBinaries = {
firefox = {
executable = "${pkgs.firefox}/bin/firefox";
profile = "${pkgs.firejail}/etc/firejail/firefox.profile";
};
chromium = {
executable = "${pkgs.chromium}/bin/chromium";
profile = "${pkgs.firejail}/etc/firejail/chromium.profile";
};
};
};
}
Flatpak Sandboxing
{
services.flatpak.enable = true;
# Use Flatpak for untrusted applications
# Provides strong sandboxing via Bubblewrap
}
Kernel Hardening
Kernel Parameters
{
boot.kernel.sysctl = {
# Prevent kernel pointer leaks
"kernel.kptr_restrict" = 2;
# Restrict dmesg to root
"kernel.dmesg_restrict" = 1;
# Restrict loading TTY line disciplines
"dev.tty.ldisc_autoload" = 0;
# Disable kexec
"kernel.kexec_load_disabled" = 1;
# Restrict performance events
"kernel.perf_event_paranoid" = 3;
# Restrict BPF to CAP_BPF
"kernel.unprivileged_bpf_disabled" = 1;
# Enable ASLR
"kernel.randomize_va_space" = 2;
# Protect symlinks/hardlinks
"fs.protected_symlinks" = 1;
"fs.protected_hardlinks" = 1;
"fs.protected_fifos" = 2;
"fs.protected_regular" = 2;
# Network security
"net.core.bpf_jit_harden" = 2;
"net.ipv4.conf.all.rp_filter" = 1;
"net.ipv4.conf.default.rp_filter" = 1;
"net.ipv4.conf.all.accept_source_route" = 0;
"net.ipv6.conf.all.accept_source_route" = 0;
"net.ipv4.conf.all.send_redirects" = 0;
"net.ipv4.conf.default.send_redirects" = 0;
"net.ipv4.conf.all.accept_redirects" = 0;
"net.ipv6.conf.all.accept_redirects" = 0;
"net.ipv4.tcp_syncookies" = 1;
"net.ipv4.icmp_echo_ignore_broadcasts" = 1;
};
}
Blacklist Kernel Modules
{
boot.blacklistedKernelModules = [
# Disable uncommon network protocols
"dccp"
"sctp"
"rds"
"tipc"
# Disable uncommon filesystems
"cramfs"
"freevxfs"
"jffs2"
"hfs"
"hfsplus"
"udf"
# Disable legacy/unused
"bluetooth"
"btusb"
];
}
Secrets Management
Use agenix
{
# Never store secrets in plain text
# Use agenix for encrypted secrets
age.secrets.database-password = {
file = ../secrets/db-password.age;
owner = "postgres";
mode = "0400";
};
# Reference secret path (not content!)
services.postgresql.authentication = ''
# Use: config.age.secrets.database-password.path
'';
}
Prevent Secrets in Nix Store
{
# Don't do this:
# services.myapp.apiKey = "secret123"; # BAD! In nix store!
# Do this:
systemd.services.myapp = {
serviceConfig = {
EnvironmentFile = config.age.secrets.api-key.path;
};
};
}
Monitoring and Auditing
Audit Framework
{
# Enable audit framework
security.audit.enable = true;
security.auditd.enable = true;
# Audit rules
security.audit.rules = [
# Monitor sensitive files
"-w /etc/passwd -p wa -k passwd_changes"
"-w /etc/shadow -p wa -k shadow_changes"
"-w /etc/sudoers -p wa -k sudoers_changes"
# Monitor authentication
"-w /var/log/auth.log -p wa -k auth_log"
# Monitor network changes
"-a always,exit -F arch=b64 -S socket -S connect -k network"
];
}
ClamAV Antivirus
{
services.clamav = {
daemon.enable = true;
updater.enable = true;
};
# Scan on schedule
systemd.services.clamav-scan = {
description = "ClamAV system scan";
serviceConfig = {
Type = "oneshot";
ExecStart = "${pkgs.clamav}/bin/clamdscan --multiscan --fdpass /home";
};
};
systemd.timers.clamav-scan = {
wantedBy = [ "timers.target" ];
timerConfig = {
OnCalendar = "daily";
Persistent = true;
};
};
}
Network Security
OpenSnitch Firewall
{
# Application-level firewall
services.opensnitch = {
enable = true;
settings = {
DefaultAction = "deny";
DefaultDuration = "until restart";
};
};
}
VPN Configuration
{
# WireGuard VPN
networking.wireguard.interfaces = {
wg0 = {
ips = [ "10.100.0.2/24" ];
privateKeyFile = config.age.secrets.wireguard-key.path;
peers = [{
publicKey = "server-public-key";
endpoint = "vpn.example.com:51820";
allowedIPs = [ "0.0.0.0/0" ];
persistentKeepalive = 25;
}];
};
};
# Route all traffic through VPN
networking.firewall.checkReversePath = "loose";
}
Security Best Practices
- Use the hardened profile: Start with security-focused defaults
- Default deny firewall: Only allow required ports
- Enable AppArmor: Mandatory access control for services
- Harden SSH: Disable password auth, use keys only
- Systemd hardening: Use service isolation features
- Encrypt secrets: Never store secrets in Nix store
- Regular updates: Keep system and packages current
- Minimal installation: Don’t install unnecessary packages
- Monitor logs: Check audit logs regularly
- Principle of least privilege: Grant minimum required permissions
Testing Security Configuration
Check Open Ports
# Local ports
ss -tulpn
# From remote
nmap hostname
Verify AppArmor
# Check status
sudo aa-status
# View profile logs
sudo journalctl -u apparmor
Test Service Hardening
# Analyze security
systemd-analyze security service-name
# Check if service can access filesystem
sudo -u service-user cat /etc/shadow # Should fail
Common Hardening Pitfalls
-
Breaking functionality: Hardening can break applications
- Test thoroughly after changes
- Use
systemd-analyze securityto check impact
-
Performance overhead: Security features have cost
- Hardened kernel is slower
- Profile before/after
-
Update challenges: Hardening can complicate updates
- Document all customizations
- Test updates in VM first
-
Complexity: Too many security layers
- Start simple, add incrementally
- Understand each feature
Resources
- NixOS Security Wiki
- Solene’s NixOS Hardening Guide
- NixOS Hardened Profile
- AppArmor Documentation
- systemd Security Features
Troubleshoot - Common Issues and Solutions
Common Nix issues, error messages, and solutions.
When to Use
- “nix error”
- “troubleshoot nix”
- “nix build failing”
- “fix nix issue”
Common Errors
Hash Mismatch
Error:
error: hash mismatch in fixed-output derivation
specified: sha256-AAAA...
got: sha256-BBBB...
Solution:
# Copy the "got" hash
src = fetchFromGitHub {
owner = "owner";
repo = "repo";
rev = "v1.0.0";
hash = "sha256-BBBB..."; # Use hash from error
};
Get Hash Correctly:
# For GitHub
nix-prefetch-github owner repo --rev v1.0.0
# For URLs
nix-prefetch-url https://example.com/file.tar.gz
# For Git
nix-prefetch-git https://git.example.com/repo.git --rev commit-hash
Infinite Recursion
Error:
error: infinite recursion encountered
Common Causes:
# 1. Self-referencing attribute
{
x = x; # Infinite recursion!
}
# 2. Circular dependency
{
a = b;
b = a; # Infinite recursion!
}
# 3. Overlay recursion
final: prev: {
mypackage = prev.mypackage.override { # Infinite!
# ...
};
}
Solutions:
# Use lib.mkDefault or lib.mkForce
{ lib, ... }:
{
value = lib.mkDefault something;
}
# Break overlay recursion with super
final: prev: {
mypackage = (prev.mypackage.override {
# ...
}).overrideAttrs (old: {
# ...
});
}
# Use rec carefully
rec {
x = 1;
y = x + 1; # OK
}
Attribute Not Found
Error:
error: attribute 'foo' missing
error: undefined variable 'bar'
Debug:
# Check what attributes exist
nix eval .#nixosConfigurations.hostname --apply builtins.attrNames
# Check nested path
nix eval .#nixosConfigurations.hostname.config.services --apply builtins.attrNames
# Use --show-trace
nix eval .#value --show-trace
Common Fixes:
# Check spelling
services.nginx.enable = true; # Not nginX or nginx
# Import missing module
imports = [ ./missing-module.nix ];
# Check if package exists
nix search nixpkgs package-name
File Not Found
Error:
error: getting status of '/nix/store/.../file': No such file or directory
error: path '/path/to/file' does not exist
Solutions:
# Use relative paths in flakes
src = ./path/to/file; # Not /absolute/path
# Check file exists
# ls path/to/file
# In pure eval, paths must be relative
# Don't use: /home/user/file
# Use: ./file or ./relative/path
Import from Derivation (IFD)
Error:
error: cannot build '/nix/store/...' during evaluation
Cause: Import from Derivation - importing result of a build
Workarounds:
# Avoid when possible
# Bad:
let
generated = import (pkgs.runCommand "gen" {} ''
echo "{ value = 42; }" > $out
'');
in
generated.value
# Good: Use builtins or pure Nix
let
generated = { value = 42; };
in
generated.value
Restricted Mode / Pure Eval
Error:
error: access to absolute path '/home/...' is forbidden in pure eval mode
error: cannot look up '<nixpkgs>' in pure evaluation mode
Solutions:
# Use relative paths
path = ./file.nix; # Not /absolute/path
# Use flake inputs instead of <nixpkgs>
{ inputs, ... }:
inputs.nixpkgs.legacyPackages.x86_64-linux.hello
# For development, use --impure
nix build --impure
Build Failures
Compilation Errors
Check Build Log:
# View last build log
nix log .#package
# Keep build directory on failure
nix build .#package --keep-failed
# Inspect failed build
cd /tmp/nix-build-package-*.drv-0/
cat build.log
ls -la
Common Issues:
# Missing dependencies
# Add to buildInputs or nativeBuildInputs
# Wrong C/C++ compiler
# Set CC, CXX environment variables
# Missing pkg-config
# Add pkg-config to nativeBuildInputs
# Library not found
# Add to buildInputs and check PKG_CONFIG_PATH
Test Failures
Skip Tests Temporarily:
stdenv.mkDerivation {
# ...
doCheck = false; # Disable tests
}
Debug Tests:
# Run tests manually
nix develop .#package
unpackPhase
cd $sourceRoot
configurePhase
buildPhase
checkPhase # Run tests with full output
Missing Files in Output
Check Output:
# What's in the output?
nix build .#package
tree result/
ls -R result/
# Check if files were created during build
nix build .#package --keep-failed
cd /tmp/nix-build-*/
find . -name "expected-file"
Fix Install Phase:
installPhase = ''
runHook preInstall
mkdir -p $out/bin
cp myapp $out/bin/
# Install other files
mkdir -p $out/share/doc
cp README.md $out/share/doc/
runHook postInstall
'';
Runtime Issues
Executable Not Found
Error:
bash: command not found
Check:
# Is package installed?
which command-name
# Check package output
nix build .#package
ls result/bin/
# Check PATH
echo $PATH
# Install package
nix profile install .#package
Library Not Found
Error:
error while loading shared libraries: libfoo.so.1: cannot open shared object file
Solutions:
# Use autoPatchelfHook
nativeBuildInputs = [ autoPatchelfHook ];
# Add runtime dependencies
buildInputs = [ libfoo ];
# Check dependencies
ldd result/bin/program
# Patch manually
patchelf --set-rpath ${lib.makeLibraryPath [ libfoo ]} $out/bin/program
Permission Denied
Check Permissions:
# File permissions in store
ls -l result/
# Files should be readable
# Executables should have +x
Fix:
postInstall = ''
chmod +x $out/bin/myapp
'';
Disk Space Issues
Out of Disk Space
Check Space:
# Check /nix/store size
du -sh /nix/store
# Check total disk usage
df -h
# Find large paths
nix path-info --closure-size .#package | sort -h
Clean Up:
# Delete old generations
nix-collect-garbage -d
# Delete generations older than 30 days
nix-collect-garbage --delete-older-than 30d
# Optimize store (deduplicate)
nix-store --optimize
# Delete specific paths
nix-store --delete /nix/store/...-package
Garbage Collection Issues
Error:
error: cannot delete path '...' because it is in use by '...'
Solutions:
# Find what's using the path
nix-store --query --roots /nix/store/...-package
# Remove from profiles
nix profile remove package-name
# Delete old generations first
nix-env --delete-generations old
nix-collect-garbage
Network Issues
Download Failures
Error:
error: unable to download 'https://...'
error: curl error: Connection timeout
Solutions:
# Check network
ping example.com
# Try with different substituter
nix build --substituters https://cache.nixos.org
# Build without network (use only local)
nix build --offline
# Build without binary cache
nix build --no-substitute
Binary Cache Issues
Error:
error: cannot add path '...' to the store
warning: ignoring substitute for '...'
Solutions:
# Add cache manually
nix build --substituters https://cache.nixos.org \
--trusted-public-keys cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
# Configure in nix.conf
# trusted-substituters = https://cache.nixos.org
# Use cachix
cachix use cachename
Configuration Issues
Syntax Errors
Error:
error: syntax error, unexpected IF
error: undefined variable 'if'
Common Mistakes:
# 1. Missing semicolon
{
option1 = value1
option2 = value2; # ERROR: missing ; after value1
}
# 2. Wrong if syntax
if condition value1 value2 # ERROR: missing 'then' and 'else'
if condition then value1 else value2 # Correct
# 3. Missing 'in'
let x = 1; x + 1 # ERROR: missing 'in'
let x = 1; in x + 1 # Correct
# 4. Comments
/* Multi-line comment */
# Single-line comment
Module Conflicts
Error:
error: The option `services.foo.enable' is defined multiple times
Solutions:
# Use lib.mkForce to override
services.foo.enable = lib.mkForce true;
# Or remove duplicate definition
# Check all imported modules
# Use lib.mkMerge for lists
services.foo.extraConfig = lib.mkMerge [
(lib.mkIf condition1 [ value1 ])
(lib.mkIf condition2 [ value2 ])
];
Type Mismatches
Error:
error: value is a set while a string was expected
error: value is a string while a list was expected
Solutions:
# Check types
builtins.typeOf value
# Convert as needed
toString 42 # "42"
lib.splitString "," "a,b,c" # [ "a" "b" "c" ]
[ value ] # Wrap in list
# Check option type
# Look at option definition to see expected type
System Issues
System Won’t Boot
Recovery:
# 1. Boot to previous generation
# Select older generation in bootloader menu
# 2. From rescue system
mount /dev/sdX /mnt
mount /dev/sdY /mnt/boot
nixos-enter --root /mnt
# Rollback
nixos-rebuild switch --rollback
# Or specific generation
/nix/var/nix/profiles/system-42-link/bin/switch-to-configuration switch
Service Failures
Debug:
# Check service status
systemctl status service-name
# View logs
journalctl -u service-name -n 50
# View service definition
systemctl cat service-name
# Check generated config
cat /etc/systemd/system/service-name.service
Common Issues:
# Wrong user
systemd.services.myservice.serviceConfig.User = "correct-user";
# Missing dependency
systemd.services.myservice.after = [ "network.target" ];
# Wrong paths
# Use full store paths or ${}
ExecStart = "${pkgs.myapp}/bin/myapp";
Home-Manager Issues
Error:
error: collision between files
Solutions:
# Let home-manager manage conflicts
home.file."conflict".source = ./file;
# Force overwrite
home.file."conflict" = {
source = ./file;
force = true;
};
# Disable conflicting package
home.packages = lib.filter (p: p != pkgs.conflicting) config.home.packages;
Performance Issues
Slow Evaluation
Profile:
# Time evaluation
time nix eval .#nixosConfigurations.hostname.config.system.build.toplevel
# Show stats
nix eval --show-stats .#value
Optimize:
# Avoid expensive operations in hot paths
# Use builtins when possible
# Minimize use of import
# Cache computed values
Slow Builds
Speed Up:
# Use more cores
nix build --cores $(nproc)
# Parallel jobs
nix build --max-jobs auto
# Use binary caches
nix build --substituters https://cache.nixos.org
# Build without downloads
nix build --offline
Emergency Recovery
Corrupted Nix Store
Check:
# Verify store
nix-store --verify --check-contents
# Repair
nix-store --verify --repair
Locked Nix Database
Error:
error: cannot open Nix database: database is locked
Fix:
# Stop nix-daemon
systemctl stop nix-daemon
# Remove lock
rm /nix/var/nix/db/db.lock
# Restart daemon
systemctl start nix-daemon
Full Disk
Emergency Clean:
# Delete old generations
sudo nix-env --delete-generations +5
# Garbage collect
sudo nix-collect-garbage -d
# Optimize
sudo nix-store --optimize
# Remove build artifacts
rm -rf /tmp/nix-build-*