This is the deployment used for torly.smesh.lol: one TinyGo binary behind
Caddy, serving the relay and Blossom endpoints. The old orly service and its
database have been removed from the host.
/usr/local/bin/torly torly binary
/usr/local/bin/torly-monitor health check
/etc/torly/torly.env torly environment
/etc/systemd/system/torly.service
/etc/systemd/system/torly-monitor.{service,timer}
/home/mleku/.local/share/torly/
relay.key stable relay signing key
db/ torly WAL and indexes
blossom/blobs/ content-addressed Blob files
blossom/index.log Blob ownership index
monitor-status.json last health check
torly listens on 127.0.0.1:3336. Caddy terminates TLS and proxies
https://torly.smesh.lol/, https://relay.orly.dev/ and
https://relay.mleku.dev/ and their WebSocket endpoints to that port. All
three names serve the same relay identity
350abd25b77d4d6a11e66e022efa181c759e07a2828b8cc9a80034bcf4161d88.
systemctl status torly
systemctl restart torly
journalctl -u torly -n 100
curl -sS http://127.0.0.1:3336/health
torly.service uses TORLY_CONN_WORKERS=256 and
TORLY_BLOSSOM_MAX_BLOB_MB=128 from /etc/torly/torly.env. The worker pool is
fixed; the acceptor is a raw nonblocking IPv4 socket with a 1024-connection
backlog. Database startup waits up to two minutes because replaying a large WAL
after an unclean shutdown can take that long.
torly-monitor.timer runs every five minutes. It checks /health, the NIP-11
document and that torly.service is active, then writes
monitor-status.json. After three consecutive health failures it restarts
torly. It does not depend on orly or a mirror process.
cat /home/mleku/.local/share/torly/monitor-status.json
journalctl -u torly-monitor -n 50
systemctl list-timers torly-monitor.timer
The backup is a tar with manifest.json first, followed by
blobs/<sha256>. Blob metadata (owner pubkey, MIME type, upload time) is in the
manifest. The offline backup command requires the relay to be stopped because
it opens the Blob store directly.
systemctl stop torly
runuser -u mleku -- /usr/local/bin/torly blossom-backup \
--data-dir /home/mleku/.local/share/torly \
--out /home/mleku/torly-blossom-$(date +%Y%m%d-%H%M%S).tar
systemctl start torly
The default restore is live. The CLI copies the tar atomically to
DATA/blossom/restore.tar; the running Blossom domain notices it within one
second, imports every blob, writes restore.status.json, and removes the
spool:
runuser -u mleku -- /usr/local/bin/torly blossom-restore \
--data-dir /home/mleku/.local/share/torly \
--file /home/mleku/torly-blossom-YYYYmmdd-HHMMSS.tar
Use --offline to open the store directly while torly is stopped. Restore
verifies every SHA-256, skips blobs already present, and preserves metadata.
The live path is safe to repeat: the import is idempotent.
For a database backup, stop torly and copy the whole data directory; the WAL and index files are only consistent while the process is stopped.
The old Blossom data lived in Badger. tools/orly-blossom-extract is a
standalone Go module that scans blob:meta: records and files and writes a
torly backup tar. It must run as the orly user with orly stopped so Badger can
take the lock:
cd tools/orly-blossom-extract
go build -o /usr/local/bin/orly-blossom-extract .
runuser -u mleku -- /usr/local/bin/orly-blossom-extract \
--db /home/mleku/.local/share/ORLY \
--out /home/mleku/torly-blossom.tar
The migration used here produced 659 blobs (564 MB); the live restore reported
{"ok":true,"restored":68,"skipped":591} because most blobs were already
present from an earlier partial run. The old orly database has since been
deleted.
The site block is kept in deploy/Caddyfile.torly and appended to
/etc/caddy/Caddyfile:
torly.smesh.lol {
import compress
import block_bots
import no_adtech
header Access-Control-Allow-Origin *
header Access-Control-Allow-Headers "Accept, Authorization, Content-Type"
reverse_proxy 127.0.0.1:3336
log {
output file /var/log/caddy/torly.smesh.lol.log
format json
level INFO
}
}
The relay.orly.dev and relay.mleku.dev blocks also reverse-proxy to
127.0.0.1:3336. caddy validate --config /etc/caddy/Caddyfile must be run as
root only after the log file exists with owner caddy; caddy validate run as
root can create the log file as root and make the subsequent reload fail with
permission denied. If that happens, remove the root-owned file and reload Caddy
again.
malformed JSON (out of 2,114,719 lines). torly's strict decoder rejected
them and the importer counted them under invalid; they are not present in
torly. This loss was accepted.
Badger extractor above.
relay.key changes the relay's NIP-11identity and graph-result signatures.
queries but are skipped entirely by the graph index.