Chapter 08

Home Manager 用户环境管理

用 Nix 声明式管理你的 dotfiles——Git、Shell、编辑器、终端配置一键同步到任何机器

Home Manager 简介

Home Manager 将 NixOS 模块系统的理念应用到用户级配置管理:用 Nix 声明你想要的 dotfiles 和用户级软件,Home Manager 负责生成实际的配置文件并管理它们的生命周期。

核心价值
将散落在 ~/.gitconfig、~/.zshrc、~/.config/nvim/ 等各处的配置文件统一用 Nix 语言描述,纳入版本控制,跨机器一键同步。新机器只需运行 home-manager switch 即可重现完整用户环境。
两种使用模式
Standalone 模式:独立安装,适用于任何有 Nix 的系统(macOS、非 NixOS Linux)。② NixOS 模块集成:作为 NixOS 模块使用,在 configuration.nix 或 flake.nix 中配置。

安装 Home Manager(Standalone + Flakes)

# 创建 flake.nix 来管理 Home Manager
mkdir -p ~/.config/home-manager
cd ~/.config/home-manager
# ~/.config/home-manager/flake.nix
{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
    home-manager = {
      url = "github:nix-community/home-manager";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = { nixpkgs, home-manager, ... }:
    let
      system = "x86_64-linux";   # 或 "aarch64-darwin" for Apple Silicon
      pkgs = nixpkgs.legacyPackages.${system};
    in {
      homeConfigurations."alice" =
        home-manager.lib.homeManagerConfiguration {
          inherit pkgs;
          modules = [ ./home.nix ];
        };
    };
}
# 首次激活
nix run home-manager -- switch --flake ~/.config/home-manager#alice

# 之后使用
home-manager switch --flake ~/.config/home-manager#alice

# 或者用 .envrc + direnv 简化
alias hms='home-manager switch --flake ~/.config/home-manager#alice'

home.nix 基础结构

# ~/.config/home-manager/home.nix
{ config, pkgs, ... }:

{
  # 必填:用户名和 HOME 目录
  home.username = "alice";
  home.homeDirectory = "/home/alice";   # macOS: "/Users/alice"
  home.stateVersion = "24.05";   # 不要随意修改

  # 用户级包(安装到 ~/.nix-profile/)
  home.packages = with pkgs; [
    ripgrep
    fd
    bat
    eza
    delta
    fzf
    jq
    httpie
    gh            # GitHub CLI
  ];

  # 让 Home Manager 管理自身
  programs.home-manager.enable = true;
}

程序配置:programs.*

Git 配置

  programs.git = {
    enable = true;
    userName = "Alice";
    userEmail = "alice@example.com";

    signing = {
      key = "~/.ssh/id_ed25519.pub";
      signByDefault = true;    # 默认签名所有 commit(SSH 签名)
    };

    aliases = {
      st = "status -sb";
      lg = "log --oneline --graph --decorate";
      co = "checkout";
      br = "branch";
      undo = "reset --soft HEAD~1";
    };

    extraConfig = {
      init.defaultBranch = "main";
      pull.rebase = true;
      push.autoSetupRemote = true;
      core.pager = "delta";    # 使用 delta 显示 diff
      delta = {
        navigate = true;
        light = false;
        side-by-side = true;
      };
    };
  };

Zsh 配置

  programs.zsh = {
    enable = true;
    enableCompletion = true;
    enableAutosuggestions = true;
    syntaxHighlighting.enable = true;

    # oh-my-zsh(可选)
    oh-my-zsh = {
      enable = true;
      plugins = [ "git" "fzf" "docker" ];
      theme = "robbyrussell";
    };

    # ~/.zshrc 额外内容
    initExtra = ''
      export EDITOR=nvim
      export VISUAL=nvim
      alias ll="eza -la --icons"
      alias cat="bat --style=plain"
      alias find="fd"
      # fzf 集成
      source ${pkgs.fzf}/share/fzf/completion.zsh
      source ${pkgs.fzf}/share/fzf/key-bindings.zsh
    '';

    # 历史设置
    history = {
      size = 50000;
      save = 50000;
      ignoreDups = true;
      share = true;
    };
  };

Neovim 配置

  programs.neovim = {
    enable = true;
    defaultEditor = true;

    # 插件(用 Nix 管理)
    plugins = with pkgs.vimPlugins; [
      nvim-treesitter
      nvim-lspconfig
      telescope-nvim
      neo-tree-nvim
      catppuccin-nvim
    ];

    # 基础 Lua 配置(extraConfig 用于 Vimscript)
    extraLuaConfig = ''
      vim.opt.number = true
      vim.opt.relativenumber = true
      vim.opt.tabstop = 2
      vim.opt.shiftwidth = 2
      vim.opt.expandtab = true
      vim.cmd.colorscheme("catppuccin")
    '';
  };

  # Neovim 需要的外部工具(LSP、formatter 等)
  home.packages = with pkgs; [
    nil             # Nix LSP
    nixpkgs-fmt     # Nix 格式化
    rust-analyzer   # Rust LSP
    nodePackages.typescript-language-server
  ];

Tmux 配置

  programs.tmux = {
    enable = true;
    terminal = "screen-256color";
    historyLimit = 100000;
    keyMode = "vi";
    prefix = "C-a";     # 将前缀键改为 Ctrl+a

    plugins = with pkgs.tmuxPlugins; [
      catppuccin           # 主题
      vim-tmux-navigator  # 与 Neovim 面板导航集成
      yank                 # 系统剪切板集成
    ];

    extraConfig = ''
      set -g mouse on
      bind-key -T copy-mode-vi v send-keys -X begin-selection
      bind | split-window -h -c "#{pane_current_path}"
      bind - split-window -v -c "#{pane_current_path}"
    '';
  };

文件管理

  # 直接管理配置文件(home.file)
  home.file = {
    # 将 Nix store 中的文件链接到 HOME 目录
    ".npmrc".text = ''
      prefix=~/.npm-global
    '';

    ".config/starship.toml".source = ./starship.toml;   # 链接到本地文件
  };

  # XDG 配置目录(xdg.configFile)
  xdg.configFile = {
    "wezterm/wezterm.lua".text = ''
      local wezterm = require 'wezterm'
      return {
        font = wezterm.font 'JetBrains Mono',
        color_scheme = 'Catppuccin Mocha',
      }
    '';
  };

  # direnv 集成
  programs.direnv = {
    enable = true;
    nix-direnv.enable = true;  # 自动启用 nix-direnv 缓存
  };
查找 Home Manager 支持的选项

Home Manager 提供了大量 programs.* 模块(git、zsh、fish、bash、tmux、neovim、alacritty、wezterm、vscode 等)。查看完整选项列表:

本章小结

Home Manager 让 dotfiles 管理从"手动维护散落文件"升级为"声明式版本控制的配置"。programs.* 模块提供了类型安全的高级接口,home.filexdg.configFile 处理没有专用模块的配置。将 home.nix 纳入 Git 仓库,新机器上的完整用户环境配置就变成了一条命令的事情。