Your own Blossom server
Last updated: 27 October 2026
Herkos Drive cuts each file into encrypted blocks and keeps them on several Blossom servers: three copies, on at least two kinds of server, and one on a server of yours. Public servers keep blocks for free, but they promise nothing: they can purge them, fill up or close.
A Blossom server of your own keeps your copy for as long as you decide and takes blocks only from your Drive. This page explains how to set one up in three steps, plus a nightly backup. It goes well with your own mailbox relay, and it takes about fifteen minutes if you already have a server.
Which server to use
blossom-server by hzrd149, version 6.4.1 (6 October 2026, MIT licence). We ran it on 27 October 2026 with the configuration below and Drive's own upload code, and checked what Drive needs, not what the server advertises:
| What Drive does | Result |
|---|---|
Uploads 8 MiB encrypted blocks (application/octet-stream) |
Accepted |
| Asks before uploading (BUD-06) | Answers, and turns away any other key |
| Asks your server to copy a block from a public one (BUD-04) | Copied |
| Reads a block without identifying | Served, byte for byte |
| Deletes a block with the key that uploaded it | Deleted: asking again gives 404 |
| Uploads from any other key | Refused (401) |
What you need
- A machine that is always on and reachable from the internet: a small VPS or a computer at home. It needs as much disk as your Drive holds, and some room to grow.
- A domain or subdomain pointing to it, for example
blossom.example.com. - Docker and a reverse proxy that provides HTTPS. The examples use Caddy, which gets the certificate on its own.
- Your Drive's volume key. Herkos Drive shows it in Settings → Servers → Your own server, as 64 letters and digits. It is not your profile's key: Drive never uploads with your profile key, so a server that only accepts your npub would turn Drive away.
Step 1: run the server
Make a folder for it, for example /root/blossom, and save these two files in
it. The first is 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: {}
The second is config.yml. Put your domain in publicDomain and your volume
key where it says 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
What it says: only your volume key may upload or ask for copies
(requirePubkeyInRule), and a block is kept until Drive deletes it. The
server needs an expiry in every rule; 100 years without being read is never,
in practice, and Drive reads its blocks regularly anyway. The port only
listens on the machine itself (127.0.0.1): everything goes through the proxy.
Start it:
cd /root/blossom
docker compose up -d
Step 2: put HTTPS in front
With Caddy, the whole configuration (/etc/caddy/Caddyfile) is:
blossom.example.com {
reverse_proxy 127.0.0.1:3000
}
If the same Caddy already serves your relay, add this block below that one.
Reload Caddy (sudo systemctl reload caddy). Opening
https://blossom.example.com in a browser should now answer, with a 404:
there is no home page, on purpose.
Step 3: tell Herkos Drive
- In Herkos Drive, open Settings → Servers, add
https://blossom.example.comand mark it as yours. - Drive asks it before each upload. From then on, every new file gets a copy there, and the files you already had get theirs the next time Drive checks the copies.
- Keep the other servers in the list. Yours is one of the three copies, never the only one: if it goes down, your files are still on the others, and Drive tells you after a week of silence.
Step 4: back it up every night
If your server dies, Drive notices and gives the affected files copies on the other servers in your list. But the copy on your server is the only one that depends on nobody else, and a nightly backup lets you rebuild it without copying everything again over the internet.
The server keeps everything inside the Docker volume blossom_data (the name
starts with the folder the files are in; check it with docker volume ls):
the blocks, one file each, and a small SQLite database that says who uploaded
each one. Blocks never change, but the database must not be copied while it is
being written. So the script copies everything with the server running, stops
it for the few seconds it takes to copy what changed in between, starts it
again, and only then uploads the copy. While it is stopped, Drive simply tries
again a little later.
The copy goes off the server with restic, which encrypts it before it leaves. Use a place at a different provider from the server: an SFTP account (a storage box, a computer at home) or an S3-compatible bucket. If you already back up your relay this way, use the same place with another folder.
-
Install the tools and create the repository. Keep the password in your password manager as well: without it the copies cannot be read, and if it only lives on the server, it dies with the server. For SFTP, root also needs an SSH key that the backup machine accepts (
sudo ssh-keygen -t ed25519, then add/root/.ssh/id_ed25519.pubthere).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' -
Save this as
/usr/local/bin/backup-blossomand make it executable (sudo chmod 700 /usr/local/bin/backup-blossom). ChangeBLOSSOM_DIRif your files are not in/root/blossom. It keeps the last 14 days, 8 weeks and 12 months. Blocks never change, so each night only adds what is new.#!/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 -
Run it once by hand (
sudo /usr/local/bin/backup-blossom), then schedule it withsudo crontab -e. The second line reads back a tenth of the stored data each month, a different tenth every time, to prove the copies can still be opened. Look at/var/log/backup-blossom.lognow and then: a line withFatalmeans that night's copy failed. If the relay is backed up on the same machine, these times do not overlap with its own.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
To restore (a new server, or after a disk failure): set the server up again
(steps 1 and 2) and repeat points 1 and 2 of this step with the same repository,
but write the password you saved into /root/.restic-blossom-password instead
of creating a new one, and skip restic init. Then copy the latest backup into
the server's volume:
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
The next time it checks the copies, Drive finds the blocks back and copies over, from the other servers, whatever arrived after the last backup. We tried this whole chain on 27 October 2026: backup, server deleted, restore, every block read back with its own hash, and deleted afterwards with Drive's key.
Once a year, do this restore on a spare machine and check that the server answers with your blocks: it is the only test that proves the whole chain, password included.
Good to know
- Only your Drive can upload. Anyone who knows the address of a block can download it, as on any Blossom server, but it is encrypted: without the keys in your Drive it is noise.
- If your volume key changes (Drive tells you when a volume is renewed), add
the new one as another line under
pubkeys, restart (docker compose up -d), and leave the old one there. - Updates. Read the changelog,
change the version in
image:, and rundocker compose pullanddocker compose up -d. - Your IP address. The server sees the address of every app that connects to it, as any server does. On your own server, the only one who sees them is you.