Immich 备份脚本实战:基于 Borg 的数据库与媒体库版本化备份方案 Immich 备份脚本实战基于 Borg 的数据库与媒体库版本化备份方案【免费下载链接】immichHigh performance self-hosted photo and video management solution.项目地址: https://gitcode.com/GitHub_Trending/im/immichImmich 官方的docs/docs/guides/template-backup-script.md提供了一套基于 Borg 备份工具 的模板 Bash 脚本用于将照片/视频媒体库与 PostgreSQL 数据库纳入同一套去重、版本化的快照体系中。本文完整继承该文档的初始化、定时任务与恢复流程并结合仓库中的 docker-compose.yml、example.env 以及服务端 database-backup.service.ts 源码解释每个参数的来龙去脉读完你可以直接落地一套“库与库同步、快照可版本化、本地加异地双副本”的自动化备份方案。方案总览为什么选择 BorgBorg 是一个功能丰富的去重归档软件内建版本化versioning能力。官方文档提供的思路是将这套模板脚本作为 cron 任务每天/每周运行一次同时备份文件与数据库。文档特别建议在运行脚本之前先阅读 Borg 的 quick-start 指南理解仓库初始化与加密选项的含义。文档明确给出了这套方案的两点前提假设服务器外接了一块第二块硬盘用于本地on-site备份通过 SSH 可访问一台远程机器用于第三份异地off-site副本。如果暂时没有异地条件可以从模板脚本中直接删除远程相关的行只保留本地备份文档也提到 BorgBase 这类托管服务是异地的替代选项。数据库备份的位置设计先落盘到 UPLOAD_LOCATION再随库一起进快照这是整套脚本最关键的架构决策。数据库的导出结果先写到 Immich 上传目录UPLOAD_LOCATION下的database-backup子目录$UPLOAD_LOCATION/ ├── database-backup/immich-database.sql # pg_dump 导出的最新数据库 ├── upload/ # 用户上传的原始素材 ├── profile/ # 用户头像 ├── thumbs/ # 缩略图快照中排除 └── encoded-video/ # 转码视频快照中排除随后 Borg 把UPLOAD_LOCATION整体纳入快照数据库文件与媒体素材进入同一个快照、同一个时间点。这保证了每个快照里“数据库与素材始终一致”避免了先备文件后备库或反之导致的引用错位问题——官方备份文档 中也强调数据库与文件系统备份失配是恢复后出现“坏资产”的典型原因。UPLOAD_LOCATION正是安装时 example.env 中定义的变量默认./library并在 docker-compose.yml 中以${UPLOAD_LOCATION}:/data挂载进immich_server容器。也就是说你只需把example.env里实际配置的上传路径填进脚本即可。与 Immich 内置自动数据库备份的关系文档用醒目提示说明这个脚本备份数据库 媒体库与 Immich内置的自动数据库备份工具见 backup-and-restore.md 的 Automatic Database Backups 一节默认保留最近 14 份、每天 2:00 生成存放在UPLOAD_LOCATION/backups功能重叠。使用本脚本相比内置工具有两个优势存储效率更高Borg 通过版本化去重管理备份而不是不断产生完整拷贝时序一致数据库与媒体库在同一时刻备份任意快照中二者永远同步。从源码看内置备份由DatabaseBackupService驱动它在ConfigInit事件里依据管理面板配置的backup.database注册 cron 任务执行时内部调用pg_dump见 buildPostgresLaunchArguments 与 handleBackupDatabase完成后清理过期备份。两条路径最终都是pg_dump逻辑备份因此使用本脚本后可以安全地在管理面板关掉内置自动备份以节省空间。前置条件Prerequisites文档列出的三项前置要求Borg 必须安装在服务器与远程机器上官方文档引导安装此处不展开外部链接可选以非 root 用户运行需要把该用户加入 docker 组否则无法执行脚本中的docker exec免密 SSH若脚本要非交互运行需从服务器到远程机器配置 passwordless ssh如果上一步没有加入 docker 组请确保本步骤在 root 账号下完成。初始化 Borg 仓库一次性操作在跑定时任务前先执行一次仓库初始化。注意UPLOAD_LOCATION的值要与.env中 Immich 实际使用的数据库/上传位置一致即UPLOAD_LOCATION变量指向的宿主机路径UPLOAD_LOCATION/path/to/immich/directory # Immich database location, as set in your .env file BACKUP_PATH/path/to/local/backup/directory mkdir $UPLOAD_LOCATION/database-backup borg init --encryptionnone $BACKUP_PATH/immich-borg ## Remote set up REMOTE_HOSTremote_hostIP REMOTE_BACKUP_PATH/path/to/remote/backup/directory borg init --encryptionnone $REMOTE_HOST:$REMOTE_BACKUP_PATH/immich-borg逐行说明mkdir $UPLOAD_LOCATION/database-backup预先创建数据库导出落盘目录后续pg_dump重定向写入它borg init --encryptionnone初始化本地Borg 仓库。示例使用--encryptionnone不加密是为了简化演示生产环境如果备份盘存在泄露风险可考虑改用repokey/keyfile加密这属于 Borg 自身的能力选择文档模板默认 none远程同理通过userhost:path语法在远端初始化第二个仓库形成本地异地双副本。每日/每周执行的备份模板脚本文档给出的完整模板如下。按说明路径中不能包含:、、字符否则需要转义或重命名这是因为 Borg 的仓库位置格式host:path::archive依赖:与::做分隔符#!/bin/sh # Paths UPLOAD_LOCATION/path/to/immich/directory BACKUP_PATH/path/to/local/backup/directory REMOTE_HOSTremote_hostIP REMOTE_BACKUP_PATH/path/to/remote/backup/directory ### Local # Backup Immich database docker exec -t immich_postgres pg_dump --clean --if-exists --dbname DB_DATABASE_NAME --usernameDB_USERNAME $UPLOAD_LOCATION/database-backup/immich-database.sql # For deduplicating backup programs such as Borg or Restic, compressing the content can increase backup size by making it harder to deduplicate. If you are using a different program or still prefer to compress, you can use the following command instead: # docker exec -t immich_postgres pg_dump --clean --if-exists --dbname DB_DATABASE_NAME --usernameDB_USERNAME | /usr/bin/gzip --rsyncable $UPLOAD_LOCATION/database-backup/immich-database.sql.gz ### Append to local Borg repository borg create $BACKUP_PATH/immich-borg::{now} $UPLOAD_LOCATION --exclude $UPLOAD_LOCATION/thumbs/ --exclude $UPLOAD_LOCATION/encoded-video/ borg prune --keep-weekly4 --keep-monthly3 $BACKUP_PATH/immich-borg borg compact $BACKUP_PATH/immich-borg ### Append to remote Borg repository borg create $REMOTE_HOST:$REMOTE_BACKUP_PATH/immich-borg::{now} $UPLOAD_LOCATION --exclude $UPLOAD_LOCATION/thumbs/ --exclude $UPLOAD_LOCATION/encoded-video/ borg prune --keep-monthly3 --keep-weekly4 $REMOTE_HOST:$REMOTE_BACKUP_PATH/immich-borg borg compact $REMOTE_HOST:$REMOTE_BACKUP_PATH/immich-borg把这段脚本放入你的 crontab 即可文档未规定具体调度频率daily/weekly 均可按数据增长速度取舍。数据库导出pg_dump 的参数细节模板中的核心一行docker exec -t immich_postgres pg_dump --clean --if-exists \ --dbname DB_DATABASE_NAME --usernameDB_USERNAME \ $UPLOAD_LOCATION/database-backup/immich-database.sqlimmich_postgres是 docker-compose.yml 中database服务固定的container_name脚本因此可以直接 exec 进容器执行pg_dumpDB_DATABASE_NAME与DB_USERNAME对应.env中的DB_DATABASE_NAME默认immich与DB_USERNAME默认postgres见 example.env--clean让 dump 内含DROP语句、--if-exists避免 DROP 时报错二者配合使导出的 SQL 可在全新库上直接回放文档注释特别说明对 Borg/Restic 这类去重备份程序压缩反而会增大备份体积压缩使相邻快照字节序列趋同困难、削弱去重效果因此默认不压缩如果你用别的备份工具、或坚持要压缩则改用注释里给出的gzip --rsyncable管道版本。从源码结构看Immich 内置备份走的是容器内/usr/lib/postgresql/version/bin/pg_dump见 database-backup.service.ts 与对应测试快照 database-backup.service.spec.ts与脚本里docker exec的pg_dump是同一工具的不同入口恢复方式因此完全通用。Borg create / prune / compact 三件套每条快照流程都是固定的三步命令作用borg create repo::{now} path --exclude ...创建一个以当前时间命名Borg 内置{now}占位符的新快照borg prune --keep-weekly4 --keep-monthly3 repo按保留策略裁剪旧快照保留最近 4 份周快照 3 份月快照borg compact repo压缩 Borg 仓库回收碎片空间两个--exclude值得注意排除了$UPLOAD_LOCATION/thumbs/与$UPLOAD_LOCATION/encoded-video/。这与 官方备份文档的 Filesystem 一节 的存储布局一致——thumbs缩略图和encoded-video转码视频都属于可再生内容真正关键的是upload/library原始素材、profile头像和数据库本身。排除二者可以显著减小快照体积恢复后如需重建需要重跑转码与缩略图生成任务文档原文提示了这一点。--keep-weekly4 --keep-monthly3只是模板值可按保留策略自行调整。恢复Restoring恢复走borg mount把仓库挂载为目录每个快照是挂载点下的一个子目录按需取文件最后卸载。从本地备份恢复BACKUP_PATH/path/to/local/backup/directory mkdir /tmp/immich-mountpoint borg mount $BACKUP_PATH/immich-borg /tmp/immich-mountpoint cd /tmp/immich-mountpoint从远程备份恢复REMOTE_HOSTremote_hostIP REMOTE_BACKUP_PATH/path/to/remote/backup/directory mkdir /tmp/immich-mountpoint borg mount $REMOTE_HOST:$REMOTE_BACKUP_PATH/immich-borg /tmp/immich-mountpoint cd /tmp/immich-mountpoint在/tmp/immich-mountpoint下可以看到各个时间点的快照子目录。选取所需快照后把upload、profile、database-backup等目录内容复制回新的UPLOAD_LOCATION注意如果你的profile/等目录曾拆分到别的存储设备恢复路径要按实际部署调整。数据库部分把快照里的database-backup/immich-database.sql通过psql灌回新库即可官方文档给出的灌库命令带search_path修正与单事务保护可参考 backup-and-restore.md 的命令行恢复小节。全部完成后执行borg umount /tmp/immich-mountpoint卸载仓库。要点回顾与适用边界这套方案适合已用 Docker Compose 部署 Immich、希望一条 cron 脚本同时覆盖数据库与媒体库的场景脚本强依赖docker exec immich_postgres因此服务器必须能访问 Docker 守护进程root 或将运行用户加入 docker 组模板假设路径中无:、、字符{now}时间戳、--keep-weekly4 --keep-monthly3保留策略、以及本地/异地双写都是可按需修改的参数与内置备份二选一即可使用本脚本后建议在管理面板关闭自动数据库备份避免在UPLOAD_LOCATION/backups中持续累积冗余拷贝本文所有事实均出自 template-backup-script.md 原文及其引用的 backup-and-restore.md、example.env、docker-compose.yml 与 database-backup.service.ts未涉及仓库之外的假设。【免费下载链接】immichHigh performance self-hosted photo and video management solution.项目地址: https://gitcode.com/GitHub_Trending/im/immich创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考