Files
floonet-strfry/deploy/Caddyfile
T
2ro 7205ddbafd floonet-strfry: co-locate the name authority on the relay domain (toggle)
Serve the authority's NIP-05 lookup on the relay's own domain so
`name@relay.example` resolves, without giving the authority a second
vhost/cert. Live on us-east: relay.floonet.dev now answers
/.well-known/nostr.json from the co-located authority (127.0.0.1:8193)
while the WebSocket relay and NIP-11 stay untouched.

  * deploy/us-east/colocated-authority.conf
        The nginx opt-in: an exact-match `location = /.well-known/nostr.json`
        proxied to the authority ahead of the relay's WebSocket catch-all.
        Only the READ path is exposed; registration and the rest of /api/*
        stay on the authority's own domain. Sets X-Real-IP (the per-IP rate
        limiter keys off it). Same proxy shape as nm.floonet.dev.conf.
  * README.md — "Co-locating names on the relay domain": the Caddy/compose
        stack is co-located by default (single FLOONET_DOMAIN); a split nginx
        deploy opts in with the snippet. Documents FLOONET_AUTHORITY_COLOCATED.
  * deploy/Caddyfile, .env.example — note the single-domain stack is
        co-located by default and point split deploys at the snippet.

The box vhost mirrors this snippet exactly; applied with nginx -t + reload
(no restart), firewalld untouched.
2026-07-03 04:11:19 -04:00

63 lines
2.1 KiB
Caddyfile

# Caddy reverse proxy for the Floonet relay + name authority, with automatic
# HTTPS.
#
# Used by docker-compose.yml (upstreams are the compose service names
# `authority` and `relay`). For a bare-metal Caddy install, replace those
# with `127.0.0.1:8191` and `127.0.0.1:7777`, set the site address to your
# domain literally, and point the landing root at deploy/landing.
#
# FLOONET_DOMAIN is injected from the environment by compose.
{$FLOONET_DOMAIN} {
# SECURITY-CRITICAL (both upstreams): X-Real-IP is set from the real
# client address inside each reverse_proxy below. The name authority keys
# ALL of its per-IP rate limiting off this header; if the proxy does not
# set it, every request looks like one client and the limiter is
# defeated. Caddy's {remote_host} is the connecting peer, not a
# forwardable client header.
# NIP-05 resolution and the registration/paid API go to the authority.
# This single-domain stack is co-located by design: names AND the relay
# answer on FLOONET_DOMAIN (the FLOONET_AUTHORITY_COLOCATED=on default;
# a split nginx deploy opts in via deploy/us-east/colocated-authority.conf
# instead — see the README). gzip is scoped here (HTTP/JSON) and
# deliberately NOT applied to the relay path: strfry already negotiates
# permessage-deflate on the WebSocket.
@authority {
path /.well-known/nostr.json /.well-known/nostr.json/* /api/*
}
handle @authority {
encode gzip
reverse_proxy authority:8191 {
header_up X-Real-IP {remote_host}
}
}
# The Floonet logo and a static landing page for plain browser visits.
# The relay wire protocol never matches these: WebSocket upgrades and
# NIP-11 info requests carry the headers excluded below and fall through
# to the relay.
handle /floonet-logo.svg {
root * /srv/landing
file_server
}
@browser {
path /
not header Connection *Upgrade*
not header Accept *application/nostr+json*
}
handle @browser {
root * /srv/landing
rewrite * /index.html
file_server
}
# Everything else, in particular WebSocket upgrades and the NIP-11
# document, is the relay.
handle {
reverse_proxy relay:7777 {
header_up X-Real-IP {remote_host}
}
}
}