ubuntu-bootstrap:实践指南

作者:袖梨 2026-10-02

实际看ubuntu-bootstrap,先要确认它的用途:Ubuntu 26.04 LTS 工作站引导程序与 Fluxion:apt/Docker/toolchains/flatpaks/GNOME。部署与运行环境里,权限、依赖和环境差异会放大维护成本。我会在非生产环境复现一次安装与运行,检查依赖锁定、权限边界、日志、回滚和资源消耗。它适合愿意维护环境并重视故障恢复的工程团队;采用前仍要看维护状态和试跑结果。

w0rxbend/ubuntu-bootstrap 项目截图 1

ubuntu 引导程序

此存储库使用 Ubuntu 26.04 LTS (“resolute”,GNOME 50,amd64)设置我的工作站 Fluxion 0.4.1 或更高版本(请参阅 Fluxion 版本)。

它移植了 Arch 和 Fedora 脚本 w0rxbend/system-bootstrap 到声明性通量配置文件。它还 重现了我在之前的工作站安装中手动安装的所有内容,如 bash 和 zsh 历史记录中所示, apt log, and the snap and flatpak lists. The same tools stay in charge of their own jobs:

  • dotbot (dotbot-go) 直接从原始存储库的实时克隆链接点文件 ~/.system-bootstrap(没有任何内容复制到此存储库中)。
  • nerd-fonts-installer 安装 Nerd 字体。
  • cargo-binstall 安装 Rust CLI 工具。
  • binstaller 将固定版本二进制文件安装在 ~/.apps 中。
  • SDKMAN、nvm、pyenv 和其他语言安装程序的工作方式与以前一样。

桌面是 Ubuntu 自己的 GNOME 会话(Ubuntu Dock、Yaru),带有 Fedora 风格的 Super+1..9 工作区和 Vicinae 启动器 Super+D。不包括平铺或 Arch 桌面设置中的任何内容(niri、DMS、sway、PaperWM、waybar 等), Docker CE 取代了 podman。代理技能位于每个编码代理都链接到的一个 git-tracked 文件夹中。 测试工具在生成的、不间断的配置文件副本上运行相同的编排。

内容

  • 快速入门
  • 首先在全新的Ubuntu上运行,一步一步
  • Fluxion版本
  • 工作原理
  • 布局
  • 模块
  • 库存充足
  • Docker 代替 podman
  • 带有 dotbot 的 Dotfiles
  • 代理技能
  • 狼蛛发射器
  • 测试
  • 添加或更改项目
  • 重运行和幂等性
  • 此处处理的 Fluxion 警告
  • 引导程序后的手动步骤
  • 可选模块
  • 没有移植,为什么
  • 更新中
  • 故障排除

快速启动

从 本地 GNOME 会话 在计算机本身的终端中执行此操作,而不是通过 SSH。系统扁平化 polkit 仅对活动本地会话授权安装,并且 gsettings 需要会话总线。

先决条件:

  • Ubuntu 26.04 LTS 桌面(“决心”),amd64,具有 sudo 权限的用户,网络访问权限。
  • git 和 curl(新的 Ubuntu 26.04 桌面两者都不附带)。
  • fluxion 0.4.1 或更高版本(请参阅 Fluxion 版本)。 bootstrap.sh 将版本安装到 ~/.local/bin 当它发现没有变化时,并且拒绝与较旧的变化一起申请。
  • 首次运行大约需要 10 GB 的可用磁盘和几个小时。
# 1. prerequisites
sudo apt update && sudo apt install -y git curl

# 2. clone to the expected path (the profiles hard-code repoDir=$HOME/.ubuntu-bootstrap)
git clone [email protected]:w0rxbend/ubuntu-bootstrap.git ~/.ubuntu-bootstrap
cd ~/.ubuntu-bootstrap

# 3. (optional) run a fluxion build of your own instead of the release bootstrap.sh installs.
#    fluxion-bin.local is git-ignored; bootstrap.sh, the tests and `just` all read it.
echo /path/to/fluxion > fluxion-bin.local     # later: just use-fluxion /path/to/fluxion

# 4. see what would happen (read-only, no sudo)
./bootstrap.sh --validate      # validate --strict + lint for every module
./bootstrap.sh --dry-run       # exact commands per module

# 5. run it. sudo asks for your password once, and the script keeps the ticket warm
./bootstrap.sh
# ... it stops at the `session` log-out checkpoint (exit 0, summary says "checkpoint (log out/in)").

# 6. log out and back in (or reboot), then finish:
cd ~/.ubuntu-bootstrap && ./bootstrap.sh              # converged: every module skips, no second log-out prompt
./bootstrap.sh --only post-checks                    # verification + reminders of the manual steps

dotfiles 模块克隆 w0rxbend/system-bootstrap 到 ~/.system-bootstrap 通过 https(不需要 SSH 密钥)并从那里链接共享点文件;它取代的任何东西 首先将$HOME备份到~/.ubuntu-bootstrap-backup/。

运行是无人值守的:bootstrap.sh 传递了 --no-tui,因此 Fluxion 打印普通输出而不是打开其 每个模块的全屏选择器。添加 --tui 以获取选择器(按 enter 启动,按 q 关闭 运行后的屏幕)。在选择器上按 q 会跳过该模块,并且 Fluxion 仍会退出 0,因此 摘要将其报告为 ok,即使没有运行任何内容。

fluxion doctor -c profiles/00-base.yaml(来自 fluxion-bin.local 的 Fluxion)以只读方式检查主机。上一个 新主机 doctor 失败 30-toolchains.yaml 的 cargo-binstall command not found 和 pipx 命令不 found for optional/gnome-extensions.yaml。两者均由同一运行的早期 phase/module 安装 (rust 阶段和 base),因此在第一次应用之前预计会出现这两次失败。

要应用单个模块或模块内的单个阶段,而不运行所有内容:

./bootstrap.sh --only docker                  # one module (wrapper: PATH, sudo keep-alive, summary)
./bootstrap.sh --only apps,docker             # several modules, in table order
# one phase, directly with fluxion (keep the module's state name; run `sudo -v` first; `fluxion` below means
# the build from fluxion-bin.local when there is one, e.g. alias fluxion="$(grep -v '^#' ~/.ubuntu-bootstrap/fluxion-bin.local | head -n1)"):
fluxion apply -c profiles/10-apps.yaml --profile apps --phase vscode --skip-already-installed
fluxion list -c profiles/10-apps.yaml         # phase and step names of a module
fluxion graph -c profiles/10-apps.yaml        # phase dependency graph (mermaid)

最后一个模块 (session) 更改您的组 (docker、libvirt、kvm) 和您的登录 shell。然后它停止 注销检查点:fluxion 退出 75,bootstrap.sh 在那里停止,打印要执行的操作并退出 0。阶段是 记录为已完成,因此下一次运行不会再次询问,并且 session 不会更改任何内容的运行(a 聚合主机(--re-probe)根本不会询问。重新登录还会加载 Vicinae GNOME Shell 扩展。退出 然后返回,或重新启动,然后运行:

cd ~/.ubuntu-bootstrap && ./bootstrap.sh --only post-checks

完整的演练,包括模块中途失败时该怎么做,是 首先在全新的 Ubuntu 上运行。

全新安装的完整运行需要一段时间。慢速部分是 TeX Live,大约 51 个 Flatpaks 和 22 个 snap,SDKMAN 候选者, Miniforge 和 Nerd 字体,总计约 1.5 GB。当一个模块失败时,脚本继续执行下一个模块 one 并在最后打印摘要。修复失败的内容并重新运行该模块 ./bootstrap.sh --only NAME.

bootstrap.sh 参考

./bootstrap.sh [--dry-run | --validate | --plan | --status | --failed | --list]
               [--only a,b | --from NAME] [--yes] [--tui] [--show-output] [--re-probe]
               [--test | --profiles-dir DIR] [--state-prefix P] [--report FILE]
旗帜 效果
(无) 按顺序为每个默认模块运行 fluxion apply --profile NAME --skip-already-installed --no-tui
--dry-run 运行 fluxion dry-run --no-tui:打印确切的命令并且不进行任何更改。没有须藤
--validate 在每个选定的模块上运行 fluxion validate --strict 和 fluxion lint
--plan 运行 fluxion plan --format tree
--status / --failed 运行 fluxion status --summary / --failed:只读实时探针
--list 列出模块及其文件
--only a,b 仅选择这些模块(默认或可选)。他们总是按表顺序运行
--from NAME 在 NAME 处恢复默认序列
--tui 为每个模块打开 Fluxion 的交互式 selector/TUI,而不是普通输出(仅适用)
--no-tui 默认;因兼容性而接受
--yes, --show-output, --re-probe 穿越到流变
--test 运行生成的测试配置文件(tests/generated/,首先重新生成),状态名称为 test-NAME。相同的编排,相同的模块;参见 测试
--profiles-dir DIR 从 DIR 而不是 profiles/ 读取每个模块的配置文件(相同的相对布局)
--state-prefix P 为 Fluxion 状态名称添加前缀(--test 使用 test-)
--report FILE 为每个模块附加一个制表符分隔行:名称、rc、结果、秒数和 Fluxion 的 Summary: 计数(正常、失败、跳过、将运行)

哪个fluxion运行在一个地方决定,scripts/lib/fluxion-bin.sh,由bootstrap.sh共享, tests/run-tests.sh、scripts/validate-all.sh 和 Justfile:设置时为 $FLUXION_BIN,否则为路径中的路径 git-ignored fluxion-bin.local (just use-fluxion PATH writes it), else fluxion on PATH, else bootstrap.sh 安装 Fluxion 版本。因此,测试运行的二进制文件是真正引导程序运行的二进制文件。配置文件自己的 脚本通过导出的 FLUXION_BIN 获得相同的二进制文件。

在任何模块运行之前,脚本都会执行以下检查和设置步骤:

  • 它拒绝以 root 身份运行。
  • 如果存储库不在 ~/.ubuntu-bootstrap、如果您通过 SSH 连接或者主机不在 SSH,它会发出警告 Ubuntu 26.04“坚决”。
  • 它按照上面的方式解析流数并打印哪一个流数以及它来自哪里。在应用模式下它拒绝流变 早于 0.4.1(scripts/lib/fluxion-bin.sh 中的 FLUXION_MIN_VERSION,与 fluxion --version 相比) 并说明如何安装该版本。 FLUXION_ALLOW_UNPATCHED=1 将其变成警告;只读模式 只是警告。
  • 它导出 PATH,其中包括模块创建的每个工具位置:~/.cargo/bin、~/.local/bin、 ~/.go/bin、~/.apps/{dotbot,neovim,yq,helm,kustomize}/bin、~/.local/share/pnpm/bin 和 juliaup。
  • 它运行一次sudo -v(当sudo -n true已经工作时跳过,e.g。在NOPASSWD下,其中sudo -v可以 仍然要求输入密码),然后每 50 秒刷新一次票证,直到脚本退出。

每个模块在应用之前都会经过验证。退出代码为0表示一切成功或注销 已达到检查点,当任何模块失败时为 1。

该脚本永远不会看到您的密码。 sudo 直接提示,fluxion 只调用 sudo -n。

just 快捷键

just 由 toolchains 模块安装,因此仅在首次运行后可用。

食谱 跑步
just bootstrap / just dry-run / just validate / just list 完整运行、空运行、scripts/validate-all.sh 和模块列表
just apply NAME ./bootstrap.sh --only NAME(NAME可以是a,b)
just from NAME 在 NAME 处恢复默认序列
just dry NAME / just plan NAME 试运行或计划一个模块
just status [a,b] / just failed [a,b] 实时探测摘要,或仅缺失和失败的项目
just state NAME / just state-reset NAME 显示或删除为模块记录的 Fluxion 状态
just use-fluxion PATH 写入 fluxion-bin.local (git-ignored),以便每个脚本运行该 Fluxion 构建,并检查它是否有修复
just dotfiles / just dotfiles-dry / just dotfiles-check scripts/dotfiles-link.sh:备份+重新链接所有内容、预览或验证每个链接
just dotfiles-pull scripts/system-bootstrap-sync.sh:克隆~/.system-bootstrap或快进
just skills scripts/link-skills.sh:将每个已安装的代理链接到共享技能文件夹
just test [ARGS] / just test-validate / just test-assert / just test-gen tests/run-tests.sh(所有阶段/只读验证+空运行/仅断言),重新生成tests/generated/
just vicinae ./bootstrap.sh --only vicinae
just update ~/system-update.sh(apt、snap、flatpak、rustup、SDKMAN、nvm、...)
just refresh-binaries / just refresh-fonts 重新运行 binstaller 阶段/四个 Nerd Font 阶段,无需 --skip-already-installed(请参阅 更新)
just obs / gnome-extensions / wallpapers / post-checks 可选模块

首先在新的 Ubuntu 上运行,一步一步

下面的一切都发生在机器本身上登录的 GNOME 会话内的终端中(不是通过 SSH): 系统 flatpak 安装仅由 polkit 授权用于活动本地会话,并且 gsettings 需要该会话 巴士。

  1. 基础工具和存储库。

    sudo apt update && sudo apt install -y git curl
    git clone [email protected]:w0rxbend/ubuntu-bootstrap.git ~/.ubuntu-bootstrap && cd ~/.ubuntu-bootstrap
    
  2. fluxion. 无需执行任何操作:./bootstrap.sh 将 FLUXION_VERSION (v0.4.1) 命名的版本安装到 ~/.local/bin 当它没有找到时。要手动安装它或替换旧的:

    curl --proto '=https' --tlsv1.2 -sSfL https://worxbend.github.io/fluxion.cr/install.sh | sh -s -- --version v0.4.1
    

    要运行您自己的构建(fluxion.cr 结账:来自 crystal 经典快照的 Crystal >= 1.21, 加上build-essential pkg-config libyaml-dev libssl-dev libpcre2-dev zlib1g-dev):

    cd ~/Projects/fluxion.cr && shards install && crystal build --release --no-debug src/main.cr -o bin/fluxion
    echo ~/Projects/fluxion.cr/bin/fluxion > ~/.ubuntu-bootstrap/fluxion-bin.local && cd ~/.ubuntu-bootstrap
    

    ./bootstrap.sh --validate 然后打印 using fluxion 0.4.1 (<path>, from fluxion-bin.local),并警告如果 构建版本早于回购需求。

  3. 预览(可选,只读): ./bootstrap.sh --validate 和 ./bootstrap.sh --dry-run。

  4. 运行默认序列: ./bootstrap.sh。 sudo 会询问您一次密码(在 NOPASSWD 下跳过)。的 十一个模块按顺序运行;失败的模块不会阻止其他模块,最后的摘要列出了每个模块 模块的结果。如果失败,请阅读 ./bootstrap.sh --failed --only NAME,修复原因,然后重新运行 (./bootstrap.sh --only NAME)或恢复序列(./bootstrap.sh --from NAME,其中失败 给您的消息名称)。已完成的项目会从记录状态中跳过,因此重新运行的成本很低。 Ctrl+C 是 也很安全:fluxion 记录其停止的位置,而 ./bootstrap.sh(或 --from NAME)继续进行。

  5. 注销提示。 最后一个模块 session 将 zsh 设置为您的登录 shell 并将您添加到 docker, libvirt 和 kvm,然后在检查点停止:fluxion 打印 需要重新启动,摘要显示 session ... 75 checkpoint (log out/in) 和 bootstrap.sh 退出 0 并运行下一个命令。 注销并 返回,或重新启动。 这将使组和登录 shell 生效并加载 Vicinae GNOME 扩展。

  6. 重新登录后恢复:

    cd ~/.ubuntu-bootstrap
    ./bootstrap.sh                      # optional: re-checks the whole sequence; everything is skipped, no new prompt
    ./bootstrap.sh --only post-checks   # docker without sudo, zsh, fonts, nvim, CLIs, Vicinae server + extension
    

    post-checks 还保留手动步骤的提醒(gh 登录、SSH 密钥、重复的 TG 平台 flatpak)。它 退出 1 并命名每一个,直到完成为止;这是预期的,请参阅 引导程序 之后的手动步骤。

  7. 可选模块(当您需要时):./bootstrap.sh --only obs,wallpapers,gnome-extensions。日志out/in 在 gnome-extensions 之后再次。

  8. 验证(可选): tests/run-tests.sh 来自 GNOME 会话运行整个套件(应用 + 幂等性 + 对测试配置文件的断言,加上仅生产状态);请参阅 测试。

流变版本

此仓库需要 fluxion 0.4.1 或更高版本(scripts/lib/fluxion-bin.sh 中的 FLUXION_MIN_VERSION;bootstrap.sh 并且测试拒绝应用于较旧的测试,FLUXION_ALLOW_UNPATCHED=1 覆盖)。 bootstrap.sh 安装 FLUXION_VERSION (v0.4.1) 当发现没有通量时;运行您自己的构建,just use-fluxion PATH(请参阅 首先运行)。

此存储库所需的修复是在 fluxion.cr 分支 fix/zorin-bootstrap 上编写的(以此存储库的 Zorin 命名) OS 起源)并在 fluxion 0.4.0 中发布 (worxbend/fluxion.cr#2):

提交 修复 为什么这个仓库需要它
d26a299, d6f0caf apt probe reads dpkg-query output correctly; a package held with apt-mark hold counts as installed 0.3.1 探测每个 apt 软件包都不存在,因此 status 是错误的,--re-probe 重新安装了约 200 个软件包
49aae0a, 95fe904 每个包列表一个 apt-get install,仅在失败时一一对应;不在 Ctrl+C 之后 200 个包阶段运行一个事务而不是 200 个事务
4c30b6d, 149f1d8 system-setting 项目和断言由 status 回答 base 时钟设置和每个 host-check 显示为未知
af2c932 每次运行时都会检查断言,从不信任状态 诸如 gnome-session-check 之类的守卫和重新运行的后检查
f992d37, 5d19083, c34113b, eded4b5 apt sources must match the declared line and keyring; a keyring must hold the declared fingerprint; gpg keys are read with a throwaway gpg home (fresh accounts have no ~/.gnupg) and an unusable TMPDIR fails one item instead of the run apps(claude-desktop、VS 代码、1Password、水晶钥匙)
9d7b731, 16712e6, 82f3e77 cargo crates and SDKMAN candidates have live probes toolchains --re-probe 下的幂等性
8065313, 953e35e binstaller 固定到 v0.5.0(读取 GNU @LongLink tar 条目) 否则,binaries 在 zig 0.15.2 上失败
9a77b8f 步骤的 probeCommand 每一步结算一次,而不是在每个项目之前结算 多脚本步骤 (vicinae) 跳过了后面的脚本
4254ceb, d699c4a prompt-logout 阶段被记录为已完成并退出 75,并且仅询问何时更改了某些内容 session:一次注销提示,不是每次运行一次; --re-probe 运行完成
7430ef4, 7e01f16 flatpak 探针看到扩展(运行时参考) obs 插件安装后显示不存在
bdf915b fluxion state forget 将配置文件作为位置参数 记录的 state forget 命令
241e8f1, 0da747d 每个文件的代码拆分为 500 行以下;记录的与 Java 规范的差异 上游卫生,无行为改变

fluxion 0.4.1(worxbend/fluxion.cr#3 及之后)添加了以下内容 第一次在Ubuntu 26.04上运行发现:

提交 修复 为什么这个仓库需要它
0fb69d5 特权命令可能是根拥有的符号链接到另一个根拥有的树 Ubuntu 26.04 将 coreutils 作为 Rust uutils 提供:/usr/bin/install 和 chown 链接到 /usr/lib/cargo/bin/coreutils,并且 0.4.0 拒绝它们(“无法从受信任的 root 拥有的系统目录中获取”),因此每个 apt-repository 步骤和特权文件写入都会失败
e88f6c0 声明的 probeCommand 类型 0.4.0 的答案给出了类型化探针 配置文件自己的探针仍然负责
8aa709f 报告每个批次的包裹;跨运行保留欠注销 正确的总结; session 中断运行后仍然询问
55ae3f7 等待另一个进程持有的包管理器锁(5 秒到 30 秒的暂停,最多 15 分钟) 新的桌面在安装后立即运行无人值守升级,这通常会在第一个 apt 阶段失败

要迁移到较新的版本:在 bootstrap.sh 中设置 FLUXION_VERSION,如果 repo 出现,则提高 FLUXION_MIN_VERSION 要依赖它,请安装它,并删除 fluxion-bin.local(如果它指向较旧的版本)。

它是如何运作的

Fluxion没有包含机制,因此每个模块都是profiles/中的完整、独立的WorkstationProfile。 bootstrap.sh 依次运行它们。每个模块都有自己的自己的状态名称(--profile base, --profile docker,...),因此其状态位于 ~/.local/share/fluxion/<name>.state.json 中。

以这种方式拆分设置会产生以下后果:

  • 每个模块都在一个新的 Fluxion 进程中运行。 Fluxion 在加载时读取 PATH 并仅评估 when: 一次。工具 因此,由早期模块(cargo-binstall、dotbot、broot、gext)安装的模块对于后续模块是可见的。
  • 模块可以自行重新运行、重置或调试。
  • 一个模块的故障不会阻塞其他模块。在模块内部,最有可能失败的列表(flatpaks、snap、 curl installers) sit in leaf phases that no other phase depends on.
  • 唯一的 prompt-logout 阶段位于最后一个模块 session 中,因此其他模块的空运行永远不会被切断 短。生成的测试配置文件完全放弃了它。
  • dotfiles 故意迟到。多个安装程序(pnpm、codex、kimi)将行附加到 ~/.zshrc。在它们后面运行 dotbot 意味着这些行落在一次性 oh-my-zsh 模板中(该模板受支持) 最多 ~/.ubuntu-bootstrap-backup/.zshrc),然后 dotbot 将其替换为以下链接 ~/.system-bootstrap/.files/.zshrc。如果 dotbot 首先运行,安装程序将编辑共享文件。

每个配置文件都以 host-check 开头,断言主机是 Ubuntu 26.04“坚决”,带有 apt-get,并且 声明 target.os ubuntu/resolute/26.04。配置文件不使用 when: {distribution: ubuntu}:每个配置文件都是 已经仅限 Ubuntu。

布局

~/.ubuntu-bootstrap/
├── README.md
├── Justfile                      # shortcuts (just is installed by `toolchains`)
├── bootstrap.sh                  # ordered runner: preflight, sudo keep-alive, summary (--test for the tests)
├── .gitignore  .editorconfig  .shellcheckrc
├── fluxion-bin.local             # git-ignored, optional: a fluxion build to run instead of the one on PATH
├── scripts/
│   ├── lib/fluxion-bin.sh        # the one fluxion resolver + minimum-version check (bootstrap, tests, just)
│   ├── validate-all.sh           # validate --strict + lint (prod + test profiles), bash -n + shellcheck
│   ├── system-bootstrap-sync.sh  # clone ~/.system-bootstrap (https) or fast-forward it; --check
│   ├── dotfiles-link.sh          # back up what is in the way, run dotbot for both configs; --check/--dry-run
│   └── link-skills.sh            # POSIX sh: <agent>/skills -> ~/.agents/skills for installed agents
├── profiles/
│   ├── 00-base.yaml              # base
│   ├── 10-apps.yaml              # apps
│   ├── 20-docker.yaml            # docker
│   ├── 30-toolchains.yaml        # toolchains
│   ├── 40-binaries.yaml          # binaries
│   ├── 50-shell.yaml             # shell
│   ├── 60-desktop-apps.yaml      # desktop-apps
│   ├── 70-gnome.yaml             # gnome
│   ├── 75-vicinae.yaml           # vicinae
│   ├── 80-dotfiles.yaml          # dotfiles
│   ├── 90-session.yaml           # session (log-out checkpoint)
│   └── optional/
│       ├── obs.yaml
│       ├── gnome-extensions.yaml
│       ├── wallpapers.yaml
│       └── post-checks.yaml
├── config/
│   ├── binstaller.yaml           # binstaller profile, an Ubuntu fork (also linked to ~/.config/binstaller/config.yaml)
│   └── nerd-fonts/
│       ├── 01-core.yaml  02-more.yaml  03-rest.yaml  04-noto.yaml   # batches fluxion uses; together they
│                                 # equal the clone's .config/nerd-fonts-installer/config.yaml (all 42 families)
├── dotfiles/                     # ONLY Ubuntu-specific files; shared dotfiles come from ~/.system-bootstrap
│   ├── system-bootstrap.conf.yaml  # dotbot config, base dir ~/.system-bootstrap/.files (the live clone)
│   ├── install.conf.yaml         # dotbot config, base dir dotfiles/ (the Ubuntu-only files below)
│   ├── custom.zsh                # -> ~/.custom.zsh, sourced by the shared .zshrc (Ubuntu PATH + ubuntu plugin)
│   ├── ubuntu-system-update.sh   # -> ~/system-update.sh
│   ├── .config/xdg-terminals.list  .config/environment.d/90-session.conf   # kitty as terminal, session env
│   └── agents/skills/            # the shared agent skills (README.md explains the layout)
└── tests/
    ├── gen-test-profiles.sh      # profiles/ -> tests/generated/ (halting steps removed)
    ├── run-tests.sh              # validate, apply, idempotency re-apply, assertions; --container
    ├── generated/                # git-ignored, regenerated before every use
    ├── assertions/               # lib.sh + one <module>.sh per module (the real post-conditions)
    ├── container/Dockerfile      # "fresh Ubuntu Desktop" image for --container (ubuntu:26.04 + baseline)
    ├── container/ubuntu-baseline.txt  # what that image adds: Ubuntu-Desktop-shipped CLI packages (+ git, curl), delta documented
    ├── lib/                      # generator, profile queries, inline-snippet extractor, dotfile-copy detector
    │                             # (find_copies.py), uinput key presser (python3 + PyYAML)
    └── logs/                     # git-ignored run logs

~/.system-bootstrap/              # live clone of github.com/w0rxbend/system-bootstrap (source of truth)
└── .files/                       # .zshrc, nvim, kitty.conf, .tmux.conf, starship, alacritty, .config/...

配置文件内的相对路径从配置文件自己的目录解析。这就是为什么 profiles/*.yaml 引用 ../config/... 和 profiles/optional/*.yaml 指 ../../...。

模块

默认序列(./bootstrap.sh):

# 模块 文件 它的作用
1 base profiles/00-base.yaml 修复损坏的 Crystal apt 源、apt full-upgrade、debconf 预置、大约 190 个 Ubuntu 存档包(CLI、构建、调试、GUI-dev、媒体、字体、TeX、桌面、虚拟化)、GPU 选择的工具lspci、libvirtd、全局 git 配置、NTP 时钟、bat 符号链接
2 apps profiles/10-apps.yaml 第三方应用程序:GitHub CLI、Claude Desktop、1Password(apt repos)、ChatGPT 和 fastfetch(.deb)、VS Code 和 Crystal(经典快照)
3 docker profiles/20-docker.yaml Docker CE、buildx 和来自 Docker apt 存储库的 compose 插件、docker/containerd 服务、distrobox
4 toolchains profiles/30-toolchains.yaml rustup, cargo-binstall and 14 crates, Go 1.27.1, SDKMAN and 8 candidates, nvm and Node LTS, pnpm, pyenv, poetry, uv, Miniforge, juliaup, kustomize, helm 4, dotenvx
5 binaries profiles/40-binaries.yaml binstaller配置文件(~/.apps中的13个工具),/usr/local/bin中的nvim/vim链接,4批Nerd字体
6 shell profiles/50-shell.yaml oh-my-zsh(固定)和 3 个插件,TPM、starship、kitty(上游构建、桌面集成、x-terminal-emulator 替代)、ghostty snap
7 desktop-apps profiles/60-desktop-apps.yaml flatpak 和 Flathub 遥控器、类别组中的 51 个 flatpaks、20 个快照、Claude Code、Codex 和 Kimi CLIs、Zed、Paseo
8 gnome profiles/70-gnome.yaml 9 个固定工作区、Super+N / Super+Shift+N 绑定、屏幕截图键、Ubuntu Dock 热键关闭、固定收藏夹
9 vicinae profiles/75-vicinae.yaml Vicinae 启动器(通过官方脚本将 AppImage 固定到 /usr/local 中)、其 systemd 用户服务、vicinae@dagimg-dot GNOME 扩展、Super+D 切换
10 dotfiles profiles/80-dotfiles.yaml Clones/fast-forwards ~/.system-bootstrap,备份阻碍的内容,链接两个 dotbot 配置(来自克隆的共享点文件、来自此存储库的仅 Ubuntu 文件和代理技能)、tmux 插件、broot 启动器
11 session profiles/90-session.yaml zsh 作为登录 shell,docker/libvirt/kvm 组,注销检查点

可选模块(./bootstrap.sh --only NAME):

模块 它的作用
obs OBS Studio 和 10 个 flatpak 插件(DroidCam、背景去除、VAAPI、PipeWire 视频、...)
gnome-extensions gext (pipx) 加上用户主题、电池指示器图标、通知图标、礼帽、空格键、AlphabeticalAppGrid,随 gext -F 一起安装(无 GNOME Shell 对话框)
wallpapers 将旧存储库中的壁纸稀疏克隆到 ~/.local/share/backgrounds/system-bootstrap(约 109 个 MB)
post-checks 重新登录后运行。检查 docker 组、docker run hello-world、zsh 登录 shell、字体、nvim、核心 CLIs、Vicinae 服务器应答且其扩展处于活动状态,然后提醒您手动步骤。在重新登录之前运行,仅对 docker-group、docker run 和扩展检查失败(--show-output 表示是否缺少日志 out/in)

库存齐全

配置文件具有每个项目的确切规格。本节是一个快速总结。

base :Ubuntu 存档

集团 套餐
核心 ca-certificates curl wget gnupg git zsh unzip zip xz-utils fontconfig fusion3 libfuse2t64 software-properties-common debconf-utils apt-transport-https pciutils python3-yaml(由点文件和测试脚本使用)
CLI alacritty bat btop fzf htop tmux wl-clipboard jq net-tools hyperfine asciinema gdu xsensors lm-sensors 应力 zoxy tig wev foot mtr nmap httpie ripgrep pipx stacer tree mediainfo libimage-exiftool-perl imagemagick poppler-utils ffmpegthumbnailer 7zip python3-venv python3-pip python3-dev
建造 build-essential gcc g++ pkg-config clang clangd clang-format clang-tidy clang-tools llvm llvm-dev libclang-dev libclang-rt-dev lld lldb make cmake meson ninja-build ccache flex bison gperf,加上 pyenv、Python、Rust 和 Crystal 构建所需的 -dev 库(readline、ffi、ssl、zlib、bz2、 sqlite3、lzma、tk、ncurses、xml2、xmlsec1、secret、yaml、gmp)和 dfu-util
调试 gdb valgrind strace ltrace linux-tools-common linux-tools-generic-hwe-26.04 tshark protobuf-编译器
GUI 开发者 GTK 3/4 和 GObject-introspection 开发包、WebKitGTK 6、X11/Xcursor/Xrandr/Xi/Xinerama 开发、Mesa/GL/EGL/GBM 开发、mesa-utils(无 mesa-vdpau-drivers:Mesa 25 已删除) VDPAU)
媒体 vlc mpv imv ffmpeg、libav* 开发包、GStreamer 插件集 (base/good/bad/ugly/libav/vaapi/pipewire)、libopenh264-8、VA-API(mesa-libgallium,在 26.04 上携带 Mesa 的 VA 驱动程序)、 libvdpau-va-gl1 和 vainfo、PipeWire 和wireplumber、easyeffects、power-profiles-daemon、upower、ubuntu-restricted-extras(EULA 预置)、v4l2loopback-dkms 和 HWE 标头
字体 / TeX 字体-firacode 字体-字体-真棒字体-noto-核心字体-noto-颜色-表情符号字体-roboto,texlive-base/latex-base/latex-recommended/fonts-recommended/xetex
桌面 gnome-tweaks、shell 扩展首选项和扩展、gnome-browser-connector、xdg-desktop-portal-gtk、gnome-keyring、libpam-gnome-keyring、seahorse、gcr、gcr4、zathura (+pdf-poppler)、mupdf
GPU(由 lspci,如旧脚本中所示) 当存在 AMD GPU 时为 radeontop,当存在 Intel GPU 时为 intel-media-va-driver (iHD VA-API);除此之外什么也没有
虚拟 qemu-system-x86 qemu-utils ovmf libvirt-daemon-system libvirt-clients virtinst virt-managerbridge-utils dnsmasq-base vde2 netcat-openbsd cpu-checker,加上 libvirtd.socket 启用并侦听(libvirtd.service 启用;它是套接字激活的,并在 120 后退出空闲)
配置 git user.email, user.name = w0rxbend, pull.rebase=true, init.defaultBranch=main, core.autocrlf=input; NTP on and RTC in UTC; ~/.local/bin/bat pointing to batcat

在任何东西运行 apt-get update 之前,apt-sources-repair 阶段将主机获得的损坏的水晶源移到一边 来自curl -fsSL https://crystal-lang.org/install.sh | sudo zsh (see Troubleshooting). It does 当文件不存在或正确时,什么也没有。

Debconf preseeds 首先运行:它们接受 mscorefonts EULA 并将wireshark 设置为 install-setuid=false。流变确实 未设置 DEBIAN_FRONTEND,因此如果没有预置,这些包可能会挂起等待答案。

apps :第三方应用程序(这些是在此主机上手动安装的)

应用程序 来源
gh cli.github.com/packages 存储库,钥匙圈 /etc/apt/keyrings/githubcli-archive-keyring.gpg(sha256 固定)
claude-desktop downloads.claude.ai/claude-desktop/apt/stable 存储库,钥匙圈 /usr/share/keyrings/claude-desktop-archive-keyring.gpg。它为其 VM 引入 qemu、ovmf 和 virtiofsd
code code经典snap(VS代码),由snapd刷新
1password 1 密码密钥(已固定指纹)和一个与软件包中写入的文件相同的 1password.sources 文件
ch@tgpt persistent.oaistatic.com 的最新 .deb。它的 postinst 添加了存储库和密钥环,因为没有公钥 URL
fastfetch fastfetch GitHub 版本中的最新 .deb(比 resolute archive 版本更新)
crystal crystal 经典快照(撰写本文时为 Crystal 1.21.1,带有 shards),由 snapd 刷新。切勿在其旁边安装 Ubuntu 的 crystal/shards apt 软件包:/usr/bin 位于 PATH 上的 /snap/bin 之前,因此它们会隐藏它

勇敢没有被感动。在此主机上,它是手动安装的 brave 管理单元。

claude-desktop 包的 postinst 会在每个 安装和升级。该文件是无害的。这里写的claude-desktop.list没有###管理的 克劳德桌面 package. marker, so the postinst leaves it alone and it keeps pointing at the dearmored .gpg。

docker

请参阅 Docker 而不是 podman。

toolchains :用户级,无sudo

工具 如何 哪里
铁锈 rustup (sha256-pinned script, --no-modify-path) ~/.cargo, ~/.rustup
cargo-binstall 固定的上游安装脚本 ~/.cargo/bin
板条箱(cargo-binstall) eza lsd fd-find bingrep hx just sd procs du-dust gping 树保姆-cli macchina 底部 broot ~/.cargo/bin
去1.27.1 官方 tarball,经过 sha256 检查 ~/.go, GOPATH=~/.go-workspace
SDKMAN get.sdkman.io(sha256 固定),使用 bash 运行,自动应答 ~/.sdkman
SDKMAN 候选人 java gradle maven sbt scala micronaut vertx VisualVM(最新默认值) ~/.sdkman/candidates
nvm 和节点 LTS nvm v0.40.7(sha256 固定),nvm install --lts,默认别名 lts/* ~/.nvm
pnpm get.pnpm.io (PNPM_HOME=~/.local/share/pnpm) ~/.local/share/pnpm/bin(pnpm 11+ 布局)
pyenv pyenv.run(sha256 引脚) ~/.pyenv
诗歌/紫外线 官方安装程序 ~/.local/bin
小型锻造厂 最新Miniforge3-Linux-x86_64.sh,批处理模式 ~/.miniforge3
朱利亚普 install.julialang.org(sha256 引脚) ~/.juliaup
定制/舵 4 上游安装脚本,无需 sudo(helm 的脚本需要其位于 PATH 上的目录,这是该步骤设置的) ~/.apps/{kustomize,helm}/bin
多特恩克斯 dotenvx.sh ~/.local/bin

hx 是 satkevij 的十六进制查看器,而不是 Helix。

binaries

  • binstaller(config/binstaller.yaml,模式developer,appsDir: ~/.apps):yazi v26.5.6,zig 0.15.2,minikube, xplr,种类 v0.31.0,zellij v0.44.1,kubectl(稳定),neovide(AppImage),neovim(最新),lazygit 0.61.0, jujutsu v0.40.0、dotbot v0.4.2 和 yq (mikefarah,新添加)。每个工具都有自己的 ~/.apps/<tool>/bin. 需要 binstaller >= v0.3.0。 Fluxion 0.3.1 固定 binstaller v0.2.0,并且该版本无法读取 GNU @LongLink tar 条目位于 zig-x86_64-linux-0.15.2.tar.xz 中,因此 binstaller 步骤在 zig 上失败。通量0.4.0 以及后来的引脚 v0.5.0(参见 Fluxion 版本)。 将 installerVersion 排除在配置文件之外:fluxion 仅接受其自己的固定版本。

  • nvim系统链接:/usr/local/bin/{nvim,neovim,vim}指向~/.apps/neovim/bin/nvim,所以sudo vim也 打开你的 Neovim。 /usr/bin属于dpkg,未被触及。 binstaller 自己的 sudo 符号链接已关闭。

  • Nerd Fonts (nerd-fonts-installer, ~/.local/share/fonts/NerdFonts),分 4 批安装,因为 Fluxion 给该类型一个固定的 15 分钟超时:

    • 01-core:JetBrainsMono,VictorMono,FiraCode,FiraMono,SymbolsOnly,CascadiaCode,Meslo,黑客, SourceCodePro, UbuntuMono, Ubuntu, ZedMono, GeistMono, CommitMono
    • 02-more:MPlus、总站、FantasqueSansMono、HeavyData、3270、LiberationMono、RobotoMono、Mononoki、 DroidSansMono, Monoid, SpaceMono, ComicShannsMono, DaddyTimeMono, CodeNewRoman
    • 03-rest:Hasklig、DejaVuSansMono、Inconsolata、隐士、龙舌兰、Monaspace、ShareTechMono、递归、D2Coding、 EnvyCodeR, IosevkaTerm, Lekton, Lilex
    • 04-noto:诺托,很大

    终端依赖于 VictorMono (alacrtty、ghostty、wezterm) 和 FiraCode (kitty)。

shell

oh-my-zsh(固定修订版和 sha256)、zsh-syntax-highlighting、zsh-autosuggestions、zsh-history-substring-search (固定提交)、TPM(固定)、starship (~/.local/bin) 和来自上游安装程序的 kitty (~/.local/kitty.app)。 kitty 的桌面集成与我在 bash 中手动执行的操作相匹配:kitty/kitten 链接 具有绝对 Icon/Exec 路径的 ~/.local/bin 和 .desktop 文件。 kitty 也被注册并选为 x-terminal-emulator 替代方案(优先级 60),Debian 工具会使用该替代方案。 Ubuntu 26.04 上的 GNOME/GLib 询问 xdg-terminal-exec(默认安装,以 Ptyxis 为种子),dotfiles 模块通过它指向 kitty ~/.config/{,ubuntu-,gnome-}xdg-terminals.list。 幽灵快照使用经典的限制。 zsh本身来自base,登录shell的更改发生在session中。

desktop-apps

  • 来自 apt 的 flatpak 和 Flathub 远程(描述符是 sha256 固定的)。 Ubuntu 两者都不提供;它 默认为快照。
  • Flatpaks(共 51 个,每组一个叶相,continueOnError):
    • 浏览器:LibreWolf、Chrome、Zen
    • 沟通:不和谐
    • 媒体: Audacity、AudioTube、ncspot、Decibels、Amberol、G4Music
    • 图形:Kdenlive、Inkscape、Krita、Blender、FreeCAD、Godot、LibreCAD、BambuStudio、展览
    • 写作:TextPieces、撇号、Bookup、Censor、Logseq
    • dev: WezTerm, VSCodium (Ptyxis 已经是 Ubuntu 的默认终端了,来自 apt)
    • 系统:扩展管理器、Flatseal、Flatsweep、仓库、资源、精炼、任务中心、Gradia、列表、 Authenticator, Polari, D-Spy, Rewaita, Emblem, Mozilla , NetPeek, GNOME Boxes, Gear Lever
    • 生产力:会话、毯子、包、LocalSend、NewsFlash、剂量、健康
  • 快照(在此主机上手动安装;continueOnError):brave、telegram-desktop、vesktop-tsugu (Vesktop),zulip,slack,spotify,mailspring,beekeeper-studio,onlyoffice-desktopeditors,zenkit-todo 和 glab 一步完成,再加上每个经典快照一步:sublime-text、theia-ide、workshop、waveterm、 jupyterlab-desktop、antigravity、antigravity-ide-snap、flutter 和 skuberplus-client。 OBS 就是这个 例外:它在可选的 obs 模块中保留为 Flatpak。
  • AI CLIs:克劳德代码 (claude.ai/install.sh)、OpenAI 代码 ([email protected]/codex/install.sh) 和 Kimi 代码 (code.kimi.com,使用 bash 运行,因为在此主机上使用 zsh 运行失败)。
  • Home-dir 应用程序:Zed (zed.dev/install.sh) 和 Paseo,在 Gear Lever 在此主机上提供的布局中: ~/AppImages/paseo.appimage,图标 ~/AppImages/.icons/paseo(摘自 AppImage),启动器 ~/.local/share/applications/paseo.desktop(paseo:// URL 处理程序、StartupWMClass=Paseo)和 ~/.local/bin/paseo 链接。保留现有启动器,当 AppImage 已存在时,不会下载任何内容 那里。

粗体中的项目是在此主机的历史记录或程序包日志中找到的。

gnome

关闭动态工作区并设置 9 个工作区。 Super+1..9 切换工作空间,Super+Shift+1..9 移动工作空间 那里有窗口,就像在 Fedora 上一样。默认switch-to-application-N绑定被清除,截图UI开启 Super+Print 和 Print。 Ubuntu Dock 的 hot-keys 设置([email protected],dash-to-dock 使用 org.gnome.shell.extensions.dash-to-dock 模式构建(默认情况下为 hot-keys=true)已关闭,因为 它抓取 Super+1..9 和 Shift+Super+1..9 来启动固定应用程序;否则,工作区绑定永远不会触发。探头(和 tests/assertions/gnome.sh)还会扫描每个 gsettings 键以查找这些快捷方式的任何其他持有者。该模块必须 在登录的 GNOME 会话中运行并断言 DBUS_SESSION_BUS_ADDRESS 已设置。

它还将 dash/taskbar 收藏夹设置为我手动固定的内容:Brave、Files、Software、Ghostty、Terminal、 TG 平台(快照)、Vesktop、ChatGPT、Claude 和 Paseo (org.gnome.shell favorite-apps)。 gnome 在 apps 之后运行, shell 和 desktop-apps,所以 .desktop IDs 那时就存在。该列表仅在 Vesktop 捕捉 (vesktop-tsugu_vesktop-tsugu.desktop) 时写入 尚未固定,因此稍后手动更改的引脚将被保留。断言如下:它需要 Vesktop 并且仅 报告(跳过)其他声明的手动移除的引脚。

tests/assertions/gnome.sh 还检查正在运行的 mutter 有 9 个工作区(_NET_NUMBER_OF_DESKTOPS 在 Xwayland 根窗口)。对于 ASSERT_LIVE_INPUT=1,它更进一步:它按下 Super+3,然后按下 Super+1 临时 /dev/uinput 键盘(tests/lib/uinput_keys.py,需要 sudo -n)并检查会话是否确实 切换工作区。该检查默认处于关闭状态,因为它将按键发送到桌面。

vicinae

请参阅 Vicinae 启动器。

dotfiles 和 session

请参阅 Dotfiles 与 dotbot 和 代理技能。 session 套 /usr/bin/zsh 作为您的登录 shell 并将您添加到 docker、libvirt 和 kvm。然后它会要求您注销。

Docker 代替 podman

旧的 Fedora 设置使用 podman、podman-docker、toolbox 和 buildah。在 Ubuntu 上,这些被替换为 Docker CE 来自 Docker 的官方 apt 存储库。 Ubuntu的docker.io没有使用。

什么 价值
回购协议 deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu resolute stable 中 /etc/apt/sources.list.d/docker.list
钥匙 https://download.docker.com/linux/ubuntu/gpg,sha256 引脚,指纹 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88
套餐 docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
服务 docker 和 containerd 启用并启动
冲突 首先删除 docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc(如果存在)
集团 docker,在session中添加。 注销并重新登录后生效
工具箱更换 distrobox 1.8.2.5从上游发布tarball(sha256固定),与--prefix ~/.local一起安装到~/.local/bin中; uidmap 来自 apt。它自动使用docker

注意事项:

  • distrobox 不取自 apt:Ubuntu 的 distrobox 软件包依赖于 podman | docker.io, and docker.io 与 docker-ce 冲突,因此 apt 会将 podman 拉回来。通过 distroboxVersion / 进行碰撞 distroboxSha256 中的 profiles/20-docker.yaml。
  • 该套件的字面意思是 resolute(Docker 发布 26.04 软件包;密钥与旧套件相同)。
  • Compose 是 v2 插件,因此使用 docker compose ... 而不是 docker-compose。 oh-my-zsh docker 和 docker-compose 插件在 .zshrc 中保持启用状态。
  • kind 和 minikube(来自 binstaller)使用 docker 驱动程序。直到您再次登录,docker 需要 sudo 或 newgrp docker。
  • 属于 docker 组相当于拥有 root 访问权限。这是通常的权衡,同样的 旧的 podman-docker 套接字设置已完成。如果您想避免它,请考虑 Docker 的无根模式。
  • 使用运行 docker run --rm hello-world 的 ./bootstrap.sh --only post-checks 进行检查。

使用 dotbot 的点文件

原始存储库是事实来源。 w0rxbend/system-bootstrap 被克隆到 ~/.system-bootstrap,dotbot 直接从该克隆链接出点文件。这个仓库没有保留 副本:dotfiles/ 仅保留原始存储库中没有同等内容的内容。

克隆人

scripts/system-bootstrap-sync.sh(dotfiles 的相 system-bootstrap-clone 或 just dotfiles-pull):

  • 通过 https 克隆,因此它在任何 SSH 密钥存在之前就可以工作,并设置 remote.origin.pushurl = [email protected]:w0rxbend/system-bootstrap.git,因此一旦您拥有密钥,推送就会超过 SSH;
  • 当克隆存在时,仅快进它(git fetch + git merge --ff-only)。本地提交,未提交 编辑、另一个分支、分离的 HEAD 或分歧的历史记录将被单独保留并带有警告;没有任何内容被重置, 隐藏或覆盖。不是该存储库克隆的路径是一个错误,不会被触及;
  • 当克隆已包含远程 HEAD 时,--check(fluxion 探针)通过。它决定了第一次运行 和 --re-probe 运行;之后 ./bootstrap.sh 跳过记录的步骤,因此更新克隆 just dotfiles-pull.

两个 dotbot 配置

这里的 dotbot 是 Go 版本(dotbot-go v0.4.2、~/.apps/dotbot/bin/dotbot 或 Fluxion 已验证的缓存 复制)。 scripts/dotfiles-link.sh 每个配置运行一次,每个配置都有自己的基本目录:

配置(在此存储库中) 基目录 友情链接
dotfiles/system-bootstrap.conf.yaml ~/.system-bootstrap/.files ~/.zshrc、~/.tmux.conf、~/.ideavimrc、~/.wezterm.lua、~/.hidden、~/.config/{starship.toml, alacritty/{alacritty,theme}.toml, kitty/kitty.conf, nvim, btop, ghostty, zathura/zathurarc, zellij/{config.kdl, layouts/*}, lazygit, lsd, yazi, bottom, nerd-fonts-installer/config.yaml}; ~/.config/paperwm/paperwm.conf 仅当安装 PaperWM 时
dotfiles/install.conf.yaml ~/.ubuntu-bootstrap/dotfiles ~/.custom.zsh、~/system-update.sh、~/.config/{,ubuntu-,gnome-}xdg-terminals.list(小猫)、~/.config/environment.d/90-session.conf、~/.config/binstaller/config.yaml(Ubuntu fork Fluxion适用,config/binstaller.yaml)和代理技能 链接

故意不与克隆链接:niri.conf.yaml 及其链接的所有内容(niri、DankMaterialShell、 danksearch、90-dms.conf、mimeapps.list、其 Alacritty xdg-terminals.list)、arch/ 和 fedora/(其 install.conf.yaml 和 *-system-update.sh),克隆的 binstaller 配置(~/.config/binstaller/config.yaml 链接 Fluxion应用的Ubuntu fork config/binstaller.yaml; tests/assertions/dotfiles.sh 报告任何版本引脚 与克隆的不同)和 vencord-settings-backup.json (手动导入)。 paperwm.conf 是 dconf dump; PaperWM之后 安装并链接后,用dconf load /org/gnome/shell/extensions/paperwm/ < ~/.config/paperwm/paperwm.conf加载。

链接默认值为 relink: true, create: true, force: true。在 dotbot 运行之前,dotfiles-link.sh 复制每个 链接目标处的 真实 文件或目录(以及指向其他地方的每个符号链接),其中 cp -a 为 ~/.ubuntu-bootstrap-backup/,保持其相对于$HOME的路径(~/.zshrc -> ~/.ubuntu-bootstrap-backup/.zshrc、~/.claude/skills -> ~/.ubuntu-bootstrap-backup/.claude/skills)。一个年纪较大的 备份永远不会被覆盖;较新的不同副本具有 .YYYYmmdd-HHMMSS 后缀。 create: 给出明确的 模式(~/.vim/undo-history 为 0755 和 0700),因为 dotbot-go v0.4.2 否则会创建目录为 0777。

Ubuntu 上的 .zshrc : ~/.custom.zsh 覆盖

~/.zshrc 是克隆中的共享文件。它以 [-f ~/.custom.zsh ] && source ~/.custom.zsh 结尾,并且 dotfiles/custom.zsh 链接在那里。它带有以前在复制的版本中进行编辑的 Ubuntu 差异 .zshrc:~/.cargo/env、~/.local/bin 首先在 PATH(克劳德代码、Codex、uv、诗歌、星舰)、~/.kimi-code/bin、 pnpm 11's $PNPM_HOME/bin, ~/.apps/yq/bin, the oh-my-zsh ubuntu plugin (the shared plugin list has dnf), and bootstrap / dotfiles 别名。所以老手编~/.zshrc放到PATH上的工具(claude、codex、kimi) 留在PATH; tests/assertions/dotfiles.sh 检查交互式 zsh 是否找到它们。

日常工作流程:在 ~/.system-bootstrap 中编辑并提交

nvim ~/.config/kitty/kitty.conf          # the link points into ~/.system-bootstrap/.files
cd ~/.system-bootstrap && git add -p && git commit -m "kitty: ..." && git push   # SSH pushurl
just dotfiles-pull                       # later, on any machine: fast-forward the clone
just dotfiles                            # re-link after adding a file or editing a dotbot config (idempotent)
just dotfiles-dry                        # preview (backups + dotbot -n)
just dotfiles-check                      # every link resolves to its source?

仅 Ubuntu 文件 (dotfiles/) 在此存储库中进行编辑和提交。一个新的共享点文件进入 ~/.system-bootstrap/.files(在那里提交)加上 dotfiles/system-bootstrap.conf.yaml 中的 link: 行。运行 just dotfiles 现在链接它。 ./bootstrap.sh 也选择配置编辑:bootstrap.sh 导出两者的摘要 dotbot configs 和 scripts/dotfiles-link.sh (ZB_DOTFILES_INPUTS),链接项以它命名 (dotbot-links-<digest>)。 Fluxion 会从 --skip-already-installed 下的状态跳过记录项,并且不会 对配置进行指纹识别,因此,如果没有该配置,引导程序就永远不会链接已编辑的配置。新的摘要就是新的 item:当每个链接都正确时,它的探测器(dotfiles-link.sh --check)会跳过它,否则它会运行。

克隆步骤不同:一旦记录,./bootstrap.sh 就会从状态中跳过它,因此它不会快进 在以后的运行中克隆。使用 just dotfiles-pull(或 ./bootstrap.sh --only dotfiles --re-probe)。

~/.system-bootstrap/.files/.config/vesktop/vencord-settings-backup.json 是故意不链接的。它是一个 您手动导入的备份;请参阅下面的手动步骤。

代理技巧

我的代理技能存在于一个真实的 git-tracked 文件夹,dotfiles/agents/skills/,以及每个编码代理链接 对其(dotbot,dotfiles/install.conf.yaml):

链接 代理 当
~/.agents/skills Codex(本地读取)和共享位置 总是
~/.claude/skills 克劳德·科德 总是
~/.cursor/skills, ~/.gemini/skills, ~/.copilot/skills, ~/.config/opencode/skills 光标,双子座 CLI,副驾驶 CLI,开放代码 仅当该代理的目录存在时(dotbot if:)

布局:每个技能一个文件夹,文件夹名称必须等于其 SKILL.md 前面内容中的 name:( 文件始终称为 SKILL.md)。 dotfiles/agents/skills/README.md 有详细信息和示例。

dotfiles/agents/skills/
├── README.md          # not a skill (outside any skill folder)
├── .gitignore         # ignores synced/ (Claude Code's own cache of claude.ai skills)
└── my-skill/
    ├── SKILL.md       # ---nname: my-skillndescription: ...n---
    └── scripts/  references/   # optional

验证循环(也由 tests/assertions/dotfiles.sh 运行):

cd ~/.ubuntu-bootstrap/dotfiles/agents/skills
for d in */; do d=${d%/}; [ "$d" = synced ] && continue
  n=$(sed -n 's/^name:[[:space:]]*//p' "$d/SKILL.md" 2>/dev/null | head -n1 | tr -d ""'")
  [ "$n" = "$d" ] && echo "ok   $d" || echo "FAIL $d (name: '${n:-missing SKILL.md}')"; done

scripts/link-skills.sh(POSIX sh、just skills)在没有 dotbot 的情况下进行链接,例如在安装后 代理:它将 ~/.agents/skills 指向 repo 文件夹,并将 <agent>/skills 指向 ~/.agents/skills ln -sfn,跳过未安装的代理,保留正确的链接,并且永远不会覆盖真实的链接 目录(它报告它并退出1;您自己将其移动到~/.ubuntu-bootstrap-backup/)。 --check 和 --dry-run 只报告。

注意事项:

  • 第一次运行dotfiles替换真实的~/.claude/skills目录,备份到后 ~/.ubuntu-bootstrap-backup/.claude/skills。它只保存了synced/,克劳德·科德的claude.ai技能的缓存,这 Claude Code 在链接文件夹内重新创建(git-ignored)。
  • Codex 的捆绑技能(~/.codex/skills/.system)从未被触及。 ~/.codex/skills/onboard-new-user 不是 移动:它是 Codex 应用程序的首次运行入门技能(它调用仅限应用程序的工具,例如 setup_codex_step),这不是我的技能,并且在其他特工中不起作用。

鼠尾草发射器

模块vicinae(profiles/75-vicinae.yaml,默认顺序,在gnome之后):

件 如何
野豌豆 v0.29.0 没有 .deb/PPA,并且发布的 tarball 是针对 Arch 的 Qt6 构建的。官方 AppImage(sha256 固定)通过固定到标签 v0.29.0(sha256 固定)的官方安装脚本提取到 /usr/local 中,使用 --appimage 和 TERM=dumb 以 root 身份运行(脚本中止,没有TERM)。作为 root,它还会在 vicinae-input-server 上设置 cap_dac_override 并加载 uinput(片段、粘贴)。探头为vicinae version = v0.29.0
服务器 安装程序附带的 systemd 用户 单元(/usr/local/lib/systemd/user/vicinae.service、vicinae server --replace、WantedBy=graphical-session.target)已启用并启动; vicinae ping 必须回答。 vicinae toggle 不自行启动服务器
GNOME 扩展 vicinae@dagimg-dot v1.7.2(EGO 8594,shell 46-50),GNOME Wayland 上需要用于剪贴板历史记录、窗口切换器、粘贴、居中和近距离焦点丢失。从固定的 GitHub 发行版 zip 安装到 ~/.local/share/gnome-shell/extensions/,编译模式,添加到 enabled-extensions,所有这些都没有 GNOME Shell 确认对话框。 下一个日志 out/in 后处于活动状态(session 检查点)
Super+D 运行 /usr/local/bin/vicinae toggle 的 GNOME 自定义快捷方式(Vicinae 自己的全局快捷方式需要 X11 或 ext-hotkey-v1,而 Mutter 缺乏)。 Ubuntu的模式覆盖(10_ubuntu-settings)将Super+D绑定到show-desktop,因此show-desktop首先设置为['&lt;Primary&gt;&lt;Super&gt;d', '&lt;Primary&gt;&lt;Alt&gt;d'](撤消:gsettings reset org.gnome.desktop.wm.keybindings show-desktop)

重新登录后,按 Super+D 并立即键入:启动器应居中打开并聚焦(GNOME 的 focus-new-windows 为 smart)。不要从应用程序网格启动“Vicinae”:它的启动器运行 vicinae server --replace 并与 systemd 副本进行斗争。日志:journalctl --user -u vicinae。碰撞和撤销是 在配置文件标题中进行了描述。

测试

tests/ 在镜像生产 1:1 的测试配置文件上执行相同的编排 (bootstrap.sh):

  • tests/gen-test-profiles.sh 从 profiles/ 中的每个文件生成 tests/generated/<same path> (python3 + PyYAML,tests/lib/gen_test_profiles.py)。唯一的变化:prompt-logout / requires-new-shell 删除重新启动策略,删除 interrupt / manual / shell-reload 步骤(并且阶段留空, 及其 dependsOn 引用),confirm: 防护被删除,相对 config: 路径变为绝对路径。 每个生成的文件都以注释开头,其中准确列出了更改的内容。今天是 session 注销 检查点和post-checks中的三个手动提醒。相同的列表转到 tests/generated/production-only.tsv,prod-status 阶段报告。
  • tests/generated/ 是 git-ignored:它是派生数据,由 bootstrap.sh --test 重新生成,并且 每次使用之前的 tests/run-tests.sh (如果 --check 过时,则会显示差异),因此它不会漂移。
  • ./bootstrap.sh --test ... 运行状态名称为 test-NAME 的配置文件,因此生产状态 (~/.local/share/fluxion/NAME.state.json) 未受影响。

tests/run-tests.sh 阶段(全部默认,--stages a,b 可选择):

舞台 发生了什么
validate fluxion validate --strict + 每个选定测试配置文件的 lint,并且 bootstrap.sh --test --dry-run 退出 0,没有检查点
apply bootstrap.sh --test --only MODULES 每个模块退出 0
idempotency 再次运行相同的操作:每个模块都退出 0,除了 assert 步骤之外没有任何运行(fluxion 会在每次运行时重新检查每个断言,并且从不跳过保持 1 的阶段,请参阅警告表)。 --strict-idempotency 添加了 --re-probe,因此记录的状态被忽略,并且每一项都必须由其实时探针满足;当它们的步骤没有 probeCommand 时,包 actions 也会运行,例如 apt update,并且也不被计算在内(这些配置文件中的每个 actions: [update] 都有一个,所以没有一个运行:00-base 在成功更新后跳过它 6 小时,一旦步骤的包是 10-apps安装); pipx、uv-tool、snap、npm-global 和 go-install 后端的 tool-packages 项目也没有步骤 probeCommand,因为 Fluxion 没有针对这些项目的实时探针(fluxion status 将它们显示为未知)并重新运行它们。自fluxion 0.4.0(提交9d7b731和82f3e77)以来,cargo/cargo-binstall crates和sdkman-packages候选者会按项目进行探测,因此必须跳过它们。再次运行的项目列在日志目录的 ran-again-MODULE.txt 中
prod-status 只读,测试无法运行的内容:对于 production-only.tsv 中的每个仅生产部分,来自 生产 配置文件和状态 (fluxion status --format json) 的实时状态:done、PENDING 以及步骤自己的消息(用户的手动步骤;报告,未失败),或not exercised(注销检查点)。列于汇总表下方
assert tests/assertions/MODULE.sh:真正的结果。配置文件自己的列表中的软件包、固定版本的命令、apt 源和密钥环、docker/containerd 活动和 docker run --rm hello-world(使用 sudo -n 直到 docker 组处于活动状态)、~/.system-bootstrap 克隆和 Pushurl、每个 dotbot 链接解析为克隆或此存储库、技能链接 + 名称检查,交互式 zsh 查找 claude/codex/kimi、Super+1..9 的 gsettings(加上对任何其他持有者的扫描)、Super+D -> vicinae 和 show-desktop、vicinae 用户服务和 ping、/etc/group 中的登录 shell 和组成员身份
tests/run-tests.sh --list                          # modules, generated profiles, GUI needed?
tests/run-tests.sh --stages validate --with-optional   # read-only (just test-validate)
tests/run-tests.sh --assert-only --only gnome,vicinae  # read-only (just test-assert ...)
tests/run-tests.sh --only gnome,vicinae            # apply + idempotency + assert for two modules
tests/run-tests.sh                                 # the whole default sequence
tests/run-tests.sh --container                     # base,apps,toolchains,binaries,shell,dotfiles,wallpapers
                                                   # in a throwaway ubuntu:26.04 container (needs docker)
FLUXION_BIN=/path/to/fluxion tests/run-tests.sh --require-prod-bin ...   # another build; fail if production differs
  • Fluxion 由 scripts/lib/fluxion-bin.sh 解析,与 bootstrap.sh 解析它完全相同($FLUXION_BIN,否则 fluxion-bin.local,否则 PATH),因此绿色运行涵盖了生产二进制文件。运行打印二进制文件,其中 来自及其 binstaller 引脚,拒绝早于 0.4.1 的 Fluxion,并在出现错误时发出警告 显式 FLUXION_BIN 与普通 ./bootstrap.sh 运行的不同(--require-prod-bin 使得 失败)。容器模式安装相同的二进制文件。
  • 从 GNOME 会话运行主机测试。如果没有会话总线(SSH、cron),则每次需要它的检查都会失败 而不是被跳过,因此 gnome、vicinae 和 gnome-extensions 无法通过零检查;只有 容器会跳过它们。列表助手(assert_pkgs、assert_flatpaks、assert_snaps)在空列表上失败,因此 形状发生变化的轮廓不能空空通过。
  • tests/assertions/dotfiles.sh 证明“没有副本”:tests/lib/find_copies.py 比较此文件的每个 git-tracked 文件 存储库,其中包含克隆的 .files 下的每个 git-tracked 文件,逐字节并包含注释、引号和空格 正常化了。它还报告(跳过)Ubuntu 分支 config/binstaller.yaml 中的每个 binstaller 版本 pin 与克隆体不同。
  • ASSERT_NETWORK=0 跳过需要网络的检查(apt-get update, docker run,克隆的ls-remote)。 ASSERT_LIVE_INPUT=1 让 gnome 真正按下 Super+3/Super+1 (参见 gnome)。
  • 日志、每阶段 --report 文件和 summary.tsv 转到 tests/logs/<timestamp>/ (git-ignored;--log-dir 改变)。
  • 每个断言文件也单独运行:tests/assertions/vicinae.sh。
  • 容器模式是新鲜机测试。它构建了 tests/container/Dockerfile: ubuntu:26.04 以及软件包 在 tests/container/ubuntu-baseline.txt 中,所有这些都随 Ubuntu 26.04 Desktop 一起提供(对照 桌面映像安装的软件包列表,/var/log/apt/history.log 的第一个条目在新的 26.04.1 上) 除快速启动安装的 git 和 curl 外;主机的用户名、uid 和主路径 无密码 sudo 仅在图像内。镜像保留Ubuntu自带的/etc/os-release(ID=ubuntu, VERSION_CODENAME=resolute)。 Desktop、snapd 和 flatpak 都不在里面。然后运行 git clones 这个存储库的提交了 HEAD (以只读方式安装) ~/.ubuntu-bootstrap,与快速启动完全相同,因此未测试未提交的更改(它警告)。只有 非GUI模块运行(base,apps,toolchains,binaries,shell,dotfiles,wallpapers);其他人都被拒绝。
  • 容器中没有静默地跳过任何内容。需要 systemd 作为 PID 1 或 snapd 的步骤(systemd-unit 和 system-setting种类,ghostty、code和crystal按扣; tests/lib/gen_test_profiles.py 中的 CONTAINER_SKIPS) 被删除 仅来自测试配置文件 (TEST_CONTEXT=container),每个配置文件都列在生成的文件的标头中, 在运行之前和摘要中的日志目录中的 container-skips.tsv 中。断言运行于 ASSERT_CONTEXT=container 并为每个需要 systemd、snapd 的检查打印 skip 行(带有原因), flatpak、GNOME 会话或 GUI 模块的输出(claude/codex/kimi 来自 desktop-apps)。
  • post-checks 持有断言,仅传入 session 模块之后启动的会话(docker group、Vicinae 扩展已加载)。在您注销并重新登录之前,其 apply 和 idempotency 阶段正是在这些方面失败;的 断言 (tests/assertions/post-checks.sh) 将它们视为信息性的。

添加或更改项目

将一个新项目放入其所属的模块中,使其保持在正确的阶段,然后验证:

添加 哪里 如何
Ubuntu 归档包 profiles/00-base.yaml 将名称添加到匹配的 apt-* 阶段列表中。首先检查它是否存在:apt-cache policy NAME
第三方apt应用程序 profiles/10-apps.yaml 新叶相 dependsOn: [host-check] 具有 apt-repository 步长(密钥的引脚 checksum:curl -fsSL KEY_URL | sha256sum) followed by an apt-packages步骤
一个扁平包装 profiles/60-desktop-apps.yaml 将完整应用程序 ID 添加到 flatpak-* 类别阶段(flatpak remote-info flathub ID 进行检查)
啪啪啪 profiles/60-desktop-apps.yaml,相snaps 严格按扣:tool-packages 与 backend: snap。经典快照:带有 sudo: true、run: snap install NAME --classic 和 unless: snap list NAME 的 commands 项目
锈 CLI profiles/30-toolchains.yaml,相rust-crates 添加板条箱名称(使用cargo-binstall安装)
~/.apps 中的发布二进制文件 config/binstaller.yaml 添加binstaller条目(如果可能的话,引脚version + checksum),然后将其路径添加到profiles/40-binaries.yaml中的binaries-binstaller探针,将其bin目录添加到PATH(共享: ~/.system-bootstrap/.files/.zshrc;仅限 Ubuntu:dotfiles/custom.zsh),并检查 tests/assertions/binaries.sh
书呆子字体 config/nerd-fonts/0N-*.yaml 和 ~/.system-bootstrap/.files/.config/nerd-fonts-installer/config.yaml 将其添加到批次中(每个批次保持在约 15 个系列以下:每批次固定 15 分钟超时)以及克隆中的完整列表(从那里提交并推送); tests/assertions/binaries.sh 检查两者是否一致
curl/installer 脚本 拥有该工具的模块 首选 shell-scripts 和 url + sha256(如果需要 bash,则 + shell: bash)。否则,commands 项目带有 creates: 和 probeCommand,因此重新运行时会跳过它
共享点文件 ~/.system-bootstrap/.files/ + dotfiles/system-bootstrap.conf.yaml 在克隆中添加并提交文件(从那里推送),在此处添加 link: 条目,然后添加 just dotfiles
仅限 Ubuntu 的点文件 dotfiles/ + dotfiles/install.conf.yaml 添加文件和 link: 条目,然后添加 just dotfiles
代理技能 dotfiles/agents/skills/&lt;name&gt;/SKILL.md 前面的文件夹名称 = name:;提交它。每个代理都可以通过链接看到它
GNOME 设置 profiles/70-gnome.yaml 将 gsettings set 行添加到脚本中,并在需要时扩展其 probeCommand

现有配置文件遵循的规则:

  • 步骤名称在所有配置文件中都是唯一的(使用模块作为前缀:apps-...、docker-...)。
  • 每个阶段都在 dependsOn 中列出其真正的先决条件(至少 host-check)。可能部分失败的列表位于 叶期(没有什么取决于它)与execution: { continueOnError: true }。
  • Shell 文本不得包含 ${...} 配置文件变量;通过 args: / env: 传递它们并使用普通的 $HOME。
  • 任何需要root的东西都使用sudo: true(fluxion调用sudo -n;bootstrap.sh保持票据温暖)。
  • tests/assertions/<module>.sh中每个模块都有后置条件;当你添加一些东西时扩展它们 很重要。测试配置文件会自行重新生成。
  • 一个全新的模块文件:将其添加到bootstrap.sh中的DEFAULT_PROFILES(或OPTIONAL_PROFILES)中,添加 tests/assertions/<module>.sh(函数assert_<module with _ for ->),复制 host-check 与任何现有配置文件相匹配,并为其赋予唯一的 metadata.name。

然后检查一下:

just validate                                   # or: scripts/validate-all.sh (prod + test profiles, scripts)
./bootstrap.sh --dry-run --only NAME            # exact commands, no changes
tests/run-tests.sh --only NAME                  # apply + idempotency + assertions on the test profile
./bootstrap.sh --only NAME                      # apply

重运行和幂等性

  • bootstrap.sh 始终与 --skip-already-installed 一起应用。当fluxion状态时会跳过一个项目 将其记录为成功,或者当其探测器报告其存在时。探头包括dpkg-query、flatpak info、 snap list,文件存在检查和每一步的probeCommand。

  • 以未更改的指纹完成的阶段(其配置的哈希值,包括委托的配置文件和 内联脚本)被完全跳过。当您在一个阶段中更改任何内容时,它会再次行走,但是 --skip-already-installed 探测通过的每个项目仍然被跳过。对于带有粗略探针的步骤(binstaller、 Nerd Fonts)使用 just refresh-binaries / just refresh-fonts,或者运行 fluxion apply ... --phase NAME 而无需 --skip-already-installed.

  • 失败的阶段永远不会被记录为完成,因此下次运行会重试它。

  • 每个模块都保留自己的状态:

    fluxion state show docker                     # what was recorded
    fluxion state path docker                     # ~/.local/share/fluxion/docker.state.json
    fluxion state forget --profile docker --phase docker-engine   # re-run one phase next time
    fluxion state reset docker --force            # forget everything for the module (just state-reset docker)
    
  • tests/run-tests.sh 检查这一点是否真实:测试应用后,第二次运行必须报告 0 ok · 0 failed 每个模块(参见 测试)。

  • --re-probe 忽略记录的状态并仅信任实时探针。删除某些内容后很有用 手。

  • 运行一个模块:./bootstrap.sh --only toolchains。失败后恢复:./bootstrap.sh --from shell。

  • 要在没有包装器的情况下直接运行 Fluxion,请使用相同的状态名称并导出相同的 PATH (请参阅 bootstrap.sh):

    sudo -v && fluxion apply -c profiles/30-toolchains.yaml --profile toolchains --skip-already-installed
    

此处处理 Fluxion 警告

标记为 fixed in Fluxion 0.4.0 的行是 Fluxion 版本 的内容;其余的是 在配置文件中处理并仍然适用。

警告 这个仓库如何处理它
dotfiles-apply 已损坏:它通过了 --config,但 dotbot-go 只接受 -c (并且它需要一个配置,而这里需要两个基本目录) 80-dotfiles 从 shell-scripts 步骤运行 scripts/dotfiles-link.sh:dotbot -d ~/.system-bootstrap/.files -c dotfiles/system-bootstrap.conf.yaml,然后 dotbot -d dotfiles -c dotfiles/install.conf.yaml,以 --check 作为探针
dotbot 配置不是 dotfiles 阶段指纹的一部分,并且记录的项目会从状态中跳过(0.3.1 及更高版本),因此编辑后的 dotbot 配置从未由 ./bootstrap.sh 链接 链接项名为 dotbot-links-&lt;digest of both configs + dotfiles-link.sh&gt;(ZB_DOTFILES_INPUTS,由 bootstrap.sh 导出),因此更改的输入会生成 --check 探针决定的新项
apt包探针总是说“未安装”:输出清理程序将dpkg-query -f='${Status}t${Version}'中的选项卡变成空格,因此探针永远不会看到install ok installed(在0.3.1和当前主版本中,src/fluxion/executor/probe.cr + redaction.cr) --skip-already-installed 仍然跳过已完成的阶段,并且已安装软件包的 apt-get install 没有任何变化。断言直接使用 dpkg-query 检查包。 tests/run-tests.sh --strict-idempotency 需要对此修复进行流变(在 fix/zorin-bootstrap 分支上完成,该分支还将每个 apt 列表批处理为一个 apt-get install 并探测 system-setting 项目)
通过的 assert 步骤记录在状态 (0.3.1) 中,因此使用 --skip-already-installed 时,他们的阶段在下一次运行时被跳过,并且不会重新检查守卫 Fluxion 0.4.0 (af2c932) 中已修复:断言的传递永远不会从状态中存储或信任,并且保存断言的阶段永远不会被跳过(其其他步骤仍然从 state/probes 跳过)。配置文件保持简单的kind: assert步骤;在 0.3.1 中,仅在 --re-probe 下重新检查更改的主机
apt-repository 探针仅检查 .list 是否存在; gpg-key 仅探测密钥环路径是否存在 (0.3.1),因此 vendor/hand-written claude-desktop.list (signed-by=...asc) 或密钥环路径中的错误密钥被视为永久安装 Fluxion 0.4.0 中已修复(f992d37、5d19083):源文件必须等于声明的 source 行,并且其密钥环必须非空; gpg-key 密钥环必须准确保存声明的指纹。 apps 声明 apps-claude-desktop-key(指纹固定)+ apps-claude-desktop-repo,无采用步骤。在已有供应商 claude-desktop.list 的主机上使用 0.3.1,使用 --re-probe --only apps 运行一次修补版本
prompt-logout 阶段从未被记录为已完成,并且运行退出 0 (0.3.1):暂停阶段仅写入恢复点,因此每次运行都会重新运行 session 并再次要求注销,并且 bootstrap.sh 看到 rc 0 而不是检查点代码 75,因此--with-optional 重新登录之前,它会进入可选模块(包括后检查) Fluxion 0.4.0 中已修复(4254ceb、d699c4a):该阶段被记录为已完成,并且 apply 退出 75,因此 bootstrap.sh 在检查点停止一次,下一次运行会从状态跳过 session。没有运行任何内容(跳过每个项目或仅断言)的 prompt-logout 阶段根本不会询问,因此聚合主机上的 ./bootstrap.sh --re-probe 和 --only session,obs 运行到最后
步骤的 probeCommand 在每个项目之前重新运行 (0.3.1),因此一旦较早的脚本使其成立,该步骤的后续脚本就会被跳过(“跳过:已安装(探测)”),并且该步骤仍算作成功 Fluxion 0.4.0 (9a77b8f) 中已修复:每次应用整个步骤时,都会回答一次步骤的 probeCommand。无论哪种方式,配置文件都遵循一个规则:每个可观察状态一个步骤,并且每个步骤的探测仅当其所有脚本完成时才为真。根据先前步骤留下的内容来判断的工作会得到自己的步骤(vicinae-post-install)
Flatpak 探针仅列出应用程序(flatpak list --app,0.3.1),但 OBS 插件(com.obsproject.Studio.Plugin.*)是运行时引用,因此安装后它们仍然显示为不存在,并且 --re-probe 会再次安装它们(对于 Flatpak 来说无操作,但报告为更改) Fluxion 0.4.0 (7430ef4) 中已修复:探针列出了每个已安装的参考。在 0.3.1 中,默认的(基于状态的)幂等性运行仍然会跳过它们;只有 obs 上的 --strict-idempotency 报告它们再次运行。 assert_flatpaks 检查每个参考,而不仅仅是应用程序
gpg-key 在新帐户上失败:它使用 gpg --batch --no-options --show-keys 读取每个密钥,并且使用 --no-options gpg 不会创建丢失的 ~/.gnupg (gpg: Fatal: ~/.gnupg: directory does not exist!),因此在新安装时,每个 gpg-key 步骤都会失败(每个版本;通过容器测试发现) apps 在其 gnupg-home 阶段创建 ~/.gnupg (0700),三个 gpg-key 阶段所依赖的
fluxion 从不提示输入 sudo:它只使用 sudo -n bootstrap.sh 运行 sudo -v 一次,然后保持活动循环运行直到退出。 Ubuntu的sudo票持续15分钟而TeX Live单独运行需要更长的时间
PATH 在启动时读取一次 每个模块一个 Fluxion 进程,并且 bootstrap.sh 预先导出所有未来的工具目录,因此后面的模块可以看到较早的安装
when: 在加载时评估 配置文件不在同一运行安装的工具上使用 commandExists 防护
SDKMAN 的安装程序需要 bash,但 toolchain 类型使用 sh SDKMAN、nvm 和 pyenv 将 shell-scripts 与 url、sha256 和 shell: bash 一起使用
失败的阶段会阻止依赖于它的一切 dependsOn 仅列出真正的先决条件,脆弱列表位于叶阶段,列表阶段使用 continueOnError: true
${...} 在 shell 文本中被拒绝 脚本使用普通 $HOME 并通过 args/env 获取配置文件值
apt-repository/gpg-key 永远亲爱的 每个密钥环路径均以 .gpg 结尾。 .asc 路径最终会保存二进制数据并破坏 apt
prompt-logout 停止运行(也在空运行中) 仅出现在最后一个模块session中;生成的测试配置文件将其丢弃
gext install 弹出 GNOME Shell 确认对话框(D-Bus 后端)并阻止运行 gnome-extensions 使用 gext -F install(文件系统后端); Vicinae 的扩展件是从固定拉链中解开的。探针检查文件+ enabled-extensions,因为gnome-extensions info仅在重新登录后才知道新扩展名
无 DEBIAN_FRONTEND Debconf 是为 mscorefonts 和wireshark 预置的
当上游脚本更改时,校验和引脚会失效 由于摘要不匹配,运行严重失败。重新计算引脚(请参阅 更新)

引导后的手动步骤

  1. 在 session 检查点之后注销并重新登录(或重新启动)。在那之前你并不在docker中, libvirt 和 kvm 组(使用 sudo docker ... 或 newgrp docker),新终端仍然启动旧终端 登录外壳。如果session失败,请使用chsh -s /usr/bin/zsh手动换壳。然后运行 ./bootstrap.sh --only post-checks.

./bootstrap.sh --only post-checks 提醒您接下来的三个:每个都是一个 manual 步骤,其探针通过一次 你已经完成了,直到那时模块退出1并打印指令(所以失败的post-checks正确 重新登录后通常意味着只打开一个提醒)。 tests/run-tests.sh 将它们列在“仅限生产”下 零件”与 done / PENDING。

  1. GitHub CLI:运行gh auth login。

  2. SSH 密钥:运行 ssh-keygen -t ed25519 -C "[email protected]",然后运行 gh ssh-key add ~/.ssh/id_ed25519.pub。 切勿将 ~/.ssh 复制到此存储库中; .gitignore 区块 id_*、*.pem 和 *.key。

  3. Flatpak 重复: 引导程序将 TG 平台、Zulip、Vesktop 和 Spotify 安装为 snaps。如果较旧的运行 把他们的扁平包装留在后面,用 flatpak uninstall org.telegram.desktop org.zulip.Zulip dev.vencord.Vesktop com.spotify.Client.

  4. 登录到 1Password、Claude Desktop、ChatGPT、Claude 代码 (claude)、Codex (codex)、Kimi (kimi)、VS 代码设置同步、Spotify、Discord/Vesktop 和 TG 平台。

  5. Vesktop: 打开 Vencord 设置,转到备份和恢复,然后导入 ~/.system-bootstrap/.files/.config/vesktop/vencord-settings-backup.json.

  6. Brave“GitHub”网络应用程序:在 Brave 中,打开 github.com,然后转到菜单 → 投射、保存和共享 → 将页面安装为 应用程序。浏览器自己创建这些网络应用程序,因此无法以任何合理的方式编写脚本。

  7. 区域格式: en_GB 格式和 A4 纸在设置→区域和语言中设置,其中写入 ~/.pam_environment。再次将它们放在那里;该文件不在这里管理。

  8. Claude 钥匙圈 .asc:保留它。 claude-desktop 软件包重写 每次升级时都会出现 /usr/share/keyrings/claude-desktop-archive-keyring.asc,因此删除它不会产生任何效果。它是 无害:由 apps 编写的 claude-desktop.list 没有包标记,因此包将其指向 亲爱的.gpg。

  9. 可选:1Password debsig 策略。 Ubuntu 的 dpkg 仅在 debsig-verify 为时强制执行包签名 设置。要启用 1Password 验证:

    sudo apt install -y debsig-verify
    sudo mkdir -p /etc/debsig/policies/AC2D62742012EA22 /usr/share/debsig/keyrings/AC2D62742012EA22
    curl -sS https://downloads.1password.com/linux/debian/debsig/1password.pol | sudo tee /etc/debsig/policies/AC2D62742012EA22/1password.pol >/dev/null
    curl -sS https://downloads.1password.com/linux/keys/1password.asc | sudo gpg --dearmor --output /usr/share/debsig/keyrings/AC2D62742012EA22/debsig.gpg
    
  10. Neovim: 启动 nvim 一次,以便 lazy.nvim 安装 lazy-lock.json 中列出的插件。

  11. tmux: dotfiles 已安装插件。在 tmux 内部,prefix + I 重新安装它们。

  12. droidcam 别名: 它需要 scrcpy 2.2 或更高版本,引导程序不会安装。

  13. 地址:重新登录后按Super+D并立即输入;启动器应以居中方式打开 keyboard focus. gnome-extensions info vicinae@dagimg-dot should now say ACTIVE (clipboard history needs it).

  14. 备份: dotbot 替换的任何内容都位于 ~/.ubuntu-bootstrap-backup/ 中(与 $HOME 中的路径相同)。删除它 once you are happy.

可选模块

./bootstrap.sh --only obs                 # OBS Studio + 10 plugins (flatpak)
./bootstrap.sh --only gnome-extensions    # gext -F + 6 extensions (run in the GNOME session)
./bootstrap.sh --only wallpapers          # ~109 MB of wallpapers from the old repo
./bootstrap.sh --only post-checks         # after re-login
  • obs:大多数插件都是OBS flatpak扩展。该模块安装 flatpak 和 Flathub 遥控器本身 当 desktop-apps 尚未运行时。
  • gnome-extensions:dash-to-dock(Ubuntu Dock 已经是其中之一)、tilingshell(Ubuntu 附带了 tiling-assistant)和 appindicator/status-icons(Ubuntu 附带 ubuntu-appindicators)被故意省略。所有六个都有 GNOME 50 构建。 gext -F install 解压各个扩展 并将其添加到 enabled-extensions,而不显示普通 gext install 显示的 GNOME Shell 确认对话框。 之后注销并重新登录:Wayland 上的 GNOME Shell 仅在登录时加载新扩展。
  • wallpapers:图像不在此存储库中。

没有移植,为什么

项目 原因
niri、DankMaterialShell/dms/danksearch、PaperWM 本身、sway、waybar、fuzzel、rofi、hypr*、COSMIC/SDDM 调整、multibg-wayland 箱、assets/icons、niri.conf.yaml 平铺和拱形桌面设置。 Ubuntu 保留自己的 GNOME 桌面。 (paperwm.conf 仍从克隆链接,但前提是您自己安装 PaperWM)
dash-to-dock、tilingshell 扩展 Ubuntu Dock 已经支持 Dash-to-Dock,并且 Ubuntu 还提供了平铺助手;平铺超出范围
podman、podman-docker、工具箱、buildah 替换为 Docker CE 和 distrobox
RPM Fusion、ffmpeg 交换、fedora-workstation-repositories、Fedora/Arch dotbot 覆盖、fedora-/arch-system-update.sh 仅适用于 Fedora 或 Arch。 Ubuntu的ubuntu-restricted-extras覆盖了编解码器,ubuntu-system-update.sh替换了更新脚本
勇敢的平包 勇敢来自于它在这个主机上的快照
dev.zed.Zed 扁平包装 Zed 来自 zed.dev/install.sh,与主机上一样
org.telegram.desktop、org.zulip.Zulip、dev.vencord.Vesktop、com.spotify.Client 平板包装 他们的快照被使用,就像在这个主机上一样
com.oguzhaninan.Stacer 扁平包装 从 Flathub 中删除。 Stacer 来自 apt 相反
apt kitty, neovim (0.9.5), yq (Python flavour), fd-find, gnome-shell-extension-manager 替换为上游 kitty、binstaller 的 neovim 和 mikefarah yq、cargo 的 fd 以及 Extension Manager flatpak
mimeapps.list 只有 niri 配置在旧存储库中链接它,并且 Ubuntu/GNOME 管理它
coursier、platformio、deno、nimble、JetBrains 工具箱、Android SDK、opencode、mill、envman、~/.fzf.zsh、scrcpy 由旧的 .zshrc 引用,但没有安装它们,并且它们不会出现在主机历史记录中。 .zshrc 线路留在防护装置后面,因此稍后安装任何一条线路都可以
自动 1Password debsig 策略 Ubuntu 上的 dpkg 不会强制执行,除非您设置了 debsig-verify(请参阅手动步骤)
旧存储库的格式为 CI(shfmt、stylua、prettier,...) Fluxion validate/lint 与 scripts/validate-all.sh 一起是这里的质量门

更新中

日常:运行 update(~/system-update.sh 的 zsh 别名)或 just update。它更新 apt、snap、flatpak、 rustup, juliaup, SDKMAN, nvm/Node LTS, mamba, uv, pnpm, Poetry, oh-my-zsh and, optionally, the cargo crates. Each section 当工具丢失时会被跳过,并且一次失败不会停止其余的操作。

~/.apps 二进制文件和 Nerd 字体: ./bootstrap.sh --only binaries 不会刷新它们。 bootstrap.sh 总是通过 --skip-already-installed,并且在该模式下,fluxion 会跳过探针通过的项目,即使当 阶段的配置发生了变化。一旦所有 13 个可执行文件存在,binstaller 探针就会通过,并且每个字体探针都会通过 一旦 fc-list 找到它的家人。运行没有该标志的阶段(不需要 sudo):

just refresh-binaries   # fluxion apply -c profiles/40-binaries.yaml --profile binaries --phase binstaller --no-tui
just refresh-fonts      # ... --phase fonts-core,fonts-more,fonts-rest,fonts-noto --no-tui

因此,要修改工具,请在 config/binstaller.yaml 中编辑其版本(和校验和),然后运行 just refresh-binaries。 latest-url 工具(minikube、xplr、kubectl、neovide、neovim、yq)在每次刷新时都会迁移到最新版本。

撞针(安装程序脚本、密钥、tarball)。大多数远程脚本和密钥由 sha256 和 git 固定 按提交回购。当上游更改它们时,fluxion 会因摘要不匹配而失败,这是预期的。撞针:

curl -fsSL https://sh.rustup.rs | sha256sum                  # installer scripts / keys / descriptors
git ls-remote https://github.com/tmux-plugins/tpm HEAD       # git-repo refs (40-hex)

然后编辑配置文件中的值并运行 just validate。

销 文件
Go 版本和 tarball sha256 (spec.vars)。 另外更改 go-toolchain probeCommand 中的文字 go1.27.1 :探针无法使用 ${...},并且每次运行都会重新下载过时的探针 profiles/30-toolchains.yaml
rustup, cargo-binstall script (commit and sha), SDKMAN, nvm tag and sha, pyenv, juliaup profiles/30-toolchains.yaml
oh-my-zsh 修订版和 sha、zsh 插件提交、TPM 提交 profiles/50-shell.yaml
Docker / GitHub CLI / Claude 桌面密钥 sha256; 1密码密钥指纹 profiles/20-docker.yaml, profiles/10-apps.yaml
distrobox 版本和 tarball sha256 (spec.vars)。 另外更改 docker-distrobox probeCommand 中的文字 distrobox: 1.8.2.5 profiles/20-docker.yaml
Flathub 描述符 sha256 profiles/60-desktop-apps.yaml, profiles/optional/obs.yaml
binstaller 工具版本 config/binstaller.yaml
Vicinae 版本、AppImage 和安装脚本 sha256、GNOME 扩展 zip 版本和 sha256(也是探针中的文字版本) profiles/75-vicinae.yaml
流动本身 FLUXION_VERSION 位于 bootstrap.sh 中(一旦存储库依赖于新版本,FLUXION_MIN_VERSION 位于 scripts/lib/fluxion-bin.sh 中);如果 fluxion-bin.local 指向较旧的版本,请删除它。在修改之前请阅读 Fluxion 变更日志,因为上面的警告与版本相关

故障排除

查找失败的原因:

./bootstrap.sh --failed --only docker                           # missing / failed items (just failed docker)
fluxion explain -c profiles/20-docker.yaml --profile docker --phase docker-engine
fluxion status  -c profiles/20-docker.yaml --profile docker --failed
fluxion state show docker                                       # ~/.local/share/fluxion/docker.state.json
./bootstrap.sh --only docker --show-output --no-tui            # re-run, echoing each command's output

apt-get update 失败并显示 crystal ... does not have a Release file(退出 100): Crystal 安装程序是 通过管道传输到 sudo zsh。 zsh 保留 ${OBS_PROJECT//:/:/} 的反斜杠,因此 /etc/apt/sources.list.d/crystal.list 包含 devel:/languages:/crystal(404)和 /etc/apt/trusted.gpg.d/devel_languages_crystal.gpg 为空。 base 首先将两个文件移动到 /var/backups(阶段 apt-sources-repair);水晶本身来自 crystal 按扣。手动修复它: sudo rm -f /etc/apt/sources.list.d/crystal.list /etc/apt/trusted.gpg.d/devel_languages_crystal.gpg。如果你使用 再次安装该安装程序,将其通过管道传输到 bash,而不是 zsh,或者更好地使用 sudo snap install crystal --classic。

yazi 停在 Press <Enter> to continue with preset settings(TOML parse error ... "$schema" 或 missing field group): 从 ~/.system-bootstrap/.files/.config/yazi 链接的 yazi.toml 和 keymap.toml 是固定 yazi 的 v26 之前的格式v26.5.6 拒绝(旧的仓库固定相同的版本,所以这不是新的)。这是克隆的内容,因此请修复它(删除 "$schema" 行并将文件移至 v26 格式,然后以 ~/.system-bootstrap 提交); tests/assertions/dotfiles.sh 将其报告为跳过,直到加载链接的配置。

模块显示 ok 但未安装任何内容: 使用 --tui,在选择器处按 q 退出该模块, Fluxion 退出 0。在没有 --tui 的情况下重新运行它。

“需要密码”/ sudo 失败: keep-alive 循环停止,例如因为 终端关闭或机器暂停。重新运行模块,完成的项目将被跳过。

Flatpak 安装失败并出现授权错误: 您可能正在 SSH 上运行,或者在活动范围之外运行 本地会话。从 GNOME 会话中的终端重新运行 ./bootstrap.sh --only desktop-apps。

gnome 失败其 gnome-session-check: 相同的原因:gsettings 需要 DBUS_SESSION_BUS_ADDRESS,这 只有本地会话有。

apt 或 dpkg 挂起,或者出现 debconf 问题: 软件包询问了未预置的内容。完成它 手与sudo dpkg --configure -a,添加debconf-set-selections线到base-debconf-preseed profiles/00-base.yaml,并重新运行。

已持有 dpkg 锁: GNOME 软件或无人值守升级正在运行。等待,或检查 sudo lsof /var/lib/dpkg/lock-frontend,然后重新运行。

v4l2loopback DKMS 构建失败: 该模块必须针对正在运行的 HWE 内核(目前为 7.0)进行构建。 检查是否安装了 linux-headers-$(uname -r) 并查看 sudo dkms status。安全启动可能会要求您 在下次启动时注册 MOK 密钥。这里的故障仅影响 apt-media 阶段。

docker: permission denied ... docker.sock: docker 组仅在您注销并重新登录后适用。 当前 shell,使用 newgrp docker。

session模块失败,没有注销提示:添加组失败,通常是因为docker 未安装且 docker 组不存在。先修复./bootstrap.sh --only docker,然后运行 ./bootstrap.sh --only session.

~/.system-bootstrap 中的 git status 显示 .files/.zshrc 中的更改: 安装程序在 dotbot 之后运行,并且 附加到链接文件。检查 git -C ~/.system-bootstrap diff .files/.zshrc。移动你想保留的东西 进入 dotfiles/custom.zsh (仅限 Ubuntu)或将其提交到克隆(共享)中,并丢弃其余部分 git -C ~/.system-bootstrap checkout .files/.zshrc。 system-bootstrap-sync.sh 永远不会覆盖此类编辑: 会触及他们的快进会被拒绝并发出警告。

dotfiles 失败,并显示“~/.system-bootstrap 存在,但不是 git 克隆”(或另一个存储库的克隆): 移动该文件 删除目录并重新运行 ./bootstrap.sh --only dotfiles;脚本永远不会删除它。

Super+1..9 不执行任何操作: 其他东西仍然会获取密钥。 tests/assertions/gnome.sh 列出每个 gsettings 持有钥匙Super+N;通常的罪魁祸首是重置或升级后 Ubuntu Dock 的 hot-keys=true(dash-to-dock)。重新运行 ./bootstrap.sh --only gnome.

Super+D 仍然显示桌面/不执行任何操作: 检查 gsettings get org.gnome.desktop.wm.keybindings show-desktop (must not contain <Super>d) and systemctl --用户状态 vicinae (vicinae 切换需要 服务器)。 tests/assertions/vicinae.sh 全部检查。

tool-packages 表示其后端丢失(cargo-binstall、pipx,...):fluxion 在没有 导出PATH。始终通过 ./bootstrap.sh 或 just。

bootstrap.sh 停止于“是 Fluxion X;此存储库需要 0.4.1 或更高版本”:它解决了旧的 Fluxion(来自 fluxion-bin.local 或 ~/.local/bin)。如果 fluxion-bin.local 指向旧版本,请删除它,然后安装 发布为 Fluxion 版本;当 ./bootstrap.sh 发现根本没有通量时,它会自行执行此操作。

校验和或摘要不匹配:上游安装程序已更改。验证新文件并更新引脚(请参阅 正在更新)。

配置文件因无效而被拒绝(退出 3): 运行 just validate 立即查看每个错误及其错误 YAML 路径。

旧仓库:w0rxbend/system-bootstrap · Fluxion 文档:https://worxbend.github.io/fluxion.cr/

相关文章

精彩推荐