Shipped Hubstr Blossom yesterday too.
A personal Blossom server: your images, video, and files stored under their SHA-256, served from your own origin, and managed with your Nostr key. Two kinds of visitor. Anyone can fetch a blob by its hash. Tenants can upload, mirror, optimise, list, and delete them.
Every upload is hashed and type-sniffed on arrival, so the stored hash is what was received and the stored type is what the bytes are, not what the header said. PUT /media re-encodes an image and drops its metadata, applying the EXIF orientation first. The result is kept only if it is smaller. Dimensions and a blurhash are computed for NIP-94. Kind 1984 reports are accepted and kept.
Blobs live on the filesystem, sharded by hash, moved into place with one atomic rename. The SQLite index holds one row per tenant per blob, so the same bytes uploaded by two tenants are stored once and removed only when the last of them deletes. Nothing else deletes them. Bytes are streamed from the process with ranges, ETags, and CORS handled in application code, so a plain reverse proxy is all it needs. Hashing and media work run on a worker pool, off the event loop.
BUDs 01, 02, 04, 05, 06, 08, 09, 11, and 12, and an acceptance suite that boots a real daemon and drives every one of them over HTTP. Caddyfile and systemd unit included. PHP 8.4, two config keys to change, and it starts.
A version of this server has been running on blossom.innis.xyz for months, with earlier versions in the wild for longer.
Built on innis/nostr-blossom, innis/nostr-core, and innis/hubstr-core.
https://github.com/johninnis/hubstr-blossom
Thanks to hzrd149 (nprofile…9x4s) for the elegant protocol.
MIT.
#nostr #php #opensource #nostrdev #blossom