Files
floonet-strfry/.env.example
T
2ro 65ec8fcef2 relay: lock public notes (kinds 1, 30023) to operator-authorized authors
Public-note kinds are now accepted only from an operator-configured list of
author pubkeys (FLOONET_AUTHORIZED_AUTHORS, hex or npub). Closed by default:
with no authors set, kinds 1 and 30023 are rejected for everyone, so random
notes cannot be spammed to the relay. Every other kind is unaffected and
kind 0 profiles stay open.

- add 30023 (long-form article) to the default kind whitelist
- check_authorized_authors runs right after check_kind; LOCKED_KINDS {1,30023}
- pure-python bech32 npub decoder (no new deps); invalid entries logged/skipped
- load_config also reads a KEY=VALUE floonet.env next to the plugin
  (FLOONET_ENV_FILE), env vars win, so config changes need no container
  recreate; strfry reloads the plugin on mtime change (no restart)
- extend test_policy.py (32 tests green)
- scripts/purge_public_notes.sh (dry-run default) to clean pre-existing notes
- scripts/smoke_test_lockdown.py post-deploy check
- README + .env.example config docs
2026-07-04 19:58:31 -04:00

122 lines
5.0 KiB
Bash

# floonet-strfry configuration. Copy to `.env` (for docker compose) and edit
# for your deployment. Every value shown is the built-in default, so an unset
# variable behaves exactly like the line below.
# --- Identity (the part you MUST change to run your own relay) ---
# Bare host this relay and its names live under: the `@domain` in
# `name@domain` and the domain Caddy obtains a TLS certificate for.
FLOONET_DOMAIN=floonet.example
# Public base URL clients actually reach. LOAD-BEARING: NIP-98 auth events
# are verified against `<FLOONET_BASE_URL><path>`, so this MUST be https://
# and its host MUST equal FLOONET_DOMAIN (a port is allowed). A wrong value
# silently breaks every authenticated call. The authority refuses to start
# if it and FLOONET_DOMAIN disagree.
FLOONET_BASE_URL=https://floonet.example
# Comma-separated relays advertised in /.well-known/nostr.json. Point this
# at your own wss:// URL (normally wss://FLOONET_DOMAIN).
FLOONET_RELAYS=wss://floonet.example
# Co-located names (FLOONET_AUTHORITY_COLOCATED): this compose stack is single
# domain, so names AND the relay are already served on FLOONET_DOMAIN
# (`name@FLOONET_DOMAIN` resolves) — on by default, nothing to set here. Only a
# SPLIT deploy that puts the relay and the authority on separate subdomains
# behind nginx needs to opt in; see "Co-locating names on the relay domain" in
# the README and deploy/us-east/colocated-authority.conf.
# --- The kind whitelist (the keystone) ---
# Comma-separated event kinds the relay stores. DEFAULT-DENY: anything not
# listed here is rejected at ingest. The shipped set is exactly what the
# Goblin wallet uses:
# 0 profile, 3 contacts, 5 delete (NIP-09), 13 seal, 1059 gift wrap
# (NIP-59), 10002 relay list (NIP-65), 10050 DM relays (NIP-17),
# 27235 NIP-98 HTTP auth
# To accept another kind, add it here and restart the relay.
FLOONET_ALLOWED_KINDS=0,3,5,13,1059,10002,10050,27235
# --- Public-note lockdown (kinds 1, 30023) ---
# Public notes (kind 1 text notes, kind 30023 long-form articles) are
# accepted ONLY from the authors listed here. Everything else (profiles,
# gift wraps, marketplace kinds, lists) is unaffected. Closed by default:
# leave this empty and kinds 1/30023 are rejected for everyone, so random
# notes cannot be spammed to your relay. Comma-separated, each entry a hex
# pubkey OR an npub (your choice); invalid entries are logged and skipped.
FLOONET_AUTHORIZED_AUTHORS=
# --- Authentication (optional) ---
# Require NIP-42 AUTH before accepting writes. Set to true AND flip
# relay.auth.enabled to true in deploy/strfry/strfry.conf (strfry issues the
# challenges; the plugin enforces the requirement).
FLOONET_REQUIRE_AUTH=false
# --- Charge GRIN for your relay (optional; all off by default) ---
# off = everything free
# name = claiming a name@domain costs FLOONET_NAME_PRICE_GRIN
# write = publishing to the relay needs a one-time payment of
# FLOONET_WRITE_PRICE_GRIN (clients must also NIP-42 AUTH, since
# payment grants are per pubkey)
FLOONET_PAY_MODE=off
# Prices, in GRIN (decimals allowed, e.g. 1.5). You set the price; edit and
# restart, no code change.
FLOONET_NAME_PRICE_GRIN=0
FLOONET_WRITE_PRICE_GRIN=0
# Your GoblinPay server (https://code.gri.mw/GRIN/GoblinPay). The authority
# creates invoices there and payers land on its hosted pay page.
GOBLINPAY_URL=
# The GoblinPay API token (GP_API_TOKEN on the GoblinPay side).
GOBLINPAY_TOKEN=
# Optional: GoblinPay webhook secret. When set, point a GoblinPay webhook at
# https://FLOONET_DOMAIN/api/v1/goblinpay/webhook and payments confirm
# instantly instead of on the next status poll.
GOBLINPAY_WEBHOOK_SECRET=
# Seconds the write policy plugin caches paid-status verdicts.
FLOONET_PAID_CACHE_SECS=60
# --- Tor onion (optional) ---
# Uncomment to ALSO run a Tor onion in front of the relay (the `tor` compose
# service), so wallets can reach it over Tor without a Tor exit hop. The onion
# forwards straight to the relay's websocket listener; see deploy/tor/torrc.
# tor prints the .onion address to its logs on first start and stores its key
# on the tor-data volume (back it up: losing it rotates the address). Publish
# the .onion so wallets can find it.
#COMPOSE_PROFILES=tor
# --- Name authority policy tunables ---
# Seconds a key must wait to claim a new name after releasing one (anti-churn).
FLOONET_NAME_CHANGE_COOLDOWN_SECS=600
# Max age (seconds) of an accepted NIP-98 auth event.
FLOONET_AUTH_MAX_AGE_SECS=60
# Allowed name length, in characters.
FLOONET_NAME_MIN=3
FLOONET_NAME_MAX=20
# --- Rate-limit ceilings (per X-Real-IP) ---
# Read endpoints: max requests per window / window length in seconds.
FLOONET_READ_RATE_MAX=120
FLOONET_READ_RATE_WINDOW_SECS=60
# Write endpoints (register/release/quote).
FLOONET_WRITE_RATE_MAX=10
FLOONET_WRITE_RATE_WINDOW_SECS=3600
# --- Optional ---
# Path to a file of additional reserved names (one per line, # comments).
# Extends the built-in generic list and your domain's own labels (which are
# always reserved). Leave unset to use only those defaults.
#FLOONET_RESERVED_FILE=/etc/floonet-authority.reserved