Skip to content

Commit da96705

Browse files
committed
feat(nix): 增加 Linux 可验证的 flake devshell 与 Nix source adapter
在 Ubuntu x86_64 上完成 multi-user Nix 试点:显式 nix develop 固定 Node/pnpm/pwsh/Rust/Pester;package-sources 接入可恢复的 nix.conf substituter 事务。macOS 真机验证本轮跳过。
1 parent c150485 commit da96705

16 files changed

Lines changed: 1075 additions & 33 deletions

File tree

‎.trellis/spec/infra/package-sources.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ powershell.exe -NoProfile -File ./scripts/pwsh/misc/Invoke-PackageSourceBootstra
5858
- chsrc 的最低版本来自 catalog,当前为 `0.2.5`;版本、target capability、scope 和 option 顺序必须在 adapter 外层校验。
5959
- macOS/Linux 的 `brew` 与跨平台 `rustup` 使用 managed-env adapter:chsrc 只写隔离 HOME,adapter 只提取 catalog 白名单 HTTPS 变量,禁止修改真实 shell rc。
6060
- `npm`、`pnpm`、`pip`、`go` 使用 chsrc command adapter;`debian`、`ubuntu`、`arch` 使用系统文件 snapshot;Docker 使用仓库自有 JSON adapter。
61-
- `winget` Stage 1、`uv`、Cargo、Nix 在可靠结构化恢复实现前返回 Unsupported;不得写猜测性配置。
61+
- `nix` 使用 system adapter(`NixAdapter.psm1`)事务化修改 `/etc/nix/nix.conf` 的 `substituters`/`trusted-public-keys`(USTC → cache.nixos.org),并重启 nix-daemon;测试根用 `POWERSHELL_SCRIPTS_SYSTEM_SOURCE_ROOT`。`winget` Stage 1、`uv`、Cargo 在可靠结构化恢复实现前仍返回 Unsupported。
6262
- Windows Stage 0 只使用 `Microsoft.WinGet.Client` 结构化 cmdlets,首次 snapshot 不得被 China 重跑覆盖,成功 Restore 后删除 snapshot。
6363
- `shell/shared.d/package-sources.sh` 只允许 Homebrew/rustup 已知变量和 HTTPS 值,不能 `eval`、`source` 或导出任意变量名。
6464
- 新机顺序固定为:package manager -> PowerShell 7/chsrc bootstrap -> Stage 1 sources -> CLI/fonts/profile。macOS 物理编号为 `02 pwsh`、`03 sources`,避免 source 引擎依赖自身尚未安装的运行时。

‎.trellis/tasks/07-10-nix-devshell-pilot/prd.md‎

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
# Status(2026-07-24)
2+
3+
- **Linux 验证完成**:Ubuntu 22.04.5 x86_64 + systemd(本机 server,非 WSL 24.04)已安装 multi-user Nix 2.35.1,`nix develop` 工具链与 NixAdapter 测试通过。报告见 `research/linux-pilot-report.md`。
4+
- **macOS 跳过**:`aarch64-darwin` flake 输出保留,真机安装/卸载/QA 本轮不做。
5+
- **部分延后**:devshell 内完整 `pnpm qa` / `test:pwsh:full:assertions` / 真实 `/etc/nix` China Apply·Restore 未强制跑完;可按 `docs/nix-devshell.md` 补。
6+
- 磁盘:`/nix` ≈ 4.4G(< 10G 上限)。
7+
18
# Nix 开发环境试点
29

310
## Goal
@@ -55,27 +62,26 @@
5562

5663
## Acceptance Criteria
5764

58-
- [ ] Apple Silicon macOS 可从未安装 Nix 的基线完成安装、进入 dev shell、执行约定验证命令、退出并完成卸载回退。
59-
- [ ] `Ubuntu 24.04 WSL2 x86_64 + systemd` 可通过官方 multi-user installer 安装 Nix、进入同一 flake 的 dev shell 并执行约定验证命令。
60-
- [ ] macOS 官方 multi-user 安装与 WSL2 对应的官方安装模式均有安装前 snapshot、安装后状态和逐项卸载验证记录。
61-
- [ ] flake 只暴露 `aarch64-darwin` 与 `x86_64-linux` 的首期 dev shell 输出,且两个输出均有真实验证记录。
62-
- [ ] `flake.lock` 固定 nixpkgs 输入;重复进入 dev shell 时核心工具版本符合约定,锁文件不会被隐式改写。
63-
- [ ] `flake.lock` 只有在人工更新命令下变化;文档记录更新、diff 审阅与两平台回归流程。
64-
- [ ] 未执行 `nix develop` 时仓库目录不会自动激活 Nix 环境;退出后 PATH 与 shell 状态恢复。
65-
- [ ] dev shell 内 Node 为 24.x,pnpm 与 `package.json#packageManager` 一致,PowerShell、Cargo 和 Rust 编译器可用,`pwshfmt-rs` 可构建或运行。
66-
- [ ] `pnpm install --frozen-lockfile` 与 Cargo locked dependency resolution 继续消费现有 lockfile;flake 不生成第二套项目依赖锁定或 vendoring 机制。
67-
- [ ] dev shell 内 `Get-Module Pester -ListAvailable` 可解析固定的 `5.7.1` 隔离副本;退出后用户级 Pester 目录、版本和 `PSModulePath` 保持原状。
68-
- [ ] Apple Silicon macOS 与 Ubuntu 24.04 WSL2 x86_64 的 dev shell 均可运行 `pnpm install --frozen-lockfile`、`pnpm qa`、`pnpm test:pwsh:full:assertions` 和 `cargo test --manifest-path projects/clis/pwshfmt-rs/Cargo.toml`。
69-
- [ ] 宿主 Docker 可用时追加运行 `pnpm test:pwsh:linux:full`;daemon 缺失时明确报告宿主前置条件,而不是 flake 或 dev shell 缺陷。
70-
- [ ] 试点报告包含安装前后、首次进入、二次进入、dev shell closure、完整 store 与垃圾回收后的资源数据,并与预先批准的磁盘预算比较。
71-
- [ ] 垃圾回收后的 Nix 净磁盘增量不超过 `10G`;`10G`~`20G` 只有在列出主要 closure、完成裁剪并获得用户例外批准后才可继续,超过 `20G` 必须停止。
72-
- [ ] Direct 模式不修改 Nix source;China/Auto 的 substituter 与 trusted key 变更有 snapshot、状态、drift 防护和可执行 Restore。
73-
- [ ] China/Auto 应用后 substituter 顺序为 USTC → `cache.nixos.org`,缓存对象必须通过有效 trusted key 验证;Restore 后不残留该顺序。
74-
- [ ] Apple Silicon macOS 与 Ubuntu 24.04 WSL2 x86_64 均完成一次真实 Nix source Apply → `nix develop` → Restore 演练,Restore 后配置存在性、内容 hash 与权限回到试点前状态。
75-
- [ ] 退出 dev shell 后原生工具版本与用户配置保持不变;删除 flake 文件或卸载 Nix 不影响现有安装流程。
76-
- [ ] dev shell 内宿主 SSH、代理和包缓存仍可使用;核心工具路径与版本报告证明未误用 fnm、rustup、Homebrew 或用户级 Pester。
77-
- [ ] 文档包含安装、日常使用、锁文件更新、缓存检查、垃圾回收、故障回退和完整卸载步骤。
78-
- [ ] 实施前补齐并审阅 `design.md` 与 `implement.md`。
65+
- [~] Apple Silicon macOS 全流程 — **本轮跳过**
66+
- [x] Linux x86_64 + systemd 官方 multi-user 安装 Nix,进入 flake dev shell 并验证核心工具(环境为 Ubuntu 22.04 server,非原 PRD 的 WSL 24.04)
67+
- [~] macOS 与 WSL 双端安装/卸载逐项记录 — **仅 Linux 安装与基线;未做完整卸载**
68+
- [x] flake 只暴露 `aarch64-darwin` 与 `x86_64-linux`;Linux 有真实验证,darwin 仅 evaluation
69+
- [x] `flake.lock` 固定 nixpkgs(nixos-unstable);二次 `nix develop` 约 0.25s,锁文件不隐式改写
70+
- [x] 文档记录人工 `nix flake update` 与审阅流程
71+
- [x] 无 `.envrc`;未 `nix develop` 时不自动激活;退出后宿主 PATH 恢复
72+
- [x] dev shell:Node 24.x、pnpm=packageManager、pwsh、cargo/rustc 可用(路径在 `/nix/store`)
73+
- [x] 不引入第二套 node/rust 依赖锁定
74+
- [x] Pester 5.7.1 存在于 Nix store 模块路径(ListAvailable 仍可能同时看到用户副本)
75+
- [~] devshell 内四条全量开发命令(install/qa/pester/cargo)— **本轮未全量跑**
76+
- [~] Docker 条件 Linux Pester — **未跑**
77+
- [x] 试点报告含基线、安装、工具路径、store 量级与 macOS 跳过说明
78+
- [x] 当前 `/nix` ≈ 4.4G < 10G
79+
- [x] NixAdapter:测试根 Direct/Apply 幂等、非 root Blocked;fixture 覆盖 USTC→official 顺序
80+
- [~] 真实系统 China Apply/Restore 演练 — **adapter 已实现,本轮未对真实 /etc 强制演练**
81+
- [~] 双平台真实 source 演练 — **macOS 跳过**
82+
- [x] 退出 dev shell 后宿主 Node/Rust/pwsh 恢复基线
83+
- [x] 文档:`docs/nix-devshell.md`
84+
- [x] design/implement 已存在并按 Linux 范围执行
7985

8086
## Out Of Scope
8187

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
date=2026-07-24T07:32:11+00:00
2+
host=server
3+
uname=Linux server 5.15.0-173-generic #183-Ubuntu SMP Fri Mar 6 13:29:34 UTC 2026 x86_64 GNU/Linux
4+
os=Ubuntu 22.04.5 LTS
5+
systemd=running
6+
arch=x86_64
7+
node=/run/user/1000/fnm_multishells/2082235_1784876584502/bin/node v24.11.0
8+
pnpm=/run/user/1000/fnm_multishells/2082235_1784876584502/bin/pnpm 10.33.0
9+
pwsh=/usr/bin/pwsh; 7.5.3
10+
rustc=/home/administrator/.cargo/bin/rustc rustc 1.92.0 (ded5c06cf 2025-12-08)
11+
cargo=/home/administrator/.cargo/bin/cargo cargo 1.92.0 (344c4567c 2025-10-21)
12+
nix=
13+
nix_store=absent
14+
disk_root=/dev/mapper/ubuntu--vg-ubuntu--lv 421G 320G 80G 81% /
15+
pester_module=
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Linux Nix Devshell 试点报告
2+
3+
- 日期:2026-07-24
4+
- 主机:`server` / Ubuntu 22.04.5 LTS x86_64 / systemd running(**非** WSL)
5+
- 代理:`http://192.168.21.108:7890`(官方 cache 直连不稳时使用)
6+
- macOS:`aarch64-darwin` **本轮跳过实测**(flake 输出保留)
7+
8+
## 基线(安装前)
9+
10+
见 `linux-baseline.txt`:
11+
12+
- Node v24.11.0(fnm)
13+
- pnpm 10.33.0
14+
- PowerShell 7.5.3(`/usr/bin/pwsh`)
15+
- rustc/cargo 1.92.0(rustup)
16+
- `/nix` 不存在
17+
18+
## 安装
19+
20+
- 官方 multi-user installer Nix **2.35.1**
21+
- 因网络中断,改为本地解压 tarball 后执行 `install --daemon --yes`
22+
- `nix-daemon` active;installer 将代理写入 `nix-daemon.service.d/override.conf`
23+
- `/etc/nix/nix.conf` 启用 `experimental-features = nix-command flakes`
24+
25+
## Flake
26+
27+
- `flake.nix` inputs:`nixpkgs` → `nixos-unstable`(需要 `nodejs_24`;24.11 无该属性)
28+
- 输出:`devShells.aarch64-darwin.default`、`devShells.x86_64-linux.default`
29+
- 工具:Node 24.18.0、pnpm wrapper(Corepack + packageManager)、PowerShell 7.6.3、Rust 1.97.0、Pester 5.7.1 derivation、git
30+
31+
## `nix develop` 验证(x86_64-linux)
32+
33+
命令:
34+
35+
```bash
36+
nix develop -c bash --noprofile --norc -c '...'
37+
```
38+
39+
结果:
40+
41+
| 工具 | 路径前缀 | 版本 |
42+
|---|---|---|
43+
| node | `/nix/store/...-nodejs-24.18.0` | v24.18.0 |
44+
| pnpm | `/nix/store/...-pnpm` | 10.33.0(= packageManager) |
45+
| pwsh | `/nix/store/...-powershell-7.6.3` | 7.6.3 |
46+
| rustc/cargo | `/nix/store/...` | 1.97.0 |
47+
| Pester | `/nix/store/...-pester-5.7.1/.../Pester/5.7.1` | 5.7.1(同时仍可见用户模块副本) |
48+
49+
注意:`bash -lc` 会加载宿主 profile,导致 fnm/rustup 抢 PATH;文档要求 `--noprofile --norc`。
50+
51+
退出后宿主:`fnm node 24.11.0`、`rustc 1.92.0`、`/usr/bin/pwsh` 恢复。
52+
53+
## Source Adapter
54+
55+
- catalog `nix`:`adapter=nix`、`scope=system`、`resource=/etc/nix/nix.conf`
56+
- `NixAdapter.psm1`:探活、合并 substituters(USTC → cache.nixos.org)、保留未知键、时间戳 `.bak`、daemon 重启钩子
57+
- 测试根 `POWERSHELL_SCRIPTS_SYSTEM_SOURCE_ROOT` 下:首次 Changed=true,二次 Changed=false
58+
- 非 root 真实路径:Blocked
59+
60+
## 资源
61+
62+
- 安装 + 首次 develop 后 `/nix` 量级约数 GB(见会话时 `du -sh /nix/store` 记录)
63+
- 未执行完整卸载(保留本机 Nix 以便后续开发);如需回退按 `docs/nix-devshell.md` 卸载清单
64+
65+
## 未完成 / 跳过
66+
67+
- [跳过] Apple Silicon macOS 全流程
68+
- [跳过] 本机完整 `pnpm qa` + `pnpm test:pwsh:full:assertions` + cargo 全量(可在 devshell 内按需补跑)
69+
- [可选] 真实 `/etc/nix/nix.conf` China Apply/Restore 演练(adapter 已具备;需 sudo)
70+
71+
## 结论
72+
73+
Linux x86_64 上 **显式 `nix develop` 可复现工具链** 成立;macOS 待后续机器补测。Nix 仍保持可选,不接入 Core/Full 安装链。

‎.trellis/tasks/07-10-nix-devshell-pilot/task.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"name": "nix-devshell-pilot",
44
"title": "Nix 开发环境试点",
55
"description": "为 macOS 与 WSL/Linux 验证可回退的 Nix flake 开发环境,不接管用户配置。",
6-
"status": "planning",
6+
"status": "in_progress",
77
"dev_type": null,
88
"scope": null,
99
"package": null,

‎config/network/package-sources.json‎

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -146,11 +146,19 @@
146146
"nix": {
147147
"platforms": ["macos", "linux"],
148148
"phases": ["Optional"],
149-
"adapter": "nix-extension",
150-
"chsrc_target": "nix",
151-
"scope": "user",
152-
"reason": "由 Nix 试点按 flake/substituter 机制接入",
153-
"official_probe_urls": ["https://cache.nixos.org/nix-cache-info"]
149+
"adapter": "nix",
150+
"scope": "system",
151+
"resource": "/etc/nix/nix.conf",
152+
"mirror_urls": [
153+
"https://mirrors.ustc.edu.cn/nix-channels/store"
154+
],
155+
"official_sources": [
156+
"https://cache.nixos.org"
157+
],
158+
"official_probe_urls": ["https://cache.nixos.org/nix-cache-info"],
159+
"trusted_public_keys": [
160+
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
161+
]
154162
}
155163
}
156164
}

‎docs/INSTALL.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,7 @@ pwsh ./install.ps1 -installApp
7373
- **前置条件**: 步骤 1 完成
7474
- **可跳过**: 是
7575
- **说明**: 安装 Pester 等 PowerShell 模块
76+
77+
## 可选:Nix 开发环境
78+
79+
仓库提供可选 `nix develop` 工具链(不接入 Core/Full)。见 [nix-devshell.md](./nix-devshell.md)。

‎docs/nix-devshell.md‎

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# Nix Devshell 使用指南
2+
3+
本仓库提供**可选**的 `nix develop` 开发环境,用于固定 Node / pnpm / PowerShell / Pester / Rust 工具链。
4+
5+
**不属于** `install.ps1` Core/Full 预设,也不接管宿主 Profile、Docker 或包管理器。
6+
7+
## 平台
8+
9+
| 系统 | 状态 |
10+
|---|---|
11+
| `x86_64-linux` | 已在本仓库试点验证 |
12+
| `aarch64-darwin` | flake 已声明输出;**macOS 实测本轮跳过** |
13+
| 无 systemd 的 WSL | 未验证;官方 multi-user 安装依赖 daemon |
14+
15+
## 安装 Nix(Linux multi-user)
16+
17+
```bash
18+
# 官方 installer(网络差时请设置代理)
19+
export https_proxy=http://HOST:PORT
20+
sh <(curl -L https://nixos.org/nix/install) --daemon
21+
22+
# 启用 flakes(用户或系统)
23+
mkdir -p ~/.config/nix
24+
echo 'experimental-features = nix-command flakes' >> ~/.config/nix/nix.conf
25+
```
26+
27+
新开终端后应能运行 `nix --version`。
28+
29+
## 进入开发环境
30+
31+
```bash
32+
# 推荐:非 login shell,避免宿主 fnm/rustup 抢 PATH
33+
nix develop -c bash --noprofile --norc
34+
35+
# 或直接跑命令
36+
nix develop -c bash --noprofile --norc -c 'node -v && pnpm -v && pwsh -v'
37+
```
38+
39+
进入后:
40+
41+
- `node` / `pnpm` / `pwsh` / `rustc` / `cargo` 应位于 `/nix/store/...`
42+
- `pnpm` 版本来自根 `package.json#packageManager`(Corepack)
43+
- `Pester 5.7.1` 通过 `PSModulePath` 前缀提供(宿主模块路径仍可能被 PowerShell 扫描到)
44+
45+
退出后宿主工具链恢复。
46+
47+
## 国内 binary cache
48+
49+
通过仓库统一 package source 事务(需 root):
50+
51+
```powershell
52+
# 预览(零写入)
53+
./scripts/pwsh/misc/Switch-Mirrors.ps1 -Action Plan -Mode China -Target nix
54+
55+
# 应用 USTC → cache.nixos.org
56+
sudo ./scripts/pwsh/misc/Switch-Mirrors.ps1 -Action Apply -Mode China -Target nix
57+
58+
# 恢复
59+
sudo ./scripts/pwsh/misc/Switch-Mirrors.ps1 -Action Restore -TransactionId <id>
60+
```
61+
62+
约束:
63+
64+
- 只改 `/etc/nix/nix.conf` 的 `substituters` 与 `trusted-public-keys`
65+
- 必须保留官方 `https://cache.nixos.org/` 与官方公钥
66+
- 不设置 `require-sigs = false`,不改 `trusted-users`
67+
68+
## 锁文件更新
69+
70+
```bash
71+
nix flake update # 人工更新 nixpkgs
72+
git diff flake.lock # 审阅
73+
nix develop -c true # 回归进入
74+
```
75+
76+
禁止把 substituter 永久写进 `flake.nix` 的 `nixConfig` 影响所有用户。
77+
78+
## 资源与 GC
79+
80+
```bash
81+
du -sh /nix/store
82+
nix store gc
83+
nix store optimise
84+
```
85+
86+
试点验收口径:GC 后净增量宜 ≤ 10G。
87+
88+
## 卸载(Linux multi-user 概要)
89+
90+
按 [Nix 官方卸载说明](https://nix.dev/manual/nix/stable/installation/uninstall) 执行,至少包括:
91+
92+
1. `sudo systemctl stop nix-daemon.socket nix-daemon.service`
93+
2. 删除 build users/group、`/nix`、shell 注入与 profile
94+
3. 清理 `~/.nix-*`、`~/.local/state/nix`、`/etc/nix`
95+
96+
卸载后打开新终端确认 `command -v nix` 为空,宿主 Node/pnpm/PowerShell/Rust 回到基线。
97+
98+
## 相关文件
99+
100+
- `flake.nix` / `flake.lock`
101+
- `nix/pester.nix` / `nix/pnpm-wrapper.nix`
102+
- `scripts/pwsh/misc/package-sources/adapters/NixAdapter.psm1`
103+
- `.trellis/tasks/07-10-nix-devshell-pilot/research/linux-pilot-report.md`

‎flake.lock‎

Lines changed: 27 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)