Home Manager 用户级配置

Home Manager 将 Nix 的声明式配置管理从系统级延伸到用户级。本文详解 home.nix 结构、用户包管理、dotfiles 管理、与 NixOS 的协同以及多主机配置复用。

1. Home Manager 的定位

Home Manager 是 Nix 生态系统中管理用户级配置的利器。它填补了 NixOS 系统级配置管理的一个空白——普通用户的个人环境配置。

解决的问题:

  • dotfiles 管理:~/.bashrc、~/.vimrc、~/.config/ 等配置文件散落各处,换机器或重装时需要数小时重新配置
  • 用户级包管理:不需要 root 权限就能安装和管理个人工具
  • 跨发行版一致:无论在使用 Ubuntu、macOS、Arch 还是 NixOS,个人环境可以完全一致
  • 版本控制:所有配置以代码形式存储,变更可追溯、可回滚

Home Manager 与 NixOS 的关系是互补的:NixOS 管理整个系统(系统服务、网络、硬件),Home Manager 管理用户个人环境(Shell 配置、编辑器设置、用户级包)。在 NixOS 上两者可以协同工作,在非 NixOS(如 Ubuntu 或 macOS)上 Home Manager 可以独立运行。

2. 安装方式

2.1 独立安装(任何 Linux /macOS)

# 添加 Home Manager 通道(不使用 Flakes)
nix-channel --add https://github.com/nix-community/home-manager/archive/master.tar.gz home-manager
nix-channel --update

# 安装
nix-shell '<home-manager>' -A install

2.2 作为 NixOS 模块

# /etc/nixos/configuration.nix
{ config, pkgs, ... }:

{
  imports = [
    <home-manager/nixos>  # 导入 Home Manager NixOS 模块
  ];

  # 在 NixOS 配置中直接定义用户配置
  home-manager.users.alice = { pkgs, ... }: {
    home.packages = with pkgs; [ vim git ];
    programs.bash.enable = true;
  };
}

2.3 作为 Flake

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

  outputs = { self, nixpkgs, home-manager }:
    let
      system = "x86_64-linux";
      pkgs = nixpkgs.legacyPackages.${system};
    in
    {
      homeConfigurations.alice = home-manager.lib.homeManagerConfiguration {
        inherit pkgs;
        modules = [ ./home.nix ];
      };
    };
}

3. home.nix 基础结构

3.1 最小配置

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

{
  # 用户信息(必填)
  home.username = "alice";
  home.homeDirectory = "/home/alice";

  # 用户级包
  home.packages = with pkgs; [
    htop
    jq
    fzf
    ripgrep
    fd
    tree
  ];

  # 程序配置
  programs.git = {
    enable = true;
    userName = "Alice";
    userEmail = "alice@example.com";
    extraConfig = {
      init.defaultBranch = "main";
      push.autoSetupRemote = true;
    };
  };

  programs.bash = {
    enable = true;
    shellAliases = {
      ll = "ls -la";
      ".." = "cd ..";
      gs = "git status";
    };
    bashrcExtra = ''
      export PATH=$HOME/.local/bin:$PATH
    '';
  };

  # 状态版本(不要修改!)
  home.stateVersion = "24.05";
}

3.2 激活配置

# Flakes 方式
home-manager switch --flake ~/.config/home-manager#alice

# 传统方式
home-manager switch

# 测试配置(不实际应用)
home-manager build

# 查看当前配置
home-manager generations
home-manager news

4. 用户级程序配置

4.1 Shell 配置

{
  programs.bash = {
    enable = true;
    historyFileSize = 100000;
    historySize = 10000;
    shellAliases = {
      ll = "ls -la";
      ".." = "cd ..";
      "..." = "cd ../..";
      gs = "git status";
      gc = "git commit";
      gp = "git push";
    };
    bashrcExtra = ''
      # 自定义 PS1
      PS1='\n\[\033[1;32m\][\u@\h]\[\033[0m\] \[\033[1;34m\]\w\[\033[0m\] \n\$ '
      
      # 启用 fzf 补全
      eval "$(fzf --bash)"
    '';
  };

  # 或使用 Zsh
  programs.zsh = {
    enable = true;
    enableCompletion = true;
    autosuggestion.enable = true;
    syntaxHighlighting.enable = true;
    
    oh-my-zsh = {
      enable = true;
      theme = "robbyrussell";
      plugins = [ "git" "docker" "kubectl" "fzf" ];
    };
    
    shellAliases = {
      ll = "ls -la";
      gs = "git status";
    };
  };
}

4.2 编辑器配置

{
  # Vim 配置
  programs.vim = {
    enable = true;
    plugins = with pkgs.vimPlugins; [ vim-airline nerdtree ];
    settings = {
      number = true;
      relativenumber = true;
      tabstop = 2;
      shiftwidth = 2;
    };
    extraConfig = ''
      syntax on
      set hlsearch
      set ignorecase
      set smartcase
    '';
  };

  # Neovim 配置(通过外部文件)
  programs.neovim = {
    enable = true;
    defaultEditor = true;
    
    plugins = with pkgs.vimPlugins; [
      nvim-treesitter
      nvim-lspconfig
      telescope-nvim
    ];
    
    extraConfig = builtins.readFile ./nvim/init.vim;
  };

  # VS Code
  programs.vscode = {
    enable = true;
    extensions = with pkgs.vscode-extensions; [
      bbenoist.nix
      ms-python.python
      rust-lang.rust-analyzer
    ];
    userSettings = {
      "editor.fontSize" = 14;
      "editor.tabSize" = 2;
      "editor.wordWrap" = "on";
    };
  };
}

4.3 Git 配置

{
  programs.git = {
    enable = true;
    package = pkgs.gitAndTools.gitFull;
    
    userName = "Alice";
    userEmail = "alice@example.com";
    
    extraConfig = {
      core.editor = "vim";
      init.defaultBranch = "main";
      push.autoSetupRemote = true;
      pull.rebase = true;
      
      # 颜色
      color.ui = true;
      
      # 别名
      alias.st = "status";
      alias.co = "checkout";
      alias.br = "branch";
      alias.ci = "commit";
      alias.lg = "log --oneline --graph --decorate";
    };
    
    # 忽略文件模板
    ignores = [
      "*.swp"
      "*.swo"
      ".DS_Store"
      "node_modules/"
      ".env"
    ];
    
    # delta:增强型 diff 查看器,提供更美观的差异输出,支持语法高亮和并排对比
    delta = {
      enable = true;
      options = {
        line-numbers = true;
        side-by-side = true;
        decorations = {
          commit-decoration-style = "bold yellow box ul";
          file-decoration-style = "none";
          file-style = "bold yellow ul";
        };
      };
    };
  };
}

4.4 终端与工具

{
  # Alacritty 终端
  programs.alacritty = {
    enable = true;
    settings = {
      window.opacity = 0.95;
      font.size = 13;
      font.normal.family = "Fira Code";
      colors.primary.background = "#1a1b26";
      colors.primary.foreground = "#c0caf5";
    };
  };

  # tmux
  programs.tmux = {
    enable = true;
    shortcut = "a";
    baseIndex = 1;
    newSession = true;
    plugins = with pkgs.tmuxPlugins; [ sensible resurrect continuum ];
    extraConfig = ''
      set -g mouse on
      set -g default-terminal "screen-256color"
    '';
  };

  # fzf
  programs.fzf = {
    enable = true;
    enableBashIntegration = true;
    enableZshIntegration = true;
    defaultOptions = [ "--height 40%" "--layout=reverse" "--border" ];
  };

  # direnv
  programs.direnv = {
    enable = true;
    nix-direnv.enable = true;
  };
}

5. Dotfiles 管理

Home Manager 最强大的功能之一是管理 dotfiles。它可以自动创建 ~/.config/、~/.bashrc、~/.ssh/config 等文件。

5.1 配置文件生成

{
  # 直接生成配置文件内容
  home.file."/.config/alacritty/alacritty.yml".text = ''
    window:
      opacity: 0.95
    font:
      size: 13
      normal:
        family: Fira Code
  '';

  # 从仓库中的文件复制
  home.file."/.ssh/config".source = ./ssh/config;
  home.file."/.config/git/ignore".source = ./gitignore;

  # 生成脚本
  home.file."/.local/bin/my-script" = {
    source = ./scripts/my-script;
    executable = true;
  };

  # 目录复制
  home.file."/.config/nvim" = {
    source = ./nvim;
    recursive = true;
  };
}

5.2 条件配置

{ config, pkgs, lib, ... }:

with lib;

{
  # 根据主机名加载不同配置
  home.file."/.config/machine-specific" = mkIf (config.home.username == "work") {
    text = "work-specific-config";
  };

  # 根据平台条件配置
  programs.bash.bashrcExtra = mkIf pkgs.stdenv.isDarwin ''
    export BASH_SILENCE_DEPRECATION_WARNING=1
    # macOS 特定配置
    export PATH="/opt/homebrew/bin:$PATH"
  '';

  # 根据是否存在某个包来配置
  programs.vim.extraConfig = mkIf config.programs.git.enable ''
    " Git integration
    set nobackup
    set nowritebackup
  '';
}

6. 与 NixOS 协同

6.1 NixOS + Home Manager 架构

系统级 (root)           用户级 (alice)
─────────────────────────────────────────
/etc/nixos/              ~/.config/home-manager/
├── configuration.nix    ├── flake.nix (可选)
├── hardware-*.nix       └── home.nix
└── flake.nix

NixOS 管理:              Home Manager 管理:
- 内核、驱动              - Shell 配置
- 系统服务                - 用户包
- 网络配置                - dotfiles
- 系统级包                - 编辑器配置
- 防火墙                  - Git 配置

6.2 NixOS 中使用 Home Manager 模块

# /etc/nixos/configuration.nix
{ config, pkgs, ... }:

{
  imports = [
    <home-manager/nixos>
  ];

  # 系统级配置
  networking.hostName = "my-laptop";
  boot.loader.systemd-boot.enable = true;

  # 用户配置(由 Home Manager 管理)
  home-manager.users.alice = { pkgs, ... }: {
    home.packages = with pkgs; [
      firefox
      vscode
      slack
    ];

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

    programs.bash = {
      enable = true;
      shellAliases = {
        ll = "ls -la";
      };
    };

    home.stateVersion = "24.05";
  };

  # 自动激活 home-manager 配置
  home-manager.useGlobalPkgs = true;
  home-manager.useUserPackages = true;
}

6.3 分离配置的好处

场景配置位置工具
系统级服务/etc/nixos/configuration.nixNixOS
用户个人偏好~/.config/home-manager/home.nixHome Manager
共享团队配置导入的模块两者

分离的好处:

  • 普通用户可以修改自己的配置而无需 sudo
  • 用户可以在不同机器上共享相同的 home.nix
  • 重装系统时,home 配置独立备份和恢复

7. 多主机配置复用

7.1 使用 Flakes 管理多主机

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

  outputs = { self, nixpkgs, home-manager }:
    let
      mkHome = { username, system, extraModules ? [] }:
        home-manager.lib.homeManagerConfiguration {
          pkgs = nixpkgs.legacyPackages.${system};
          modules = [
            ./home-common.nix          # 通用配置
            ./hosts/${username}.nix    # 主机特定配置
          ] ++ extraModules;
          extraSpecialArgs = { inherit username; };
        };
    in
    {
      homeConfigurations = {
        "alice@laptop" = mkHome {
          username = "alice";
          system = "x86_64-linux";
          extraModules = [ ./profiles/development.nix ];
        };
        
        "alice@desktop" = mkHome {
          username = "alice";
          system = "x86_64-linux";
          extraModules = [ ./profiles/gaming.nix ./profiles/development.nix ];
        };
        
        "alice@macbook" = mkHome {
          username = "alice";
          system = "aarch64-darwin";
          extraModules = [ ./profiles/development.nix ];
        };
      };
    };
}

7.2 激活不同主机配置

# 笔记本电脑
home-manager switch --flake ~/.config/home-manager#alice@laptop

# 台式机
home-manager switch --flake ~/.config/home-manager#alice@desktop

# MacBook
home-manager switch --flake ~/.config/home-manager#alice@macbook

8. 总结

Home Manager 将 Nix 的声明式配置优势延伸到了用户级环境:

能力Home Manager 方案传统方案
dotfiles 管理home.file 声明式生成手动复制、stow、chezmoi
用户包home.packagesbrew、apt、手动安装
编辑器配置programs.vim、programs.vscode手动编辑配置文件
配置版本控制Git 管理 home.nixGit 管理 dotfiles 仓库
跨平台一致性一份配置多处使用每个平台单独维护
可复现性完全可复现依赖手动步骤

对于已经在使用 Nix 的开发者,Home Manager 几乎是必选项。它不仅解决了 dotfiles 管理的长期痛点,还提供了一种优雅的方式来在多台机器之间同步开发环境——只需复制 flake.nix 和 home.nix,几秒钟后即可获得完全一致的开发体验。

Home Manager 的常见陷阱

PATH 污染:未正确隔离的 Home Manager 环境可能导致系统工具被用户包覆盖:

# 问题:用户的 git 优先于系统 git
$ which git
/home/user/.nix-profile/bin/git  # 可能版本与团队不一致

# 解决:使用 `home.sessionPath` 控制顺序
# 或明确指定 `programs.git.package` 版本

与系统包管理器冲突:同时使用 Home Manager 和 Homebrew 可能导致同一工具存在两个版本。建议:

  • macOS:完全切换到 Home Manager,移除 Homebrew
  • Linux:保留系统包管理器用于 GUI 应用,开发工具全部走 Home Manager

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「devops」更多文章

  1. 值班工程与告警疲劳治理
  2. 基础设施代码测试:Terratest、Kitchen 与 InSpec
  3. 发布列车与版本节奏治理