sirius-press/docs/bcnr-records.md
Local Dev 582cc81ffe sirius-press: let the published port be bound to localhost
A stack with TLS in front of it was still publishing nginx on 0.0.0.0,
so the admin stayed reachable over plain HTTP on a raw port while the
proxy served the same site over HTTPS beside it. On this project's own
instance that meant wp-login.php answering 200 to the open internet.

There is no password to steal — the account is a key — but the session
cookie is the account, and a cookie read off the wire is a logged-in
administrator.

HTTP_BIND defaults to 0.0.0.0, so a stack with nothing in front behaves
exactly as before. The records doc now also explains the pinned
self-signed certificate route, which is how a BCNR name gets HTTPS
without a certificate authority — and why an editor needs it at all:
the publishing key is derived in the page, and crypto.subtle does not
exist outside a secure context.
2026-10-03 16:49:23 +02:00

144 lines
5.2 KiB
Markdown

# Pointing your name at your site
A BCNR name carries a small set of records on-chain. Two of them say "the site
for this name is served from here":
| Record | Holds | Use it when |
|---|---|---|
| `ip` | An IPv4 or IPv6 address | You have a server with a fixed address — the normal case for a VPS |
| `p` | A hostname | Something else already resolves to your server: a DNS name, a tunnel endpoint, a load balancer |
Either one makes a BCNR resolver — Theseus, Ariadne, or the public gateway —
send visitors to your Sirius Press instance.
---
## Setting the record
From the Sirius portal at [sirius.x](https://sirius.x): open your name, go to
the DNS tab, add the record, and sign. The change costs nothing and takes
effect as soon as the manifest is published, because records live in a
wallet-signed manifest rather than in a chain transaction.
You can also set them from the registrar CLI if you run one.
---
## Which one to use
**`ip`, if you can.** It is one fewer system between a reader and your site,
and it does not depend on anyone's DNS continuing to answer — which is most of
the point of having a BCNR name in the first place.
**`p`, if your address moves**, or if you are behind a tunnel, or if you want
a CDN in front. The tradeoff is real: a `p` record points at a name in somebody
else's namespace, and whoever controls that namespace can redirect your
visitors. If you are using BCNR to get out from under ICANN, pointing your name
back into it is worth doing deliberately rather than by default.
### Put TLS in front of it, with `ip` + `tls`
An `ip` record on its own is served over plain HTTP, and for a site with an
editor that is not good enough. Two reasons, and the second is the one people
miss:
1. **The session cookie is the account.** There is no password to steal here,
but a cookie read off the wire is a logged-in admin, and a BCNR name does
not stop a network between you and the server.
2. **Manual publishing does not work without it.** The key that signs an
upload is derived in the page, and `crypto.subtle` does not exist outside a
secure context. Over plain HTTP the Publishing screen can queue work and
never sign it.
You do not need a certificate authority. Put a reverse proxy in front with a
**self-signed certificate**, and record its fingerprint on chain:
```bash
openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -nodes \
-keyout server.key -out server.crt -days 3650 \
-subj "/CN=yourname.x" -addext "subjectAltName=DNS:yourname.x,DNS:*.yourname.x"
# the value for the `tls` record
openssl x509 -in server.crt -noout -fingerprint -sha256 \
| sed 's/.*=//; s/://g' | tr 'A-Z' 'a-z'
```
Set `ip` to the server's address and `tls` to that fingerprint. Theseus and
Ariadne both refuse any certificate whose DER SHA-256 does not match — which
is a narrower claim than a CA makes, and it expires on your schedule rather
than someone else's. Rotating the certificate is one record update.
Then stop publishing the container's port to the world, since the proxy is now
the only thing that should reach it:
```ini
# .env
HTTP_BIND=127.0.0.1
```
---
## Telling WordPress its own address
WordPress builds absolute URLs from a value it stores, and it has to match what
visitors actually type or you get redirect loops.
In Docker, set `SITE_URL` in `docker/.env` and restart:
```
SITE_URL=https://example.bch
```
Elsewhere, set it in `wp-config.php`:
```php
define( 'WP_HOME', 'https://example.bch' );
define( 'WP_SITEURL', 'https://example.bch' );
```
Do this once your name resolves, not before — WordPress will happily guess from
the request until then, which is what you want during setup.
---
## The static mirror is separate
Setting `ip` or `p` points readers at your **live WordPress**. It has nothing
to do with the static export.
The export goes to your name's storage on Sia, at `bns/<name>/`, and resolvers
reach it through the name's `s3` record. That means a name can have both:
- an `ip` record, so visitors get the live site with its comments and search
- a populated bucket, so that when the server is down, or slow, or gone, the
last published copy still answers
Which one a given resolver prefers is its business, and different resolvers
choose differently. The useful way to think about it: the live site is where
your site is, and the static mirror is what survives if it stops being there.
If you want *only* the static copy served — no PHP exposed to the public at all
— leave `ip` and `p` unset and let the `s3` record do the work. Your WordPress
then runs somewhere private, as an authoring tool, and publishes outward. For
a site that is mostly reading rather than interaction, this is the strongest
arrangement available, and it is what `silentmode.st` itself does.
---
## Checking it
```bash
curl -s https://navigate.st/api/dns/example.bch | python3 -m json.tool
```
shows the verified records a resolver sees, and
```bash
curl -s https://navigate.st/api/site/example.bch | python3 -m json.tool
```
lists what is actually in the name's bucket — which is the quickest way to
confirm an export arrived.
The **Sirius Press → Publishing** screen shows the same thing from inside
wp-admin, along with whatever the queue is still working through.