Publish stamp-monitor at bee.t4t-gateway.com

The gateway's /bee page shows a summary of the node. This exposes the
monitor behind it, which is where batch fullness, the bucket map, wallet
and chequebook runway, and the ledger of every top-up made or refused
actually live.

Left unrouted originally on the reasoning that its UI can spend xBZZ.
That was the wrong test. The protection is that the app fails CLOSED --
every /api/admin route demands an x-admin-token and returns 503 when
ADMIN_TOKEN is unset -- not that the port was hard to reach. Relying on
the latter is how the batch went unwatched long enough to take the
gateway down; a dashboard nobody can open is a dashboard nobody reads.

Bee itself stays unpublished. Reaching it through the monitor's
passthrough still requires the admin token, which is the whole reason the
monitor sits in front of it.

Also bumps the image to pick up the fix that makes Settings caps bind
manual spending, not just the poller.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YLYiaPYror1vLKApYKrxTu
This commit is contained in:
Felix FaerberandClaude Opus 5 committed 2026-08-20 12:38:06 +03:00
1 parent 02f5905051
commit 550f71d2ab
2 files changed
+35 -15

No files matched your search

+21 -2
View File
@@ -34,8 +34,8 @@ services:
# Bee node that saw them knows how full a batch is. Sitting next to prod_bee # Bee node that saw them knows how full a batch is. Sitting next to prod_bee
# is what makes fullness, the bucket map and batch_full alerts possible. # is what makes fullness, the bucket map and batch_full alerts possible.
stamp-monitor: stamp-monitor:
image: ghcr.io/ffaerber/swarm-stamp-monitor@sha256:62cf97f72090879f8d470fc9f2a09ab60d1d3a29dd658dfe2cd3a313c2b23540 image: ghcr.io/ffaerber/swarm-stamp-monitor@sha256:aebf7e471f41cfdf43f8b6bc8dcdba4d29bc277612a302f61b7ed805b243901c
networks: [internal] networks: [internal, public]
volumes: volumes:
- stamp-monitor-data:/data - stamp-monitor-data:/data
env_file: env_file:
@@ -72,6 +72,25 @@ services:
limits: limits:
cpus: "0.30" cpus: "0.30"
memory: 256M memory: 256M
# Published at bee.t4t-gateway.com. The gateway's own /bee page shows a
# summary; this is the full view — batch fullness, the bucket map, wallet
# and chequebook runway, and the action ledger.
#
# Safe to publish because the app fails CLOSED, not because the network
# protects it: every /api/admin route requires an x-admin-token and
# returns 503 when ADMIN_TOKEN is unset, so a misconfigured deploy is a
# visible outage rather than an open door onto endpoints that buy postage.
# The Bee node itself stays unpublished — reaching it through here still
# needs that token, which is the point of putting the monitor in front.
labels:
- "traefik.enable=true"
- "traefik.docker.network=public"
- "traefik.constraint-label=public"
- "traefik.http.routers.stamp-monitor.rule=Host(`bee.t4t-gateway.com`)"
- "traefik.http.routers.stamp-monitor.entrypoints=websecure"
- "traefik.http.routers.stamp-monitor.tls.certresolver=le"
- "traefik.http.services.stamp-monitor.loadbalancer.server.port=3000"
- "traefik.http.routers.stamp-monitor.middlewares=redirect-to-https"
frontend: frontend:
image: ghcr.io/token-for-token/hosted-gateway-frontend:main image: ghcr.io/token-for-token/hosted-gateway-frontend:main
+14 -13
View File
@@ -30,6 +30,7 @@ Point all of these at `195.35.25.26`:
A t4t-gateway.com 195.35.25.26 A t4t-gateway.com 195.35.25.26
A www.t4t-gateway.com 195.35.25.26 A www.t4t-gateway.com 195.35.25.26
A api.t4t-gateway.com 195.35.25.26 A api.t4t-gateway.com 195.35.25.26
A bee.t4t-gateway.com 195.35.25.26
A dev.t4t-gateway.com 195.35.25.26 A dev.t4t-gateway.com 195.35.25.26
A traefik.t4t-gateway.com 195.35.25.26 A traefik.t4t-gateway.com 195.35.25.26
A grafana.t4t-gateway.com 195.35.25.26 A grafana.t4t-gateway.com 195.35.25.26
@@ -104,9 +105,19 @@ not on-chain** — postage stamps are off-chain signatures, so only a node that
saw them knows how full a batch is. A batch can be fully funded and still saw them knows how full a batch is. A batch can be fully funded and still
refuse writes. refuse writes.
No Traefik route and no published port: it is on `internal` only, and its UI Published at **[bee.t4t-gateway.com](https://bee.t4t-gateway.com)**. The
can spend xBZZ. Note `internal` is **not attachable**, so `docker run --network gateway's own `/bee` page shows a summary; this is the full view — batch
internal ...` is refused — query through a container that is already on it: fullness and the bucket map, wallet and chequebook runway, and the ledger of
every top-up it has made or refused.
It is publishable because the app fails **closed**: every `/api/admin` route
requires an `x-admin-token` and returns 503 if `ADMIN_TOKEN` is unset, so a
misconfigured deploy is a visible outage rather than an open door onto
endpoints that spend xBZZ. The Bee node stays unpublished; reaching it through
the monitor's passthrough still requires that token.
From the shell, note `internal` is **not attachable**, so `docker run --network
internal ...` is refused — query through a container already on it:
```bash ```bash
docker service logs --tail 50 prod_stamp-monitor docker service logs --tail 50 prod_stamp-monitor
@@ -115,16 +126,6 @@ M=$(docker ps --filter name=prod_stamp-monitor -q | head -1)
docker exec $M bun -e 'console.log(await (await fetch("http://bee:1633/stamps")).text())' docker exec $M bun -e 'console.log(await (await fetch("http://bee:1633/stamps")).text())'
``` ```
For the dashboard, publish it only for as long as you are looking at it, and
tunnel rather than exposing the port — swarm ingress binds `0.0.0.0`, so a
published port is on the public internet:
```bash
docker service update --publish-add published=8088,target=3000 prod_stamp-monitor
ssh -L 8088:127.0.0.1:8088 root@<host> # then http://127.0.0.1:8088
docker service update --publish-rm published=8088,target=3000 prod_stamp-monitor
```
The API authenticates with an **`x-admin-token`** header, not `Authorization: The API authenticates with an **`x-admin-token`** header, not `Authorization:
Bearer`. A wrong header is a 401; a missing `ADMIN_TOKEN` in the service is a Bearer`. A wrong header is a 401; a missing `ADMIN_TOKEN` in the service is a
503 (`admin API disabled`) — it fails closed, because these routes buy postage. 503 (`admin API disabled`) — it fails closed, because these routes buy postage.