强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

GNU Guix 函数式包管理教程 / 第十章 Guix Home

第十章:Guix Home

10.1 Guix Home 概述

Guix Home 是 Guix 的用户环境管理器,它将声明式配置的理念从系统级别延伸到用户级别。通过 Guix Home,你可以声明式管理:

  • 用户安装的软件包
  • Shell 配置(Bash、Zsh)
  • Dotfiles(配置文件)
  • 用户级服务(GPG Agent、SSH Agent 等)
  • 桌面环境配置
Guix System → 系统级声明式管理
Guix Home  → 用户级声明式管理
两者结合   → 完全声明式的计算环境

10.1.1 传统 Dotfiles 管理的困境

问题说明
分散.bashrc.vimrc.gitconfig 等分布在各处
不可重现手动复制配置难以保证一致
难以回滚修改出错后需要手动恢复
跨机器同步需要自己编写同步脚本
依赖管理配置文件依赖的工具未声明

10.1.2 Guix Home 的解决方案

;; ~/.config/guix/home-configuration.scm
(home-environment
  (packages (list vim git htop))  ; 声明安装的包
  (services (list                  ; 声明配置的服务
    (service home-bash-service-type ...)
    (service home-gpg-agent-service-type ...))))

10.2 基本配置

10.2.1 创建初始配置

# 方法一:手动创建
mkdir -p ~/.config/guix

# 方法二:导入现有 dotfiles
guix home import ~/.config/guix/home-configuration.scm

10.2.2 最小配置示例

;; ~/.config/guix/home-configuration.scm
(use-modules (gnu home)
             (gnu packages)
             (gnu services)
             (gnu home services)
             (gnu home services shells))

(home-environment
  ;; 用户级软件包
  (packages (specifications->packages
              '("git"
                "vim"
                "htop"
                "tree"
                "curl"
                "openssh"
                "rsync")))

  ;; 用户服务
  (services
    (list
      ;; Bash 配置
      (service home-bash-service-type
        (home-bash-configuration
          (aliases
            '(("ll" . "ls -alh --color=auto")
              ("la" . "ls -A --color=auto")
              ("l" . "ls -CF")
              ("gs" . "git status")
              ("gd" . "git diff")
              ("gl" . "git log --oneline --graph")
              ("gp" . "git push")
              ("gpl" . "git pull")))

          (environment-variables
            '(("EDITOR" . "vim")
              ("VISUAL" . "vim")
              ("LANG" . "zh_CN.UTF-8")
              ("LC_ALL" . "zh_CN.UTF-8")
              ("PAGER" . "less")
              ("LESS" . "-R")))

          (bashrc
            (list (plain-file "custom-bashrc" "
# 自定义 Bash 配置
HISTSIZE=10000
HISTFILESIZE=20000
HISTCONTROL=ignoredups:erasedups

# 彩色提示符
PS1='\\[\\033[01;32m\\]\\u@\\h\\[\\033[00m\\]:\\[\\033[01;34m\\]\\w\\[\\033[00m\\]\\$ '

# 自定义函数
mkcd() { mkdir -p \"$1\" && cd \"$1\"; }
")))

          (bash-profile
            (list (plain-file "custom-profile" "
# 登录时执行
if [ -f ~/.bashrc ]; then
  source ~/.bashrc
fi
")))))))

10.2.3 部署配置

# 应用 Guix Home 配置
guix home reconfigure ~/.config/guix/home-configuration.scm

# 查看当前 generation
guix home generations

# 回滚
guix home roll-back

10.3 Shell 配置

10.3.1 Bash 配置

(service home-bash-service-type
  (home-bash-configuration
    ;; 别名
    (aliases
      '(("ll" . "ls -alh")
        ("update" . "guix pull && guix upgrade")))

    ;; 环境变量
    (environment-variables
      '(("EDITOR" . "vim")))

    ;; bashrc 片段
    (bashrc
      (list
        (plain-file "aliases" "
# 更多别名
alias grep='grep --color=auto'
alias df='df -h'
alias du='du -h'
")))

    ;; bash_profile 片段
    (bash-profile
      (list
        (plain-file "profile" "
# 本地 bin 目录
export PATH=\"$HOME/.local/bin:$PATH\"
")))

    ;; login 片段
    (bash-login
      (list
        (plain-file "login" "
# SSH Agent
eval $(ssh-agent -s)
")))))

10.3.2 Zsh 配置

(use-modules (gnu home services shells))

(service home-zsh-service-type
  (home-zsh-configuration
    ;; Zsh 别名
    (aliases
      '(("ll" . "ls -alh")
        ("gs" . "git status")))

    ;; 环境变量
    (environment-variables
      '(("EDITOR" . "vim")
        ("ZSH_THEME" . "robbyrussell")))

    ;; zshrc 片段
    (zshrc
      (list
        (plain-file "zshrc" "
# 插件
source ~/.zsh/zsh-autosuggestions/zsh-autosuggestions.zsh
source ~/.zsh/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh

# 历史设置
HISTSIZE=10000
SAVEHIST=10000
HISTFILE=~/.zsh_history
setopt SHARE_HISTORY
setopt HIST_IGNORE_DUPS
")))))

10.3.3 Fish 配置

(service home-fish-service-type
  (home-fish-configuration
    (aliases
      '(("ll" . "ls -alh")
        ("gs" . "git status")))
    (environment-variables
      '(("EDITOR" . "vim")))
    (config
      (list
        (plain-file "config.fish "
# Fish 配置
set -g fish_greeting ''
set -g theme_display_git yes
")))))

10.4 Git 配置

10.4.1 声明式 Git 配置

(use-modules (gnu home services version-control))

(service home-git-service-type
  (home-git-configuration
    (config
      `((user
          ((name . "Your Name")
           (email . "[email protected]")))
        (core
          ((editor . "vim")
           (autocrlf . "input")
           (pager . "less -R")))
        (color
          ((ui . "auto")))
        (alias
          ((st . "status")
           (ci . "commit")
           (co . "checkout")
           (br . "branch")
           (lg . "log --oneline --graph --decorate --all")))
        (pull
          ((rebase . "true")))
        (push
          ((default . "current")))
        (diff
          ((algorithm . "histogram")
           (colorMoved . "default")))
        (merge
          ((conflictstyle . "diff3")))
        (init
          ((defaultBranch . "main")))))))

10.4.2 多身份 Git 配置

(service home-git-service-type
  (home-git-configuration
    (config
      `((user
          ((name . "Your Name")
           (email . "[email protected]")))
        ;; 条件包含需要通过 extra-config 实现
        ))
    ;; 全局 gitignore
    (ignore
      '("*~"
        "*.swp"
        ".DS_Store"
        "node_modules/"
        "__pycache__/"
        "*.pyc"
        ".env"
        ".direnv/"))))

10.5 GPG 和 SSH Agent

10.5.1 GPG Agent 配置

(use-modules (gnu home services gnupg))

(service home-gpg-agent-service-type
  (home-gpg-agent-configuration
    ;; Pinentry 程序
    (pinentry-program
      (file-append pinentry-qt "/bin/pinentry-qt"))

    ;; SSH 支持(通过 GPG Agent 管理 SSH 密钥)
    (ssh-support? #t)

    ;; 缓存时间
    (default-cache-ttl 3600)      ; 1 小时
    (max-cache-ttl 86400)         ; 24 小时
    (default-cache-ttl-ssh 3600)
    (max-cache-ttl-ssh 86400)

    ;; 额外配置
    (extra-content "
# 允许循环输入密码
allow-loopback-pinentry
allow-emacs-pinentry
")))

10.5.2 SSH Agent 配置

(use-modules (gnu home services ssh))

(service home-ssh-agent-service-type
  (home-ssh-agent-configuration
    (extra-content "AddKeysToAgent yes")))

;; SSH 配置
(service home-ssh-service-type
  (home-ssh-configuration
    (hosts
      (list
        (ssh-host
          (host "github.com")
          (options '((hostname . "github.com")
                     (user . "git")
                     (identity-file . "~/.ssh/id_ed25519"))))
        (ssh-host
          (host "server")
          (options '((hostname . "192.168.1.100")
                     (user . "deploy")
                     (port . "2222")
                     (identity-file . "~/.ssh/id_ed25519_server"))))))))

10.6 用户级 Shepherd 服务

10.6.1 定义用户服务

(use-modules (gnu home services shepherd))

(service home-shepherd-service-type
  (home-shepherd-configuration
    (services
      (list
        ;; 定时同步文件
        (shepherd-service
          (provision '(file-sync))
          (requirement '(user-processes))
          (one-shot? #t)
          (start #~(lambda ()
                     (system* #$(file-append rsync "/bin/rsync")
                              "-avz" "--delete"
                              (string-append (getenv "HOME") "/documents/")
                              "backup-server:/backups/documents/")
                     #t))
          (documentation "Sync documents to backup server."))

        ;; 定时运行的垃圾回收提醒
        (shepherd-service
          (provision '(gc-reminder))
          (requirement '(user-processes))
          (one-shot? #t)
          (start #~(lambda ()
                     (let ((dead (car (scandir "/gnu/store" (lambda (f) #t)))))
                       (format #t "~%Run 'guix gc' to free disk space.~%"))
                     #t))
          (documentation "Remind user to run garbage collection."))

        ;; 后台文件监控服务
        (shepherd-service
          (provision '(file-watcher))
          (requirement '(user-processes))
          (one-shot? #f)
          (start #~(make-forkexec-constructor
                     (list #$(file-append inotify-tools "/bin/inotifywait")
                           "-m" "-r"
                           (string-append (getenv "HOME") "/watched-dir"))))
          (stop #~(make-kill-destructor))
          (documentation "Watch directory for changes."))))))

10.6.2 管理用户服务

# 查看用户服务状态
herd status

# 启动特定服务
herd start file-sync

# 停止服务
herd stop file-watcher

# 查看服务日志
herd log file-sync

10.7 桌面环境配置

10.7.1 声明式桌面配置

(use-modules (gnu home services desktop))

(service home-dbus-service-type)

(service home-pipewire-service-type
  (home-pipewire-configuration
    (enable-pulseaudio? #t)))

(service home-redshift-service-type
  (home-redshift-configuration
    (location-provider 'geoclue)
    (night-color-temperature 3500)))

10.7.2 Sway/Wayland 配置

(service home-sway-service-type
  (home-sway-configuration
    (config
      `((mod . "Mod4")
        (terminal . "alacritty")
        (menu . "wofi --show drun")
        (bars
          ((command . "waybar")))
        (input
          ((type:keyboard
             ((xkb_layout . "cn")))))
        (output
          (("*"
            ((bg . "~/wallpaper.jpg fill")))))))))

10.8 Manifest 与 Profile 管理

10.8.1 分组管理包

;; 定义不同用途的包组
(define %dev-packages
  (specifications->packages
    '("gcc-toolchain" "cmake" "gdb" "valgrind"
      "strace" "lldb")))

(define %python-packages
  (specifications->packages
    '("python" "python-pip" "python-virtualenv"
      "python-numpy" "python-pandas")))

(define %tools-packages
  (specifications->packages
    '("ripgrep" "fd" "bat" "exa" "fzf"
      "tmux" "jq" "yq")))

(home-environment
  (packages (append
              %dev-packages
              %python-packages
              %tools-packages
              (specifications->packages
                '("vim" "git" "htop" "curl"))))
  ;; ...)

10.9 跨机器同步

10.9.1 Git 管理的配置仓库

# 创建配置仓库
mkdir -p ~/src/dotfiles
cd ~/src/dotfiles
git init

# 将 Guix Home 配置放入仓库
cp ~/.config/guix/home-configuration.scm .

# 提交
git add home-configuration.scm
git commit -m "Initial Guix Home configuration"

# 推送到远程
git remote add origin [email protected]:user/dotfiles.git
git push -u origin main

10.9.2 在新机器上部署

# 克隆配置仓库
git clone [email protected]:user/dotfiles.git ~/src/dotfiles

# 应用配置
guix home reconfigure ~/src/dotfiles/home-configuration.scm

# 完成!所有包、配置、服务都已就绪

10.9.3 多机器配置管理

;; 根据主机名选择不同配置
(define %hostname
  (gethostname))

(define %base-packages
  (specifications->packages
    '("vim" "git" "htop" "curl" "openssh")))

(define %work-packages
  (specifications->packages
    '("slack" "zoom" "firefox")))

(define %home-packages
  (specifications->packages
    '("mpv" "gimp" "blender")))

(home-environment
  (packages (append
              %base-packages
              (cond
                ((string=? %hostname "work-laptop")
                 %work-packages)
                ((string=? %hostname "home-pc")
                 %home-packages)
                (else '()))))
  ;; ...)

10.10 Guix Home 迁移指南

10.10.1 从现有 Dotfiles 迁移

步骤 1:盘点现有配置

# 列出家目录下的 dotfiles
ls -la ~/.*rc ~/.*profile ~/.*config
find ~ -maxdepth 2 -name ".*" -type f | head -50

步骤 2:分类整理

类别文件Guix Home 对应
Shell.bashrc, .bash_profilehome-bash-service-type
Git.gitconfighome-git-service-type
GPG.gnupg/gpg-agent.confhome-gpg-agent-service-type
SSH.ssh/confighome-ssh-service-type
编辑器.vimrc, .emacs通过 packages 安装
终端.tmux.conf通过 packages + snippet

步骤 3:逐步迁移

;; 先迁移简单的配置
(home-environment
  (packages (list vim git htop))
  (services
    (list
      (service home-bash-service-type
        (home-bash-configuration
          ;; 从 .bashrc 迁移配置
          (bashrc (list (local-file "old-bashrc"))))))))

10.11 Guix Home 命令速查表

操作命令
应用配置guix home reconfigure config.scm
查看历史guix home generations
回滚guix home roll-back
切换版本guix home switch-generation N
删除旧版本guix home delete-generations
导入配置guix home import config.scm
构建(不应用)guix home build config.scm

10.12 总结

本章讲解了 Guix Home 的用户环境管理:

  1. 核心概念——声明式用户环境管理
  2. Shell 配置——Bash、Zsh、Fish 的声明式配置
  3. Git 配置——版本控制的声明式管理
  4. 安全工具——GPG 和 SSH Agent 配置
  5. 用户服务——用户级 Shepherd 服务
  6. 跨机器同步——通过 Git 管理配置
  7. 迁移指南——从传统 dotfiles 迁移到 Guix Home

下一章我们将学习 Docker 集成。


扩展阅读