Parent: #3. The infrastructure half of #20's decision (see the correction there dated 2026-09-15).
Scope
DNS: quantus.blackbeard.observer and planck.blackbeard.observer (per architecture/public-dns.md), pointing at oolon.
nginx on oolon: one vhost per chain name, Let's Encrypt via the existing external-TLS pattern (architecture/external-tls.md), and one upstream per chain in conf.d/ so adding a server is one line:
quantus_node: bob's node over the mesh (the only node we run). The two public mainnet archive nodes the observer already uses as fallbacks may join as backup servers.
planck_node: a1-planck.quantus.cat and a2-planck.quantus.cat, the official Quantus endpoints. We run no testnet node. This is a TLS upstream, so proxy_pass https://, proxy_ssl_server_name on, and proxy_ssl_name per server so SNI is right.
Proxy both HTTP JSON-RPC POST / and the WebSocket upgrade on the same name, with proxy_read_timeout long enough for subscriptions and a health check that removes a dead upstream server.
Throttling: limit_req_zone keyed on client address for HTTP RPC, limit_conn_zone for concurrent WebSockets per client (limit_req only sees the upgrade handshake), sane bursts, and a 429/503 the wallet reads as "throttled, back off" rather than "node down". Record the chosen numbers in the vhost comments. Throttling on the Planck name also protects Quantus's public nodes from us.
bob: the node's RPC listens on loopback for the observer today. Expose it to oolon over the mesh only (firewalld service scoped to the mesh source, architecture/internal-tls.md if the hop is encrypted), --rpc-methods safe, --rpc-cors for the public name, --rpc-max-connections sized for the throttle.
Where it lives: oolon's vhosts and bob's node service are deployed from blackbeard/observer's workflow today. Put the vhost, upstream and firewalld files in that repo's asset/ and deploy job, and link the commit here, unless a wallet-owned deploy is preferred (say why on this issue if so).
Why Planck at all
Planck is in the wallet only to prove the multi-chain UX end to end, until a real post-quantum mainnet that is not Quantus exists. Heisenberg is not needed; if Planck is ever retired, the same pattern proxies whichever testnet Quantus keeps.
Acceptance
websocat wss://quantus.blackbeard.observer answers system_chain with Quantus; planck.blackbeard.observer answers Planck. Taking one Planck upstream out of DNS or having it time out does not break the name. Hammering either name from one address gets throttled while a second address is unaffected. The certificate renews unattended. The wallet's profile for each chain lists only that name.
Depends on
Nothing in the wallet code; #20 consumes the result.
Parent: #3. The infrastructure half of #20's decision (see the correction there dated 2026-09-15).
## Scope
- **DNS**: `quantus.blackbeard.observer` and `planck.blackbeard.observer` (per `architecture/public-dns.md`), pointing at oolon.
- **nginx on oolon**: one vhost per chain name, Let's Encrypt via the existing external-TLS pattern (`architecture/external-tls.md`), and one `upstream` per chain in `conf.d/` so adding a server is one line:
- `quantus_node`: bob's node over the mesh (the only node we run). The two public mainnet archive nodes the observer already uses as fallbacks may join as `backup` servers.
- `planck_node`: `a1-planck.quantus.cat` and `a2-planck.quantus.cat`, the official Quantus endpoints. We run no testnet node. This is a TLS upstream, so `proxy_pass https://`, `proxy_ssl_server_name on`, and `proxy_ssl_name` per server so SNI is right.
- Proxy both HTTP JSON-RPC `POST /` and the WebSocket upgrade on the same name, with `proxy_read_timeout` long enough for subscriptions and a health check that removes a dead upstream server.
- **Throttling**: `limit_req_zone` keyed on client address for HTTP RPC, `limit_conn_zone` for concurrent WebSockets per client (`limit_req` only sees the upgrade handshake), sane bursts, and a `429`/`503` the wallet reads as "throttled, back off" rather than "node down". Record the chosen numbers in the vhost comments. Throttling on the Planck name also protects Quantus's public nodes from us.
- **bob**: the node's RPC listens on loopback for the observer today. Expose it to oolon over the mesh only (firewalld service scoped to the mesh source, `architecture/internal-tls.md` if the hop is encrypted), `--rpc-methods safe`, `--rpc-cors` for the public name, `--rpc-max-connections` sized for the throttle.
- **Where it lives**: oolon's vhosts and bob's node service are deployed from `blackbeard/observer`'s workflow today. Put the vhost, upstream and firewalld files in that repo's `asset/` and deploy job, and link the commit here, unless a wallet-owned deploy is preferred (say why on this issue if so).
## Why Planck at all
Planck is in the wallet only to prove the multi-chain UX end to end, until a real post-quantum mainnet that is not Quantus exists. Heisenberg is not needed; if Planck is ever retired, the same pattern proxies whichever testnet Quantus keeps.
## Acceptance
`websocat wss://quantus.blackbeard.observer` answers `system_chain` with `Quantus`; `planck.blackbeard.observer` answers `Planck`. Taking one Planck upstream out of DNS or having it time out does not break the name. Hammering either name from one address gets throttled while a second address is unaffected. The certificate renews unattended. The wallet's profile for each chain lists only that name.
## Depends on
Nothing in the wallet code; #20 consumes the result.
grenade
added the child label 2026-09-15 13:01:05 +00:00
Done, 2026-09-16. The files live where the issue asked:
Quantus-Network/blackbeard.observer54db950: asset/nginx/blackbeard-nodes.conf (upstreams quantus_node → bob:9944 over the mesh, planck_node → a1/a2-planck.quantus.cat:443 with max_fails=3 fail_timeout=30s; limit_req_zone node_rpc 20r/s, limit_conn_zone node_conn), asset/nginx/quantus.blackbeard.observer.conf and planck.blackbeard.observer.conf (LE cert, TLS 1.2+1.3, limit_req burst=40 nodelay, limit_conn 16, 429 on both, 3600 s socket timeouts, 1 MiB bodies; the Planck one is proxy_pass https with proxy_ssl_server_name on, proxy_ssl_name a1-planck.quantus.cat, verification against the system CA bundle, since both hosts sit behind one *.quantus.cat certificate), and a nodes role in script/infra-setup.sh that creates the CNAME to bl.thgttg.com, issues the certificate, installs the vhosts and enables them only after nginx -t passes.
lair/quantus404c65a: bob's matrix entry gains rpc_extra_sources: "oolon.kosherinata.internal", resolved on the node into a /32 rich rule for quantus-node-rpc beside the site-subnet rule. Applied by hand on bob with the same command, then codified.
Acceptance, as run:
check
result
system_chain over HTTPS
Quantus and Planck
system_chain over WSS
both answer; chain_subscribeNewHeads on the quantus name delivered a head
throttling
120 requests from one address, 40 in parallel: 19×200, 101×429; five from bob at the same time all 200
certificates
both to 2026-12-15, certbot-renew.timer enabled and active on oolon, host-wide reload hook present
wallet profiles
list only wss://quantus.blackbeard.observer / wss://planck.blackbeard.observer; the ignored planck_accepts_the_signature… test passes against the public name
Two notes. nginx open source has no active health checks, so "taking one Planck upstream out of DNS" is covered by passive max_fails/fail_timeout (a failing server is skipped for 30 s) rather than tested by pulling a record; and a resolver that looked the quantus name up before the record existed caches the miss for a while, which is what the script's own final curl hit.
Done, 2026-09-16. The files live where the issue asked:
- **Quantus-Network/blackbeard.observer** `54db950`: `asset/nginx/blackbeard-nodes.conf` (upstreams `quantus_node` → bob:9944 over the mesh, `planck_node` → a1/a2-planck.quantus.cat:443 with `max_fails=3 fail_timeout=30s`; `limit_req_zone node_rpc 20r/s`, `limit_conn_zone node_conn`), `asset/nginx/quantus.blackbeard.observer.conf` and `planck.blackbeard.observer.conf` (LE cert, TLS 1.2+1.3, `limit_req burst=40 nodelay`, `limit_conn 16`, 429 on both, 3600 s socket timeouts, 1 MiB bodies; the Planck one is `proxy_pass https` with `proxy_ssl_server_name on`, `proxy_ssl_name a1-planck.quantus.cat`, verification against the system CA bundle, since both hosts sit behind one `*.quantus.cat` certificate), and a `nodes` role in `script/infra-setup.sh` that creates the CNAME to `bl.thgttg.com`, issues the certificate, installs the vhosts and enables them only after `nginx -t` passes.
- **lair/quantus** `404c65a`: bob's matrix entry gains `rpc_extra_sources: "oolon.kosherinata.internal"`, resolved on the node into a `/32` rich rule for `quantus-node-rpc` beside the site-subnet rule. Applied by hand on bob with the same command, then codified.
Acceptance, as run:
| check | result |
|---|---|
| `system_chain` over HTTPS | `Quantus` and `Planck` |
| `system_chain` over WSS | both answer; `chain_subscribeNewHeads` on the quantus name delivered a head |
| throttling | 120 requests from one address, 40 in parallel: 19×200, 101×429; five from bob at the same time all 200 |
| certificates | both to 2026-12-15, `certbot-renew.timer` enabled and active on oolon, host-wide reload hook present |
| wallet profiles | list only `wss://quantus.blackbeard.observer` / `wss://planck.blackbeard.observer`; the ignored `planck_accepts_the_signature…` test passes against the public name |
Two notes. nginx open source has no active health checks, so "taking one Planck upstream out of DNS" is covered by passive `max_fails`/`fail_timeout` (a failing server is skipped for 30 s) rather than tested by pulling a record; and a resolver that looked the quantus name up before the record existed caches the miss for a while, which is what the script's own final curl hit.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Parent: #3. The infrastructure half of #20's decision (see the correction there dated 2026-09-15).
Scope
quantus.blackbeard.observerandplanck.blackbeard.observer(perarchitecture/public-dns.md), pointing at oolon.architecture/external-tls.md), and oneupstreamper chain inconf.d/so adding a server is one line:quantus_node: bob's node over the mesh (the only node we run). The two public mainnet archive nodes the observer already uses as fallbacks may join asbackupservers.planck_node:a1-planck.quantus.catanda2-planck.quantus.cat, the official Quantus endpoints. We run no testnet node. This is a TLS upstream, soproxy_pass https://,proxy_ssl_server_name on, andproxy_ssl_nameper server so SNI is right.POST /and the WebSocket upgrade on the same name, withproxy_read_timeoutlong enough for subscriptions and a health check that removes a dead upstream server.limit_req_zonekeyed on client address for HTTP RPC,limit_conn_zonefor concurrent WebSockets per client (limit_reqonly sees the upgrade handshake), sane bursts, and a429/503the wallet reads as "throttled, back off" rather than "node down". Record the chosen numbers in the vhost comments. Throttling on the Planck name also protects Quantus's public nodes from us.architecture/internal-tls.mdif the hop is encrypted),--rpc-methods safe,--rpc-corsfor the public name,--rpc-max-connectionssized for the throttle.blackbeard/observer's workflow today. Put the vhost, upstream and firewalld files in that repo'sasset/and deploy job, and link the commit here, unless a wallet-owned deploy is preferred (say why on this issue if so).Why Planck at all
Planck is in the wallet only to prove the multi-chain UX end to end, until a real post-quantum mainnet that is not Quantus exists. Heisenberg is not needed; if Planck is ever retired, the same pattern proxies whichever testnet Quantus keeps.
Acceptance
websocat wss://quantus.blackbeard.observeranswerssystem_chainwithQuantus;planck.blackbeard.observeranswersPlanck. Taking one Planck upstream out of DNS or having it time out does not break the name. Hammering either name from one address gets throttled while a second address is unaffected. The certificate renews unattended. The wallet's profile for each chain lists only that name.Depends on
Nothing in the wallet code; #20 consumes the result.
Done, 2026-09-16. The files live where the issue asked:
54db950:asset/nginx/blackbeard-nodes.conf(upstreamsquantus_node→ bob:9944 over the mesh,planck_node→ a1/a2-planck.quantus.cat:443 withmax_fails=3 fail_timeout=30s;limit_req_zone node_rpc 20r/s,limit_conn_zone node_conn),asset/nginx/quantus.blackbeard.observer.confandplanck.blackbeard.observer.conf(LE cert, TLS 1.2+1.3,limit_req burst=40 nodelay,limit_conn 16, 429 on both, 3600 s socket timeouts, 1 MiB bodies; the Planck one isproxy_pass httpswithproxy_ssl_server_name on,proxy_ssl_name a1-planck.quantus.cat, verification against the system CA bundle, since both hosts sit behind one*.quantus.catcertificate), and anodesrole inscript/infra-setup.shthat creates the CNAME tobl.thgttg.com, issues the certificate, installs the vhosts and enables them only afternginx -tpasses.404c65a: bob's matrix entry gainsrpc_extra_sources: "oolon.kosherinata.internal", resolved on the node into a/32rich rule forquantus-node-rpcbeside the site-subnet rule. Applied by hand on bob with the same command, then codified.Acceptance, as run:
system_chainover HTTPSQuantusandPlancksystem_chainover WSSchain_subscribeNewHeadson the quantus name delivered a headcertbot-renew.timerenabled and active on oolon, host-wide reload hook presentwss://quantus.blackbeard.observer/wss://planck.blackbeard.observer; the ignoredplanck_accepts_the_signature…test passes against the public nameTwo notes. nginx open source has no active health checks, so "taking one Planck upstream out of DNS" is covered by passive
max_fails/fail_timeout(a failing server is skipped for 30 s) rather than tested by pulling a record; and a resolver that looked the quantus name up before the record existed caches the miss for a while, which is what the script's own final curl hit.