Herkos

你自己的 Blossom 服务器

最后更新:2026 年 10 月 27 日

Herkos Drive 把每个文件切成加密的块,并保存在多个 Blossom 服务器上:三份副本,至少分布在两类 服务器上,并且其中一份在你自己的服务器上。公共服务器免费保存块,但它们不作任何承诺:它们 可能清除这些块、存满,或者关闭。

一个你自己的 Blossom 服务器会按你决定的时长保存你的副本,并且只接受来自你的 Drive 的块。本页 介绍如何分三步搭建一个这样的服务器,外加每晚备份。它很适合与你自己的邮箱中继搭配 使用;如果你已经有服务器,大约需要十五分钟。

选用哪个服务器

blossom-server,作者 hzrd149,版本 6.4.1 (2026 年 10 月 6 日,MIT 许可证)。我们在 2026 年 10 月 27 日用下面的配置和 Drive 自己的上传 代码运行了它,检验的是 Drive 需要什么,而不是服务器宣传的内容:

Drive 做什么 结果
上传 8 MiB 的加密块(application/octet-stream) 接受
上传前先询问(BUD-06) 会回答,并拒绝其他任何密钥
请你的服务器从公共服务器复制一个块(BUD-04) 已复制
不验明身份读取一个块 原样提供,逐字节一致
用上传它的密钥删除一个块 已删除:再次请求返回 404
用其他任何密钥上传 拒绝(401)

你需要什么

第 1 步:运行服务器

为它建一个文件夹,例如 /root/blossom,并把下面两个文件保存在里面。第一个是 docker-compose.yml:

services:
  blossom:
    image: ghcr.io/hzrd149/blossom-server:6.4.1
    environment:
      BLOSSOM_REQUIRE_CONFIG: "1"
    ports:
      - "127.0.0.1:3000:3000"
    volumes:
      - data:/app/data
      - ./config.yml:/app/config.yml:ro
    restart: unless-stopped
volumes:
  data: {}

第二个是 config.yml。把你的域名填入 publicDomain,把你的卷密钥填在写着 YOUR-VOLUME-KEY 的地方:

port: 3000
host: 0.0.0.0
publicDomain: blossom.example.com
storage:
  backend: local
  local:
    dir: ./data/blobs
  rules:
    - type: "*"
      expiration: 100 years
      pubkeys:
        - "YOUR-VOLUME-KEY"
upload:
  requireAuth: true
  maxSize: 104857600
  requirePubkeyInRule: true
mirror:
  enabled: true
  requireAuth: true
delete:
  requireAuth: true
list:
  enabled: false
media:
  enabled: false
report:
  enabled: false
landing:
  enabled: false

这份配置的含义是:只有你的卷密钥可以上传或请求复制(requirePubkeyInRule),并且一个块会一直 保存,直到 Drive 删除它。服务器要求每条规则都有过期时间;连续 100 years 未被读取才过期,实际上 就等于永不过期,而且 Drive 本来就会定期读取它的块。端口只在本机上监听(127.0.0.1):所有流量 都经过代理。启动它:

cd /root/blossom
docker compose up -d

第 2 步:在前面加上 HTTPS

使用 Caddy 时,完整的配置(/etc/caddy/Caddyfile)就是:

blossom.example.com {
    reverse_proxy 127.0.0.1:3000
}

如果同一个 Caddy 已经在为你的中继提供服务,就把这段配置加在那段的下面。重新加载 Caddy (sudo systemctl reload caddy)。现在在浏览器中打开 https://blossom.example.com 应该会有 响应,返回 404:这里没有首页,是有意为之。

第 3 步:告诉 Herkos Drive

  1. 在 Herkos Drive 中打开 设置 → 服务器,添加 https://blossom.example.com,并将它标记为 你自己的。
  2. Drive 在每次上传前都会先询问它。从那以后,每个新文件都会在那里得到一份副本,而你原有的文件 会在 Drive 下一次检查副本时得到它们的副本。
  3. 保留列表中的其他服务器。你的服务器是三份副本之一,绝不是唯一的一份:如果它宕机,你的文件 仍在其他服务器上,而且 Drive 会在它沉默一周后通知你。

第 4 步:每晚备份

如果你的服务器坏了,Drive 会察觉,并在你列表中的其他服务器上为受影响的文件补上副本。但你服务器 上的那份副本是唯一不依赖任何他人的副本,而每晚一次的备份让你能够重建它,无需通过互联网把所有 内容重新复制一遍。

服务器把所有内容保存在 Docker 卷 blossom_data 内(卷名以这些文件所在的文件夹名开头;可用 docker volume ls 查看):这些块,每个块一个文件,以及一个记录每个块由谁上传的小型 SQLite 数据库。块从不改变,但数据库不能在写入时复制。因此脚本会在服务器运行时复制所有内容,然后停止 服务器几秒钟,用来复制这期间发生变化的部分,再重新启动它,之后才上传副本。服务器停止期间, Drive 只会稍后再试。

副本通过 restic 送出服务器,restic 会在数据离开之前对其加密。 请使用与服务器不同服务商的存储位置:一个 SFTP 账户(存储盒、家用电脑)或一个 兼容 S3 的存储桶。如果你已经用这种方式备份你的中继,就使用同一个位置,换一个文件夹。

  1. 安装工具并创建仓库。也请把密码保存在你的密码管理器中:没有它,副本就无法读取; 而如果密码只存在服务器上,它会随服务器一起消失。使用 SFTP 时,root 还需要一个 备份机器接受的 SSH 密钥(sudo ssh-keygen -t ed25519,然后把 /root/.ssh/id_ed25519.pub 添加到那里)。

    sudo apt install restic rsync
    sudo sh -c 'openssl rand -base64 32 > /root/.restic-blossom-password'
    sudo sh -c 'cat > /root/.restic-blossom-env' <<'END'
    export RESTIC_REPOSITORY=sftp:backup@backup.example.com:/blossom
    export RESTIC_PASSWORD_FILE=/root/.restic-blossom-password
    END
    sudo chmod 600 /root/.restic-blossom-password /root/.restic-blossom-env
    sudo sh -c '. /root/.restic-blossom-env && restic init'
    
  2. 将以下内容保存为 /usr/local/bin/backup-blossom 并设为可执行 (sudo chmod 700 /usr/local/bin/backup-blossom)。如果你的文件不在 /root/blossom 中, 请修改 BLOSSOM_DIR。它会保留最近 14 天、8 周和 12 个月的副本。块从不改变,因此每晚只会 添加新的内容。

    #!/bin/sh
    set -eu
    . /root/.restic-blossom-env
    BLOSSOM_DIR=/root/blossom
    COPY=/var/backups/blossom-data
    VOLUME=$(docker volume inspect --format '{{ .Mountpoint }}' blossom_data)
    mkdir -p "$COPY"
    rsync -a --delete "$VOLUME/" "$COPY/"
    cd "$BLOSSOM_DIR"
    docker compose stop blossom
    trap 'docker compose start blossom' EXIT
    rsync -a --delete "$VOLUME/" "$COPY/"
    docker compose start blossom
    trap - EXIT
    restic backup "$COPY" --tag blossom
    restic forget --tag blossom --keep-daily 14 --keep-weekly 8 --keep-monthly 12 --prune
    
  3. 先手动运行一次(sudo /usr/local/bin/backup-blossom),然后用 sudo crontab -e 安排定时任务。第二行每月读回十分之一的已存数据,每次读取不同的十分之一,以证明副本 仍能打开。时常看一看 /var/log/backup-blossom.log:出现含 Fatal 的行,就表示那天 夜里的备份失败了。如果中继也在同一台机器上备份,这些时间不会与它的时间重叠。

    35 4 * * * /usr/local/bin/backup-blossom >> /var/log/backup-blossom.log 2>&1
    55 5 2 * * . /root/.restic-blossom-env && restic check --read-data-subset=10% >> /var/log/backup-blossom.log 2>&1
    

恢复方法(换新服务器,或磁盘故障之后):重新搭建服务器(第 1 和 2 步),并对同一个 仓库重复本步骤的第 1 点和第 2 点,但不要生成新密码,而是把你保存的密码写入 /root/.restic-blossom-password,并跳过 restic init。然后把最新的备份复制到服务器的卷中:

sudo sh -c '. /root/.restic-blossom-env && restic restore latest --tag blossom --target /'
cd /root/blossom && sudo docker compose stop blossom
sudo rsync -a --delete /var/backups/blossom-data/ "$(sudo docker volume inspect --format '{{ .Mountpoint }}' blossom_data)/"
sudo docker compose start blossom

下一次检查副本时,Drive 会重新找到这些块,并从其他服务器复制上次备份之后新到的内容。我们在 2026 年 10 月 27 日测试了这整条链路:备份、删除服务器、恢复,每个块都按其自身的哈希值读回校验, 之后再用 Drive 的密钥删除。

每年在一台备用机器上做一次这样的恢复,确认服务器能用你的块作出响应:这是唯一能证明 整条链路(包括密码)可用的测试。

须知