关于 SafeGrd
SafeGrd 为数据库、目录和 IMAP 邮箱提供加密备份与恢复测试,适合需要检查备份可恢复性并防止误删的运维团队。它提供本地和远程 MCP 服务,且工具不能删除备份。
主要功能
- 01加密并压缩备份
- 02定期恢复演练与校验
- 03支持数据库、目录和 IMAP
- 04破坏性命令前创建锁定快照
- 05恢复数据库或单个文件
适用场景
- 01验证最新备份能否恢复
- 02在数据库变更前保护数据
- 03找回目录中的特定文件
MCP 相关
提供本地 stdio MCP 服务和远程 HTTP MCP 服务。本地服务使用主机配置和密钥执行状态查询、备份、验证、恢复与导出;远程服务可读取备份和演练记录,并请求立即备份或演练。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://safegrd.dev/mcpclaude mcp add --transport http dev-safegrd-safegrd https://safegrd.dev/mcp{"mcpServers":{"dev-safegrd-safegrd":{"type":"http","url":"https://safegrd.dev/mcp"}}}在 Cursor 中打开{"servers":{"dev-safegrd-safegrd":{"type":"http","url":"https://safegrd.dev/mcp"}}}在 VS Code 中打开{"mcpServers":{"dev-safegrd-safegrd":{"type":"http","url":"https://safegrd.dev/mcp"}}}{"mcpServers":{"dev-safegrd-safegrd":{"serverUrl":"https://safegrd.dev/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
https://safegrd.dev/mcp需要授权ghcr.io/safegrd/cli:0.0.29stdio工具
详细介绍
SafeGrd CLI(safegrd)
safegrd 可备份 PostgreSQL、MySQL、MariaDB、MongoDB 和 SQLite 数据库、目录树以及 IMAP 邮箱。每份备份都会在执行备份的主机上使用 zstd 压缩并通过 age 加密,然后写入启用了 Object Lock 的 S3 兼容存储。系统还会按计划还原备份,以检查每个表、行和文件是否都已恢复。
它是 SafeGrd 的 CLI 和守护进程。文档位于 safegrd.dev/docs,所有命令和标志都列在命令参考中。
- 备份从你的主机直接传到存储。 远程服务会收到每份备份的记录(执行时间、大小、摘要和锁定到期日期),以及每次还原测试的签名结果。数据绝不会经过远程服务。
- 由你决定谁持有密钥。 默认情况下,远程服务会密封保存你的密钥,只向已注册的主机释放,因此即使丢失一台主机,你也能还原备份。使用
enroll --key-custody local时,只有你能解密这些备份。 - 还原会经过测试。 Fire Drill 会将最新备份还原到临时数据库或目录中,将其表、行和摘要与备份内容进行比较,并为结果签名。
- Agent 无法删除备份。
safegrd guard会在破坏性命令运行前创建一份已锁定的快照,而个人访问令牌无法删除备份或缩短其锁定时间。
安装
安装脚本(Linux 和 macOS)
curl -fsSL https://safegrd.dev/install.sh | sh
脚本会检测你的操作系统和架构,下载对应的发行版归档文件,将其与该发行版的 checksums.txt 核对,然后把 safegrd 安装到 /usr/local/bin(无法使用 sudo 时则安装到 ~/.local/bin)。此仓库中的脚本是 install.sh;https://raw.githubusercontent.com/safegrd/cli/main/install.sh 提供相同的文件。
在终端中运行时,脚本接着会提示将此机器连接到远程服务:通过浏览器登录、询问由谁持有加密密钥,然后运行 safegrd enroll。登录时会显示一个 URL 和一个代码,你可以在任何设备的浏览器中打开,因此通过 SSH 或 PuTTY 连接的服务器也能以相同方式完成登录。没有终端时(CI、cloud-init、cron),脚本只会安装,不会继续操作。
选项通过环境变量设置,并写在管道后的 sh 命令上。若将它们写在 curl 前面,它们只会应用于 curl,脚本不会获取到这些变量:
curl -fsSL https://safegrd.dev/install.sh | VERSION=v0.0.3 sh # pin a release
curl -fsSL https://safegrd.dev/install.sh | SAFEGRD_INSTALL_DIR=~/.local/bin sh # no sudo
curl -fsSL https://safegrd.dev/install.sh | SAFEGRD_NO_SETUP=1 sh # install only
| 变量 | 作用 |
|---|---|
VERSION | 要安装的发行版标签。默认值:最新发行版。 |
SAFEGRD_INSTALL_DIR | 二进制文件的安装位置。 |
SAFEGRD_NO_SETUP=1 | 仅安装;不提示登录和注册。 |
SAFEGRD_FORCE_INSTALL=1 | 即使已安装指定的发行版,也下载并安装。 |
SAFEGRD_PROJECT | 要将此机器注册到的项目 ID 或标识。 |
SAFEGRD_STORAGE | 项目没有存储桶时,备份的存放位置:hosted 或 local。 |
SAFEGRD_CLAIM | 控制台为此机器显示的认领码。它包含项目、备份存放位置以及要保护的对象,因此注册时会将这些内容写入配置,不再询问。需要使用带有 --claim 选项的 enroll 命令的发行版;较旧的版本会停止并说明原因。 |
SAFEGRD_NODE_NAME | 显示此机器时使用的名称。 |
SAFEGRD_KEY_CUSTODY | local 会将此主机的密钥保存在主机上。不使用该选项时,远程服务会密封保存密钥,并只向已注册的主机释放。 |
SAFEGRD_SERVER_URL | 用于登录和注册的远程服务。默认值:https://safegrd.dev。 |
Homebrew(macOS 和 Linux)
brew install safegrd/tap/safegrd
此 formula 安装的发行版归档文件与脚本安装的相同。
Go
go install github.com/safegrd/cli/cmd/safegrd@latest
容器镜像
ghcr.io/safegrd/cli 可在 linux/amd64 和 linux/arm64 上运行,并包含 pg_dump、mysqldump
和 mongodump,以及 PostgreSQL 18 服务,因此演练可以将数据库恢复到卷上的临时集群中。标签标明
Postgres 客户端版本:<version>-pg18 可读取 Postgres 18 和所有更早版本的服务。发布版本使用 cosign 签名(无密钥,来自此仓库的发布
工作流):
cosign verify ghcr.io/safegrd/cli:<version>-pg18 \
--certificate-identity-regexp 'https://github.com/safegrd/cli/.github/workflows/release.yml@.*' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
packaging/compose 会在数据库旁运行守护进程,
packaging/kubernetes 会以 CronJob 形式运行 daemon run --once,
而 packaging/helm/safegrd 会以 Deployment 形式运行守护进程。
每个配置都标明构建时使用的发布版本,例如 ghcr.io/safegrd/cli:0.0.10;更改
标签即可升级。
发布压缩包,或从源代码构建
Linux 和 macOS(amd64、arm64)的静态二进制文件及其 SHA-256 校验和位于
发布页面。构建方法:
git clone https://github.com/safegrd/cli.git && cd cli
make build
快速入门
1. 创建配置和密钥
如果你让安装脚本连接此机器,则可跳过此步骤:脚本已经写入密钥对和
~/.safegrd/config.yaml,而 init 会拒绝覆盖它们。
# writes an age X25519 keypair and ~/.safegrd/config.yaml
safegrd init \
--database-url "postgres://postgres:password@localhost:5432/myapp_prod" \
--storage local \
--local-path ./backups \
--retention-days 14
2. 连接到远程服务(可选)
# Prints a URL and a code: open it in a browser on any device, including over SSH
safegrd login
# Register this machine, generating its encryption key if it has none.
# --key-custody decides whether the server keeps a copy (safegrd) or not (local)
safegrd enroll --key-custody local
# A host that should encrypt but never decrypt: make the key pair on your laptop,
# then put only the printed public key in the host's encryption.public_key
safegrd keygen --out ~/.safegrd/keys/prod.key
# Headless / CI: a Personal Access Token instead of the browser
safegrd enroll --token "sg_pat_..."
# Or with the claim code the console's setup shows: the project, where backups go and
# the surfaces are written into ~/.safegrd/config.yaml, and the key stays on this machine
safegrd enroll --claim <code>
safegrd doctor # every surface opens from this host; the console shows the result
safegrd daemon run --once
# Later, on an enrolled host: add the surfaces named for it in the console
# (Add surface on its row). Only adds; the old config is kept as config.yaml.bak
safegrd claim
safegrd daemon restart
# Verify the active session
safegrd whoami
3. 备份
# dumps, compresses, encrypts with age on this host, and writes to locked storage
safegrd backup
4. 运行 Fire Drill
# restores into an empty database and checks every table's row count
safegrd verify \
--snapshot snap-20260919-01 \
--sandbox-target "postgres://postgres:password@localhost:5432/ephemeral_test_db"
5. 恢复
safegrd restore \
--snapshot snap-20260919-01 \
--target "postgres://postgres:password@localhost:5432/myapp_recovered"
6. 在一台主机上无人值守地保护多个对象
~/.safegrd/config.yaml 中 surfaces: 下的每个条目都是一个受保护对象,而
safegrd daemon install 会按各自的计划运行它们。surface 的 credential 区块说明
其密钥的来源;配置中不会保存密钥:
surfaces:
- id: app-primary
type: postgres
schedule: "@daily"
credential:
from: env # or: command (with run), file (with path),
name: APP_DATABASE_URL # or safegrd: the remote server holds it for this host
- id: user-uploads
type: files
schedule: "6h"
roots: ["/var/www/uploads"]
safegrd.example.yaml 是带注释的版本。守护进程启动时会读取配置,因此修改后请运行
safegrd daemon restart。
7. 在执行破坏性命令前创建锁定快照
safegrd guard 会备份一个 surface,等待快照上传并锁定,然后
再运行命令。如果备份失败或快照未锁定,则不会运行命令,guard 会以状态码 3 退出。
safegrd guard --surface app-primary -- psql "$APP_DATABASE_URL" -c 'DROP TABLE sessions'
safegrd guard -- terraform destroy
# The commands a hook treats as destructive, and a check that takes no backup
safegrd guard --list
safegrd guard --matches "npx prisma migrate reset" # exit 0: it matches
存储在主机自身磁盘上的快照,或 worm_mode: NONE 的存储桶,无法锁定快照,
因此 guard 会拒绝在这些位置运行,除非传入 --allow-unlocked。
年龄不超过 --max-age 的 surface 锁定快照可代替新备份,因此连续运行多个破坏性命令的
Agent 只需备份一次。--check-only 完全不会执行备份;除非存在这样的快照,否则会拒绝运行命令:
safegrd guard --max-age 30m -- psql "$APP_DATABASE_URL" -c 'TRUNCATE sessions'
safegrd guard --max-age 1h --check-only -- terraform destroy
safegrd list --json 会打印所有快照及其锁定日期,供脚本使用。
8. 备份目录树并取回单个文件
文件备份采用增量方式:每月首次运行时会上传所有文件,此后的每次 运行只会上传有更改的数据块。每个文件的所有保留版本都可以搜索,并且可以单独恢复 单个文件。
safegrd backup --files /srv/app --exclude '*.tmp,node_modules/*'
# every kept version of a file, numbered from the oldest
safegrd find etc/nginx/nginx.conf
# one version of one file, or a directory as it was in one snapshot
safegrd restore --path etc/nginx/nginx.conf --version 2 --target-dir ./out
safegrd restore --snapshot snap-20260919-01 --path 'var/www/**' --target-dir ./out
# every pack present and every listing consistent, without restoring anything
safegrd check --all
# a bucket over the S3 API (Supabase Storage, or any S3-compatible store)
safegrd backup --files s3://avatars --source-endpoint https://PROJECT.storage.supabase.co/storage/v1/s3 \
--source-region eu-central-1 --source-access-key env:S3_KEY --source-secret-key env:S3_SECRET
# and back into the bucket, each object with the content type it had
safegrd restore --snapshot snap-20261012-01 --target s3://avatars --source-endpoint https://PROJECT.storage.supabase.co/storage/v1/s3 \
--source-region eu-central-1 --source-access-key env:S3_KEY --source-secret-key env:S3_SECRET
--format tar 则会为每次备份保留一个压缩包。锁定的内容、锁定时长以及恢复时会取回的内容,请参阅:safegrd.dev/docs/surfaces/files。
AI Agent(MCP)
safegrd 有两个 MCP 服务。两者都没有删除备份、更改备份位置或获取私钥的工具。
本地服务 safegrd mcp 通过 stdio 在主机上运行,并使用该主机的配置和密钥。它的工具有 status、list、doctor、backup、verify、restore 和 export,每个工具都会运行同名命令。restore 只会写入新目录、空目录或空数据库。
claude mcp add safegrd-local -- safegrd mcp
# a host that runs the container image: mount the volume it enrolled with
claude mcp add safegrd-local -- docker run -i --rm \
-v safegrd:/home/safegrd/.safegrd ghcr.io/safegrd/cli mcp
远程服务 https://safegrd.dev/mcp 会读取每台主机的备份和 Fire Drill,并在每个套餐中随时请求执行备份或演练。添加时不填写任何请求头,然后在 Claude Code 中运行 /mcp 并选择 Authenticate:在浏览器中登录 SafeGrd 并批准。
claude mcp add --transport http safegrd https://safegrd.dev/mcp
safegrd/agent-plugins 中的 Claude Code 插件会以相同方式添加同一服务器并登录,还提供技能,可在进行高风险更改前创建备份并运行 Fire Drill:
/plugin marketplace add safegrd/agent-plugins
/plugin install safegrd@safegrd
无法登录的客户端(例如 CI)可从控制台的 Tokens 页面获取个人访问令牌,并将其作为 Authorization: Bearer sg_pat_... 发送。
两个服务均列在 MCP Registry 中,名称为 dev.safegrd/safegrd;远程服务也列在 Smithery 上。Cursor 和 VS Code 配置,以及每个工具的参数:safegrd.dev/docs/mcp。
备份内容
- PostgreSQL,增量备份: 架构来自
pg_dump,行数据则通过二进制COPY从同一快照流式传输,因此数组、枚举、外键、视图、触发器和序列位置都能恢复。每次运行只会上传每张表中发生变化的数据块;restore --table会将所选表载入正在运行的数据库;--change-log则会跳过自上次运行以来没有写入的表。--format tar会为每次备份保留一个归档文件。主机上需要安装版本至少与服务器版本相同的pg_dump。 - SQLite,增量备份: 通过 SQLite 在线备份在一个读取事务中复制,因此 WAL 中尚未提交的事务也会包含在内,写入操作也能继续进行。副本会保留数据库页面的原位布局,因此每次运行只会上传页面发生变化的数据块。
--format tar会为每次备份保留一个归档文件。主机上无需安装任何软件。 - MySQL 和 MariaDB: 使用
mysqldump --single-transaction;MongoDB 使用mongodump --archive,每次备份生成一个归档文件。 - 目录树,增量备份: 每次运行只会上传发生变化的数据块;每个对象写入时都会被锁定一次;
safegrd find会列出文件的所有保留版本,以供restore --path --version使用。 - IMAP 邮箱: 每封邮件均以 RFC 5322 邮件格式保存,并在每次 Fire Drill 中通过 SHA-256 校验。
- 锁定存储: 使用合规模式的 S3 Object Lock,或在可能需要解除锁定时使用治理模式。保存在主机本地磁盘上的数据,以及
worm_mode: NONE的存储桶,都不会锁定备份。 - Fire Drill: 按计划恢复备份、统计恢复结果,并为每次测试的记录签名。
开发
需要 Go 1.25 或更高版本。直接运行 make(不指定目标)会列出所有目标。
make build # compile bin/safegrd
make test # unit and integration tests, race detector
make ci # the exact gate CI runs: gofmt check, tidy check, vet, race tests
make dist # cross-compile release archives + checksums into dist/
make fmt tidy # the developer-facing fixers (these rewrite files; `ci` never does)
CI 会在每次推送和拉取请求时运行 make ci,因此本地运行通过就意味着流水线也会通过。标记 v* 会运行 make dist VERSION=<不含 v 的标签>,并将归档文件和 checksums.txt 发布为 GitHub Release。
许可证
Business Source License 1.1,附带 Additional Use Grant。详见 LICENSE。
简而言之:你可以自由阅读、修改和构建,也可以在任何地方将其用于评估。 任何套餐的 SafeGrd 账户(包括免费套餐)均可用于生产。 无论是否拥有账户,始终允许列出、验证、恢复和导出备份。 每个版本发布四年后将转为 GPL-3.0-or-later。商业许可请联系 [email protected]。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。