7205ddbafd
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.
63 lines
2.1 KiB
Caddyfile
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}
|
|
}
|
|
}
|
|
}
|