services:
bitcoin:
# Bitcoin Knots — Luke Dashjr's fork of Core, stricter mempool policy
# Image is unofficial but built from reproducible Knots binaries (bitcoinknots.org)
# For max sovereignty: build from source and replace this image with your own
# To swap implementations: change image + datadir volume path, nothing else
image: bitcoinknots/bitcoin:29.3.knots20260210
container_name: bitcoin
restart: unless-stopped
volumes:
- bitcoin_data:/home/bitcoin/.bitcoin
ports:
- "8333:8333"
networks:
- node-net
healthcheck:
test: ["CMD", "bitcoin-cli", "-datadir=/home/bitcoin/.bitcoin", "getblockchaininfo"]
interval: 60s
timeout: 10s
retries: 5
start_period: 30s
lnd:
image: lightningnetwork/lnd:v0.18.3-beta
container_name: lnd
depends_on:
condition: service_healthy
- lnd_data:/root/.lnd
- "9735:9735"
test: ["CMD", "lncli", "--network=mainnet", "state"]
interval: 30s
retries: 10
start_period: 60s
lnbits:
image: lnbits/lnbits:latest
container_name: lnbits
condition: service_started
- "127.0.0.1:5000:5000"
- lnbits_data:/app/data
- lnd_data:/lnd:ro
environment:
- LNBITS_DATA_FOLDER=/app/data
- LNBITS_BACKEND_WALLET_CLASS=LndRestWallet
- LND_REST_ENDPOINT=https://lnd:8080
- LND_REST_CERT=/lnd/tls.cert
- LND_REST_MACAROON=/lnd/data/chain/bitcoin/mainnet/invoice.macaroon
- LNBITS_SITE_TITLE=Timmy Node
- LNBITS_SITE_TAGLINE=Lightning AI Agent Infrastructure
- UVICORN_HOST=0.0.0.0
- UVICORN_PORT=5000
# ── Nostr relay ──────────────────────────────────────────────────────────────
relay-policy:
# Write-policy sidecar: receives strfry plugin decisions, forwards to API server.
# Started before strfry so the plugin script can immediately reach it.
build:
context: ./relay-policy
dockerfile: Dockerfile
container_name: relay-policy
- PORT=3080
# Base URL of the Timmy API server (no trailing slash).
# Example: https://alexanderwhitestone.com
- RELAY_API_URL=${RELAY_API_URL:-}
# Shared secret — must match RELAY_POLICY_SECRET in the API server's env.
- RELAY_POLICY_SECRET=${RELAY_POLICY_SECRET:-}
test: ["CMD", "wget", "-qO-", "http://localhost:3080/health"]
interval: 15s
timeout: 5s
retries: 3
start_period: 10s
strfry:
# strfry — high-performance Nostr relay written in C++.
# All inbound events pass through the relay-policy sidecar before storage.
image: ghcr.io/hoytech/strfry:latest
container_name: strfry
- strfry_data:/data/strfry-db
- ./strfry.conf:/etc/strfry.conf:ro
# Plugin bridge script: reads events from strfry stdin, calls relay-policy HTTP.
- ./relay-policy/plugin.sh:/usr/local/bin/relay-policy-plugin:ro
- "7777:7777"
command: ["strfry", "--config=/etc/strfry.conf", "relay"]
test: ["CMD", "sh", "-c", "echo >/dev/tcp/localhost/7777"]
start_period: 15s
node-net:
driver: bridge
bitcoin_data:
driver: local
driver_opts:
type: none
o: bind
device: /data/bitcoin
lnd_data:
device: /data/lnd
lnbits_data:
device: /data/lnbits
strfry_data:
# Persistent event database — survives container restarts and upgrades.
# Operator must create /data/strfry on the VPS before first launch:
# mkdir -p /data/strfry && chmod 700 /data/strfry
device: /data/strfry