nix-patterns

star 21

Nix flakes, derivations, overlays, home-manager, devShells, and nixpkgs patterns for reproducible system configuration and development environments.

kpango By kpango schedule Updated 6/11/2026

name: nix-patterns description: Nix flakes, derivations, overlays, home-manager, devShells, and nixpkgs patterns for reproducible system configuration and development environments. trigger: /nix-patterns

Nix Patterns

Core Principles

  • Flakes are the standard — avoid legacy nix-env / default.nix entry points
  • Inputs are pinned; update with nix flake update
  • nixpkgs.follows prevents input duplication across flake inputs
  • Home-manager manages per-user state; NixOS/nix-darwin manage system state

Flake Structure

{
  description = "kpango dotfiles";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    home-manager = {
      url = "github:nix-community/home-manager";
      inputs.nixpkgs.follows = "nixpkgs";  # avoids duplicate nixpkgs
    };
  };

  outputs = { self, nixpkgs, home-manager, ... }@inputs: {
    homeConfigurations."kpango" = home-manager.lib.homeManagerConfiguration {
      pkgs = nixpkgs.legacyPackages.x86_64-linux;
      modules = [ ./home.nix ];
    };

    devShells.x86_64-linux.default = nixpkgs.legacyPackages.x86_64-linux.mkShell {
      packages = with nixpkgs.legacyPackages.x86_64-linux; [ go rustup buf ];
    };
  };
}

Derivations

# stdenv.mkDerivation for C/Go/Rust packages
{ lib, stdenv, fetchFromGitHub, go }:
stdenv.mkDerivation rec {
  pname = "myapp";
  version = "1.0.0";

  src = fetchFromGitHub {
    owner = "kpango";
    repo = pname;
    rev = "v${version}";
    hash = "sha256-AAAA...";  # leave empty to get hash error with correct value
  };

  nativeBuildInputs = [ go ];  # build-time only
  buildInputs = [];             # runtime deps

  buildPhase = "go build -o $out/bin/${pname} ./...";
  installPhase = "true";

  meta.license = lib.licenses.asl20;
}

# buildGoModule for Go projects
{ buildGoModule, fetchFromGitHub }:
buildGoModule {
  pname = "myapp";
  version = "1.0.0";
  src = fetchFromGitHub { ... };
  vendorHash = "sha256-...";  # null if not vendored
}

Overlays

# Overlay: add or override packages
overlays.default = final: prev: {
  myapp = final.callPackage ./pkgs/myapp.nix {};

  # Override existing package
  go = prev.go.overrideAttrs (old: {
    version = "1.23.0";
    src = prev.fetchurl { url = "..."; hash = "..."; };
  });
};

# Apply overlay in flake outputs
pkgs = import nixpkgs {
  inherit system;
  overlays = [ self.overlays.default ];
};

Home Manager

# home.nix
{ pkgs, config, ... }: {
  home.username = "kpango";
  home.homeDirectory = "/home/kpango";
  home.stateVersion = "24.11";  # don't change after initial setup

  home.packages = with pkgs; [ ripgrep fd fzf jq ];

  # Managed config file (immutable — symlinked from /nix/store)
  xdg.configFile."helix/config.toml".source = ./helix/config.toml;

  programs.git = {
    enable = true;
    userName = "kpango";
    userEmail = "yusukato@lycorp.co.jp";
    extraConfig.push.autoSetupRemote = true;
  };
}

devShells

devShells.default = pkgs.mkShell {
  packages = with pkgs; [
    go gopls golangci-lint
    rustup rust-analyzer
    buf protobuf
    kubectl helm
  ];

  shellHook = ''
    export GOPATH=$HOME/go
    export PATH=$GOPATH/bin:$PATH
  '';

  CGO_ENABLED = "0";
};

Common Commands

nix flake update                        # update all inputs
nix flake update nixpkgs               # update single input
nix build .#myapp                      # build flake output
nix develop                            # enter devShell
nix develop --command zsh              # enter with specific shell
home-manager switch --flake .#kpango   # apply home config
nix store gc                           # garbage collect old generations
nix flake check                        # validate flake outputs
nix search nixpkgs#<name>              # search packages

Arch Linux + Nix Coexistence

# On Arch: install Nix (not NixOS) via the Determinate installer
# /nix/store is the store; system packages still come from pacman

# Use home-manager only — no system-level changes
# Don't manage /etc/ or systemd system units — only ~/. paths
# Prefer home.packages over system packages to avoid pacman conflicts

Anti-Patterns

  • Don't use with pkgs; at top-level (pollutes scope, harder to grep)
  • Don't pin home.stateVersion to a version you've never bootstrapped
  • Don't mix flakes and non-flake inputs without flake = false
  • Don't use builtins.fetchTarball in flakes — use fetchFromGitHub with a hash
Install via CLI
npx skills add https://github.com/kpango/dotfiles --skill nix-patterns
Repository Details
star Stars 21
call_split Forks 7
navigation Branch main
article Path SKILL.md
More from Creator