缘起#
前面几篇介绍了系统配置、用户环境和机密管理。配置保存下来之后,重新安装电脑会方便很多,但自己的文档、照片、数据库和程序运行时产生的数据,并不会随着nixos-rebuild一起恢复。
这个问题和之前介绍的Docker数据卷类似:软件可以重新部署,数据需要另外保存。在上一篇中,解密私钥也属于必须另外保护的内容。
这里先整理NixOS中需要保存的状态,再用restic做一次备份和恢复练习。示例只使用临时目录中的演示文件,不复制私人目录,也不改动已有服务。
系统配置与数据#
可以按用途把需要恢复的内容分成几类:
| 内容 | 恢复方法 |
|---|---|
| Nix文件、flake.lock、自写模块和源文件 | 保存完整配置仓库,包括尚未提交的必要修改 |
| 系统软件与声明的设置 | 用相应输入重新构建,必要时保存构建结果或缓存 |
| 文档、照片、项目中的未提交工作 | 文件备份 |
| 数据库和服务状态 | 应用支持的备份与恢复方法 |
| 解密私钥、备份密码和恢复身份 | 单独保护并检查恢复能力 |
| 分区、文件系统和引导安排 | 安装记录或相应声明,恢复时重新确认 |
/nix/store主要保存软件和构建结果,通常不必作为文件备份的主体。但重新构建还依赖源代码、下载地址和构建资源;有一份锁文件,不等于以后一定能取得所有输入。对难以重新获取或构建的软件,可以另外考虑保留所需store闭包和可用缓存。
/home、服务的数据目录和部分/var/lib内容,则可能是不可重新生成的数据。不要把/var/lib全部当作缓存,也不要不加区分地恢复整套旧系统目录。先查清哪些服务在写入什么,再决定备份范围。
system.stateVersion用于兼容旧状态的默认值,不是数据备份,也不是当前安装版本。更新输入时不要顺便修改它。可以参考NixOS的stateVersion选项。
备份方式简介#
常见方法各有用途:
| 方法 | 适合的用途 | 需要注意的地方 |
|---|---|---|
| Git | 配置和文本修改记录 | 未提交文件、密钥和大规模数据需要另行处理 |
| 文件同步 | 保持多处文件一致 | 删除或损坏也可能同步过去 |
| 文件系统快照 | 快速保存某一时刻的文件状态 | 同一块磁盘上的快照不能应对磁盘丢失 |
| 版本化备份 | 保存多个时间点,恢复误删或旧版本 | 需要检查备份内容、保留策略和恢复方法 |
| 数据库导出或专用备份 | 保存可恢复的应用数据 | 需要相应版本、账户及恢复步骤 |
快照也可以配合复制到另一块磁盘或另一台设备使用。重要数据最好有独立于日常电脑的副本,并考虑异地保存。是否需要不可改写或离线副本,取决于备份账户失窃、误删和勒索软件等情况下会发生什么。
使用restic备份文件#
restic可以将文件保存到加密的备份仓库,保留多个快照,并复用已有数据。这里用本地目录介绍它的基本操作;这个仓库和源文件仍在同一台电脑上,只用于练习,不是完整的备份安排。
准备演示目录#
先打开带restic的Shell:
| |
在同一个Shell中执行:
| |
backup_demo是新建的临时目录。这里的密码只是演示值,真实备份应使用独立的强密码,并将恢复所需的密码保存在其他受保护的位置。演示密码和备份仓库在一起,是为了便于练习,不能照搬到真实备份。
RESTIC_REPOSITORY指定仓库,RESTIC_PASSWORD_FILE指定密码文件;文件内容没有写在命令参数里。仓库初始化方法可以参看restic文档。
创建备份#
| |
init创建一个新的仓库,已有仓库不用重复初始化。backup保存演示源目录;--host demo和--tag tutorial用于区分这组快照。记录命令是否成功,并用snapshots确认时间和路径符合预期。
实际使用时,目录遗漏、权限不足和源文件在读取时变化,都需要查看备份输出和退出状态。不能只看到定时任务运行过,就认为所有文件已经保存。相关行为可以参看restic备份说明。
恢复与比较#
先修改源文件,但不再做第二次备份:
| |
然后将之前的快照恢复到一个新的目录:
| |
这里进入演示目录后,用相对路径source备份,因此恢复文件位于目标目录下面的source/note.txt。备份绝对路径时,恢复目标下面的目录层级会不同,需要按快照中的路径确认。cmp没有输出且退出状态为零,表示恢复出的文件仍然是备份时的version one,不是现在的version two。
latest在这里经过主机和标签过滤,且只有一份演示快照。真实恢复前应先列出快照,确认具体时间、路径和快照ID,避免恢复了错误的备份。目标目录也应先单独准备,不要直接覆盖正在使用的文档或数据库。可以参考restic恢复说明。
仓库检查与保留策略#
| |
普通check检查仓库结构,--read-data还读取并验证备份数据,会消耗更多时间和流量。这两种检查都不能代替实际恢复和应用验证,可以参看仓库检查说明。
保存多个时间点后,还需要规划空间。比如,可以先预览一项保留策略:
| |
这里仅使用--dry-run查看结果,不删除任何快照。这些数字是示例,不是每个人都适用的保留要求。forget移除快照记录,prune回收不再被引用的数据;真正执行前要确认备份范围和恢复需求。规则的分组和时间计算可以参看restic保留策略文档。
数据库与服务备份#
上面的例子是普通文本文件。数据库正在运行时,直接复制它的数据目录,可能得到不能正常恢复的副本。应使用数据库支持的导出、物理备份或一致性快照方法。例如,PostgreSQL提供pg_dump等工具,可以参考官方备份说明。
有些服务同时使用数据库和上传文件。两部分最好来自相容的时间点,并记录对应的应用版本、恢复顺序和所需机密。只恢复数据库或只恢复上传目录,都可能造成记录与文件不匹配。
对于可以短暂停止的小型服务,停写后备份可能比较简单;不能中断的服务需要按它支持的方法安排。文件系统快照可以缩短文件复制时的停顿,但文件层面的一致快照,不一定就是应用层面完整的备份。
恢复测试时,可以先在隔离的实例中导入数据,确认账户、记录、附件和主要功能。避免让测试实例发送邮件、执行计划任务,或写回真实系统。
NixOS定时备份配置#
确认手动备份和恢复都正常后,可以再把任务写进NixOS。下面是一个需要调整后使用的配置片段:
| |
alice是虚构用户,/mnt/backup假设是已经准备好的独立备份介质,密码文件由运行时机密机制提供。这个片段不会创建这些条件,也不能原样用于任意电脑。目录、介质挂载和机密准备顺序都要在实际配置中确认。
initialize = false要求仓库已经初始化;真实介质未挂载时,不能让任务悄悄在系统盘的同名目录里创建仓库。实际配置还应保证目标挂载可用,必要时为生成的服务添加挂载依赖和检查。远程仓库则要处理网络、凭据和访问权限。
OnCalendar = "daily"安排每日运行。Persistent允许定时器重新启用后补跑错过的日历触发,并不会把每个错过的时间点的数据重新找回来。休眠、关机和设备离线时的具体安排,需要按使用习惯检查。
选项和生成的服务可以参看NixOS restic模块。
应用后可以查看:
| |
应检查最近一次成功的时间、退出状态和实际快照,而不是仅仅确认timer存在。日志分享前也要检查是否包含私人路径或其他敏感内容。自动清理与完整数据检查可以在基本任务稳定后另行安排。
系统恢复方法#
恢复电脑时,可以按以下顺序准备:
- 确认恢复介质、配置仓库、备份仓库和所需密钥能取得;
- 重新确认磁盘、分区、文件系统和挂载安排,避免把旧设备路径直接套到新磁盘;
- 用合适的配置和输入重建系统,准备机密;
- 在服务没有写入数据时恢复所需文件,确认所有者和权限;
- 按应用要求恢复数据库和其他状态,再启动服务并验证功能。
这个顺序是准备工作的参考,具体服务可能需要不同的导入步骤。尤其是新版本已经迁移数据库之后,切回旧系统软件并不一定能读取新数据。应保留升级前的可恢复备份,并分别考虑软件回滚和数据恢复。
如果无法从当前电脑访问备份密码、SSH身份或解密私钥,就需要另外的恢复途径。不要让“恢复备份需要的密钥”只存在于“必须先解密才能读取的备份”里。
推荐的使用方法#
我建议先列出真正需要保留的目录和服务状态,再决定备份工具与频率。普通文档可以先用restic练习,数据库和有多个数据来源的服务则分别记录恢复步骤。
每次修改备份范围、服务版本或机密安排后,都应重新检查恢复过程。让AI协助时,可以要求它列出备份了什么、遗漏了什么,以及恢复时还需要哪些条件。恢复和比较先在新目录或隔离实例中完成,确认后再安排真实数据的替换。
下一篇将介绍NixOS服务、容器与网络,包括服务启动关系、数据目录和访问设置的组织方法。
