Smithery Logo
MCPsSkillsDocsPricing
Login
NewFlame, an assistant that learns and improves. Available onTelegramSlack
    natea

    nix

    natea/nix
    DevOps

    About

    SKILL.md

    Install

    • Telegram
      Telegram
    • Slack
      Slack
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    • Download skill
    ├─
    ├─
    └─
    Smithery Logo

    Give agents more agency

    Resources

    DocumentationPrivacy PolicySystem Status

    Company

    PricingAboutBlog

    Connect

    © 2026 Smithery. All rights reserved.

    About

    Expert guidance on Nix, NixOS, and home-manager best practices. USE WHEN working with Nix expressions, NixOS configuration, home-manager, flakes, or Nix package development.

    SKILL.md

    Nix Best Practices

    Purpose

    Expert guidance on Nix, NixOS, and home-manager following best practices.

    Context Detection

    This skill activates when:

    • Current directory contains flake.nix, default.nix, shell.nix, or configuration.nix
    • Git repository contains Nix configuration files
    • User is working with .nix files
    • User explicitly mentions NixOS, home-manager, flakes, or Nix packages
    • Commands like nix build, nixos-rebuild, or home-manager are mentioned

    Workflow Routing

    When the user's request matches specific Nix operations, route to the appropriate workflow:

    Workflow Trigger File
    Build "build nix package", "nixos-rebuild build", "compile nix" workflows/Build.md
    Debug "debug nix", "nix error", "troubleshoot build", "evaluation error" workflows/Debug.md
    Develop "development shell", "nix develop", "devShell", "direnv" workflows/Develop.md
    Deploy "deploy nixos", "nixos-rebuild switch", "remote deployment" workflows/Deploy.md
    Package "create package", "nix derivation", "buildGoModule", "package app" workflows/Package.md
    Flakes "create flake", "flake.lock", "update inputs", "flake outputs" workflows/Flakes.md
    Secrets "manage secrets", "agenix", "encrypt secrets", "age encryption" workflows/Secrets.md
    Security "harden nixos", "apparmor", "firewall", "security hardening" workflows/Security.md
    Troubleshoot "hash mismatch", "nix failing", "common errors", "fix nix issue" workflows/Troubleshoot.md

    When to use workflows:

    • Route when the user explicitly asks about one of these operations
    • Workflows provide comprehensive, focused guidance for specific Nix tasks
    • For general Nix guidance or module configuration, continue with this main skill

    Core Principles

    1. Declarative Configuration Over Imperative

    # Good: Declarative
    services.nginx.enable = true;
    
    # Bad: Imperative
    systemd.services.nginx.postStart = "systemctl start nginx";
    

    2. Reproducibility

    Same inputs = Same outputs

    • Pin versions explicitly
    • Use flake.lock for consistency
    • Avoid impure operations

    3. Modularity

    Break configurations into focused, reusable modules

    # Good: Modular
    imports = [
      ./hardware.nix
      ./networking.nix
      ./services.nix
    ];
    
    # Bad: Everything in one file
    

    4. Version Control Everything

    • Track all Nix configurations in git
    • Commit flake.lock changes
    • Document why changes were made

    5. Use Flakes for Modern Nix

    Flakes provide:

    • Hermetic evaluation
    • Standardized structure
    • Dependency locking
    • Better caching

    NixOS Configuration Patterns

    Host Configuration Structure

    # systems/<hostname>/
    ├── boot.nix       # Bootloader, initrd, kernel modules
    ├── hardware.nix   # Hardware settings, filesystems, mounts
    ├── extra.nix      # Optional: additional host-specific config
    └── home.nix       # Optional: host-specific home-manager config
    

    Using mkHost Pattern

    # In flake.nix
    nixosConfigurations = {
      hostname = libx.mkHost {
        hostname = "hostname";
        system = "x86_64-linux";
        hardwareType = "desktop";  # or "rpi4"
        desktop = "sway";          # or "niri", or null
        nixpkgs = nixpkgs;         # or nixpkgs-25_05 for stable
      };
    };
    

    Common Module Organization

    systems/common/
    ├── base/          # Essential base configuration
    ├── desktop/       # Desktop environment configs
    ├── hardware/      # Hardware-specific modules
    ├── programs/      # Application configurations
    ├── services/      # System services
    └── users/         # User account definitions
    

    Checking globals.nix

    Always check globals.nix for:

    • Machine definitions (IPs, SSH keys)
    • DNS zone configurations
    • VPN settings
    • Syncthing device IDs
    • Network topology

    Module Best Practices

    Define Options Properly

    { config, lib, pkgs, ... }:
    
    {
      options = {
        services.myservice = {
          enable = lib.mkEnableOption "my service";
    
          port = lib.mkOption {
            type = lib.types.port;
            default = 8080;
            description = "Port to listen on";
          };
    
          configFile = lib.mkOption {
            type = lib.types.path;
            description = "Path to configuration file";
          };
        };
      };
    
      config = lib.mkIf config.services.myservice.enable {
        # Implementation
      };
    }
    

    Use Types Correctly

    Common types:

    • types.bool - Boolean values
    • types.int - Integers
    • types.str - Strings
    • types.path - File system paths
    • types.port - Network ports (1-65535)
    • types.listOf types.str - Lists
    • types.attrs - Attribute sets
    • types.package - Nix packages

    Leverage mkIf, mkMerge, mkDefault

    # Conditional configuration
    config = lib.mkIf config.services.myservice.enable {
      # ...
    };
    
    # Merge multiple configurations
    config = lib.mkMerge [
      { always.present = true; }
      (lib.mkIf condition { conditional.value = true; })
    ];
    
    # Provide defaults that can be overridden
    services.myservice.port = lib.mkDefault 8080;
    

    Package Development

    Use callPackage Pattern

    # In pkgs/default.nix
    {
      mypackage = pkgs.callPackage ./mypackage { };
      mytool = pkgs.callPackage ./mytool { };
    }
    

    Package Definition

    # pkgs/mypackage/default.nix
    { lib
    , stdenv
    , fetchFromGitHub
    , buildGoModule  # or rustPlatform, python3Packages, etc.
    }:
    
    buildGoModule rec {
      pname = "mypackage";
      version = "1.0.0";
    
      src = fetchFromGitHub {
        owner = "owner";
        repo = "repo";
        rev = "v${version}";
        hash = "sha256-...";
      };
    
      vendorHash = "sha256-...";
    
      meta = with lib; {
        description = "Package description";
        homepage = "https://example.com";
        license = licenses.mit;
        maintainers = with maintainers; [ ];
        platforms = platforms.linux;
      };
    }
    

    Using Overlays

    # overlays/default.nix
    { inputs }:
    {
      additions = final: _prev: import ../pkgs { pkgs = final; };
    
      modifications = final: prev: {
        # Override existing packages
        somepackage = prev.somepackage.overrideAttrs (old: {
          version = "custom";
        });
      };
    }
    

    Flake Management

    Essential Commands

    # Lock dependencies
    nix flake lock
    
    # Update all inputs
    nix flake update
    
    # Update specific input
    nix flake update nixpkgs
    
    # Check flake validity
    nix flake check
    
    # Show flake outputs
    nix flake show
    
    # Show flake metadata
    nix flake metadata
    

    Flake Structure

    {
      description = "Flake description";
    
      inputs = {
        nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
      };
    
      outputs = { self, nixpkgs }: {
        nixosConfigurations = { ... };
        homeConfigurations = { ... };
        packages = { ... };
        devShells = { ... };
      };
    }
    

    Home-Manager Patterns

    Environment Variables

    home.sessionVariables = {
      EDITOR = "vim";
      VISUAL = "vim";
      BROWSER = "firefox";
    };
    

    XDG Config Files

    # Symlink static files
    xdg.configFile."myapp/config.yml".source = ./myapp-config.yml;
    
    # Generate files dynamically
    xdg.configFile."myapp/generated.conf".text = ''
      setting1 = ${someValue}
      setting2 = value2
    '';
    
    # Make executable
    xdg.configFile."bin/script.sh" = {
      source = ./script.sh;
      executable = true;
    };
    

    Services

    # User-level systemd service
    systemd.user.services.myservice = {
      Unit = {
        Description = "My Service";
        After = [ "network.target" ];
      };
    
      Service = {
        ExecStart = "${pkgs.mypackage}/bin/myservice";
        Restart = "on-failure";
      };
    
      Install = {
        WantedBy = [ "default.target" ];
      };
    };
    

    Secrets Management with agenix

    Define Secrets

    # secrets.nix
    let
      user = "ssh-ed25519 AAAAC3...";
      system = "ssh-ed25519 AAAAC3...";
    in {
      "secret.age".publicKeys = [ user system ];
    }
    

    Use Secrets in Configuration

    {
      age.secrets.mySecret = {
        file = ../secrets/mySecret.age;
        owner = "myuser";
        group = "mygroup";
      };
    
      # Reference in config
      services.myservice.passwordFile = config.age.secrets.mySecret.path;
    }
    

    Encrypt Secrets

    # Encrypt a secret
    agenix -e secrets/mySecret.age
    
    # Re-key all secrets
    agenix -r
    

    Safety and Testing

    Build Without Switching

    # Build configuration
    nixos-rebuild build --flake .#<hostname>
    
    # Dry run (show what would change)
    nixos-rebuild dry-build --flake .#<hostname>
    
    # Test without adding to bootloader
    nixos-rebuild test --flake .#<hostname>
    

    Rollback Strategy

    # List generations
    nixos-rebuild list-generations
    
    # Rollback to previous generation
    nixos-rebuild switch --rollback
    
    # Switch to specific generation
    nixos-rebuild switch --switch-generation <number>
    

    Keep Old Generations

    • Never delete all old generations
    • Keep at least 2-3 recent generations for rollback
    • Clean periodically with: nix-collect-garbage -d

    Common Patterns

    Conditional Imports

    imports = [
      ./base.nix
    ] ++ lib.optionals (desktop != null) [
      ./desktop/${desktop}
    ];
    

    String Interpolation

    # Simple
    message = "Hello ${name}";
    
    # Multi-line
    config = ''
      setting1 = ${value1}
      setting2 = ${value2}
    '';
    
    # Escape $
    script = ''
      echo "Nix variable: ${nixVar}"
      echo "Shell variable: ''${shellVar}"
    '';
    

    List Operations

    # Concatenation
    all = list1 ++ list2;
    
    # Filter
    filtered = lib.filter (x: x > 5) list;
    
    # Map
    doubled = map (x: x * 2) list;
    

    Attribute Set Operations

    # Merge
    merged = set1 // set2;
    
    # Recursive merge
    merged = lib.recursiveUpdate set1 set2;
    
    # Filter attributes
    filtered = lib.filterAttrs (n: v: v != null) attrs;
    
    # Map attributes
    mapped = lib.mapAttrs (n: v: v * 2) attrs;
    

    Debugging

    Print Values

    # Use lib.traceVal for debugging
    value = lib.traceVal someExpression;
    
    # Trace with message
    value = lib.traceValSeq "message" someExpression;
    

    Evaluate Expressions

    # Evaluate Nix expression
    nix eval .#nixosConfigurations.hostname.config.services.nginx.enable
    
    # Show derivation
    nix show-derivation .#package
    
    # Inspect store path
    nix path-info .#package
    

    Common Issues

    Hash Mismatch

    # Update hash for fetchFromGitHub
    nix-prefetch-github owner repo --rev <commit-hash>
    
    # Update vendor hash for Go modules
    # Set vendorHash = lib.fakeSha256;
    # Build will fail with correct hash
    

    Import Cycles

    • Check for circular imports
    • Use lib.mkIf to break cycles
    • Restructure module organization

    Performance

    Build Optimization

    • Use binary caches
    • Avoid rebuilding unnecessarily
    • Keep flake.lock updated but stable
    • Use nix-direnv for development shells

    Evaluation Speed

    • Minimize use of import
    • Use builtins wisely
    • Avoid expensive list operations in hot paths

    Security

    Security-First Approach

    NixOS provides unique security advantages through its declarative model and immutable store, but requires active hardening for production systems.

    Quick Security Wins

    {
      # 1. Enable firewall (default deny)
      networking.firewall.enable = true;
    
      # 2. Harden SSH
      services.openssh.settings = {
        PermitRootLogin = "no";
        PasswordAuthentication = false;
      };
    
      # 3. Automatic security updates
      system.autoUpgrade = {
        enable = true;
        allowReboot = false;
      };
    
      # 4. Enable AppArmor
      security.apparmor.enable = true;
    
      # 5. Use encrypted secrets
      age.secrets.mySecret.file = ../secrets/mySecret.age;
    }
    

    Hardened Profile

    For security-critical systems, use the hardened profile:

    imports = [
      <nixpkgs/nixos/modules/profiles/hardened.nix>
    ];
    

    See workflows/Security.md for comprehensive hardening guidance.

    Security Checklist

    • Firewall enabled with default deny
    • SSH hardened (no root, no passwords)
    • Secrets encrypted with agenix
    • Regular system updates configured
    • AppArmor or systemd service hardening enabled
    • Audit logging configured for critical services
    • Minimal package installation
    • Strong password policies enforced

    Resources

    • NixOS Manual: https://nixos.org/manual/nixos/stable/
    • Nix Package Manual: https://nixos.org/manual/nixpkgs/stable/
    • Home-Manager Manual: https://nix-community.github.io/home-manager/
    • Nix Pills: https://nixos.org/guides/nix-pills/

    Repository-Specific Patterns

    For ~/src/home Repository

    Adding a New Host

    1. Create /systems/<hostname> with boot.nix, hardware.nix
    2. Add to flake.nix using libx.mkHost
    3. Update globals.nix with machine metadata
    4. Add to secrets.nix if using secrets

    Adding a New Package

    1. Create /pkgs/<package-name>/default.nix
    2. Add to /pkgs/default.nix with callPackage
    3. Test with nix build .#<package-name>

    Common Commands

    • Build: make switch
    • Format: make fmt
    • Clean: make clean
    • Deploy: make host/<hostname>/switch (ask first!)

    Remember: Nix is about reproducibility and declarative configuration. When in doubt, consult the manuals and follow the patterns established in the repository.

    Examples

    Example 1: Creating a Nix package

    User: "Package this Go application for Nix"
    → Creates derivation with buildGoModule
    → Adds proper vendorHash for dependencies
    → Includes meta attributes (description, license, etc.)
    → Tests build with nix-build
    → Adds to home-manager or NixOS configuration
    → Result: Application properly packaged for Nix
    

    Example 2: Debugging Nix build issues

    User: "My Nix build is failing, can you help?"
    → Reviews error message from nix-build
    → Checks for common issues (missing dependencies, wrong hash)
    → Uses nix-shell for interactive debugging
    → Tests fix incrementally
    → Updates derivation with correct values
    → Result: Build succeeds, issue resolved
    

    Example 3: Using Nix flakes

    User: "Convert this to use flakes"
    → Creates flake.nix with inputs and outputs
    → Migrates configuration to flake structure
    → Updates flake.lock with nix flake update
    → Tests with nix build or nix develop
    → Documents flake usage in README
    → Result: Modern Nix flake structure
    
    Recommended Servers
    Thoughtbox
    Thoughtbox
    Local Model Suitability MCP
    Local Model Suitability MCP
    OrgX
    OrgX
    Repository
    natea/nixos-config
    Files