OFFSET偏移
← 文章目录OFFSET / FIELD NOTESNO. 005

配置可重现,应用为什么还会“失忆”?

从 GNOME 默认值、Home Manager 激活到 Flatpak 管理范围,分清声明、偏好与数据。

所在专题环境可以重建,状态怎么带走? ↗NixOS 系统基础与配置 ↗
约 10 分钟阅读开始阅读

把软件、服务和桌面选项写进 Nix 配置后,很容易期待“一次重建恢复整个环境”。但环境里还生活着可写偏好、应用数据库、文档和缓存。先找出每类内容由谁管理,才能知道配置能带回什么,以及还缺哪份备份。

声明描述的环境,不等于磁盘的完整快照#

NixOS 配置描述软件和系统服务等目标状态,构建产生相应结果,激活把它接到运行环境。系统代际允许回到旧配置,但不会因此把文档、聊天记录或应用数据库一起恢复到那个时间点。系统回滚与数据恢复是不同机制。[1]

01 / BUILD构建环境
02 / ACTIVATE应用配置
03 / RESTORE恢复数据

也不能直接拿目录划界:同在 ~/.config 下,一些文件可能是 Home Manager 生成的链接,另一些由程序自行写入;dconf 中也可能同时存在声明写入的值与用户通过界面调整的值。位置只是线索,实际管理者与写入时机才是依据。

“运行时状态”不等于无价值,也不等于无法版本化。文本偏好可以选择性导出,业务数据可以备份;只是不能期待一个没有声明或备份它们的系统自动知道该恢复什么。相反,带有密钥、历史记录或机器相关路径的状态,通常不应直接装进公开配置仓库。

GNOME:默认值、用户值与锁定#

GNOME 的 GSettings 为应用提供带类型的设置接口,schema 定义键及默认值,常见的 dconf 后端保存可写设置。用户看到的最终值,可能来自用户数据库,也可能回退到系统提供的值或 schema 默认值。系统管理员还可以通过 dconf profile 组织数据库及锁定规则。[3]

NixOS 的 GNOME 模块提供 extraGSettingsOverrides,用于补充 schema 默认值。下面采用当前模块的选项路径,展示默认显示电量百分比、星期与启用夜灯;它是现有 GNOME 系统配置中的片段,不是一份完整系统配置。[5]

services.desktopManager.gnome.extraGSettingsOverrides = ''
  [org.gnome.desktop.interface]
  show-battery-percentage=true
  clock-show-weekday=true

  [org.gnome.settings-daemon.plugins.color]
  night-light-enabled=true
'';

改默认值不保证覆盖用户已经写入的显式值。这解释了一个常见现象:新账户表现符合预期,旧账户仍保留之前的偏好。此时先检查是否有更高优先级的用户值,而不是把每次“不生效”都归因于构建失败。

默认值也不是锁定。若要求用户不能改变某个键,需要另行设计 dconf locks;普通 schema override 与 Home Manager 写入设置本身都不等价于这一机制。[4]

Home Manager 写入的是一次激活结果#

要表达某个用户的稳定偏好,可以使用 Home Manager 的 dconf.settings。这里路径采用 dconf 的斜线分组;它和 gsettings 命令使用的点分 schema 名看起来相近,但写法不同。

dconf.settings = {
  "org/gnome/desktop/interface" = {
    color-scheme = "prefer-dark";
    clock-show-weekday = true;
    show-battery-percentage = true;
  };
};

当前核对的实现会在激活阶段生成并加载对应设置。它不是持续监视数据库的守护进程:激活之后,若没有其他锁定机制,界面或应用仍可能修改可写值;下一次相应激活又会应用声明。配置的是“何时写入什么”,不能据此宣称设置永远不能变。[2]

仅构建成功,也不能证明这些值已写入当前会话。排查时分别确认:这份 Home Manager 配置是否被使用、是否完成激活、键路径与类型是否正确、当前应用读取到什么。对于数组、枚举和特殊数值类型,要遵守对应 schema,不能只因为 Nix 表达式能求值就判断语义正确。

从声明中删掉一个键时,同样应检查模块的清理语义。该实现会处理此前管理而后来移除的键,不应把删除声明简单理解成“从此永远保留最后写进去的值”。

把界面里试好的偏好,有选择地带回配置#

不必一次性猜出所有设置键。可以先在界面调整一个明确选项,再观察对应的小范围数据,理解后写回配置。下面的命令只针对桌面界面这一组,避免把整个 dconf 数据库连同无关状态全部导出。

gsettings get org.gnome.desktop.interface color-scheme
dconf read /org/gnome/desktop/interface/color-scheme
dconf dump /org/gnome/desktop/interface/ > desktop-interface.ini

gsettings get 通过 schema 接口读设置,dconf read 和 dump 面向 dconf 中的值;它们所回答的问题并不完全相同。缺少显式写入值时,schema 的默认值仍可能让应用得到有效设置。dump 是该子树的设置摘录,不应机械地把它当作“所有与默认值不同的项目清单”。

接下来逐个挑选需要长期保留的键,去掉临时状态和机器相关值,把值转换为模块要求的类型。保留一个小而明确的声明,比把数据库整体复制成一大段看不懂的配置更容易维护。

验证顺序也应清楚:配置能求值和构建,只证明前面的结构成立;完成授权的激活后,还要查询设置并观察应用实际表现。导出文件是观察记录,加入 Git 前仍需审阅内容。

软件安装清单,管理范围也有边界#

把一个包从 environment.systemPackages 中移除,会改变新系统配置提供的那组软件。它不意味着这个程序在整台机器的所有来源都立刻消失:另一个用户 profile、容器或 Flatpak 可能仍提供同名程序,旧代际与 store 中也可能仍有对应对象。判断正在运行哪一个,应检查实际命中路径。

Flatpak 的声明管理尤其适合用来观察“范围”问题。以外部模块 nix-flatpak 为例,假设已经导入对应的 NixOS 模块,可以在配置中声明应用:

services.flatpak = {
  enable = true;
  packages = [ "org.gnome.Calculator" ];
  uninstallUnmanaged = false;
};

这里依赖 nix-flatpak 模块提供 packages 等选项,并非只启用 NixOS 的基础 Flatpak 服务就自动获得这些能力;还需要可用的对应 remote。使用 Home Manager 版本时,应导入该项目的 Home Manager 模块,按用户安装范围理解它。

该模块默认管理声明列出的项目,保留范围内其他手动安装的应用。设置 uninstallUnmanaged = true 才会要求清理未声明项目,而且仍受安装范围约束:系统安装与用户安装不是同一组对象。这个选项改变了清理权限边界,不能当作普通格式偏好随手开启。[6]

应用回来了,内容还要另行恢复#

安装应用与保存应用数据本来就是两条线。普通 Flatpak 卸载可以保留应用数据,带 --delete-data 的卸载会删除其管理的相应数据;应用写到其他位置的文件则可能另外存在。因此,“从清单删除软件”和“清理它的全部个人数据”也不能画等号。[7]

对于笔记、项目、数据库和需要延续的应用状态,应该明确:它存在哪里,备份是否覆盖,恢复时是否要求应用停止写入,目标版本能否读取。只备份启动配置,不会自动包含数据库;只复制数据目录,也不保证跨版本迁移无需处理。

缓存可以按重建成本决定是否保留。能重新生成不等于一定值得每次重建,也不意味着绝对不存在配置接口。把“要不要保留”“如何生成”“谁负责生成”分别回答,比按文件扩展名一刀切更实际。

给每类状态安排一个明确去处#

对象适合的管理方式需要验证的结果
长期使用的软件与服务Nix 声明和依赖锁定构建、激活及实际运行
稳定的桌面偏好挑选键写入相应模块写入时机、优先级与覆盖关系
试验性调整保留观察记录,稳定后再纳入配置是否值得成为长期约定
文档、数据库与重要状态备份、同步及恢复步骤完整性、版本兼容和可读取性
可再生缓存按成本保留或重建恢复耗时是否可接受

整理环境的验收可以具体到一件事:选择一个重要应用,在独立位置验证“软件装回来、设置应用上、数据读得出”这三步。配置仓库与备份各自承担清楚的职责,换机和回滚才有可预测的结果。

参考与延伸

  1. NixOS:系统回滚 ↗
  2. Home Manager dconf 激活实现 ↗
  3. GNOME:dconf profile 与优先级 ↗
  4. GNOME:设置锁定 ↗
  5. NixOS GNOME 模块 ↗
  6. nix-flatpak 的声明与清理范围 ↗
  7. Flathub:卸载与应用数据 ↗

根据技术笔记重新整理,示例使用通用名称。

沿专题继续阅读

环境可以重建,状态怎么带走?

  1. 01配置可重现,应用为什么还会“失忆”?
  2. 02Distrobox 导出的,到底是什么?

NixOS 系统基础与配置

  1. 01NixOS:声明式系统的基础
  2. 02安装 NixOS:介质、分区与初始配置
  3. 03NixOS 配置基础:选项与模块
  4. 04用 Flake 与 Home Manager 管理系统
  5. 05NixOS 命令行:新旧接口与日常维护
  6. 06NixOS 世代管理与垃圾回收
  7. 07Specialisation:一个世代的多个配置变体
  8. 08配置可重现,应用为什么还会“失忆”?
CONTINUE READING / 下一篇Distrobox 导出的,到底是什么?

完整走过 GUI 与 CLI 导出、参数、包装脚本、共享路径、排障和撤销入口。