docs: show the log, and that it holds no addresses
Build docker image and push to registry.bitdeals.org / main-build-job (push) Successful in 24s

The Notes explain at length that no visitor's IP address reaches the log and
why both loggers are hand-written to keep it that way. Nothing showed it. A
reader had to take the claim on faith or read haproxy.cfg.

Add a "the log" section to Usage in both READMEs: a real
`docker compose logs haproxy` excerpt from a running node, the two log formats
broken down field by field, and the point the sample exists to make — the
first field is the X-Client-Id pseudonym, and it is all the log knows about
who connected.
This commit is contained in:
2026-08-19 08:35:59 +00:00
parent 1f9452b773
commit b84f2e8c99
2 changed files with 70 additions and 0 deletions
+35
View File
@@ -75,6 +75,41 @@ docker run --rm -v "$PWD/docker/haproxy.cfg:/tmp/haproxy.cfg:ro" \
registry.bitdeals.org/haproxy -c -f /tmp/haproxy.cfg registry.bitdeals.org/haproxy -c -f /tmp/haproxy.cfg
``` ```
## the log
`docker compose logs haproxy` on a running node:
```text
haproxy-1 | XFF_HMAC_KEY was not set — generated one for this container.
haproxy-1 | [NOTICE] (1) : Automatically setting global.maxconn to 32745.
haproxy-1 | rlj13BvDLpJLzzHbutTiC5fjK0OR4YRlPrYnJIHpO7Y= [18/Aug/2026:10:25:25.196] http 1/1 Success
haproxy-1 | wgM6JB1uN2AGFKkl67+O7SCx+DHrGttufQw0HDQMSIU= [18/Aug/2026:10:45:10.700] https~ 1/1 SSL handshake failure
haproxy-1 | 5056er7Wogz59zFJfaNNelKpEnxzEISztzbgn/omnHg= [18/Aug/2026:10:54:38.337] https~ 1/1 Connection closed during SSL handshake
haproxy-1 | 6TPbf9FXhRxBoy+SSpFrOuTvYjZF3RjTQmdCteZWH3s= [19/Aug/2026:04:13:17.521] https~ default-backend-http/main 400 289 0/497 SSTP_DUPLEX_POST /sra_{BA195980-CD49-458b-9E23-C84EE0ADCD75}/
```
**No line carries an IP address, and none can.** The first field is the
pseudonym from `X-Client-Id` — HMAC-SHA256 of the visitor's address under
`XFF_HMAC_KEY`, base64 — and it is everything the log knows about who
connected. Both loggers are written out by hand for exactly that reason: their
defaults open with `%ci:%cp`, the address and the port. See Notes.
The four request lines are the two formats:
- connection level, `%[var(sess.cid)] [%tr] %ft %ac/%fc %[fc_err_str]`
pseudonym, time, frontend, connection counts, how the connection ended.
Everything that dies before a request exists lands here: a client that offers
nothing above TLS 1.1, a scanner that hangs up mid-handshake, a probe that
opened the port and left.
- transaction level, `… %ft %b/%s %ST %B %TR/%Ta %HM %HP` — pseudonym, time,
frontend, backend/server, status, bytes, timers, method, path. The last line
is a 400 for a stray SSTP probe. The path ends where the query string starts;
that part is never logged.
Successful requests write nothing at all (`option dontlog-normal`), so a log
this quiet is the normal state of a working node, not a sign that the loggers
are misconfigured.
## build and publish ## build and publish
A push to `main` builds and publishes the image A push to `main` builds and publishes the image
+35
View File
@@ -75,6 +75,41 @@ docker run --rm -v "$PWD/docker/haproxy.cfg:/tmp/haproxy.cfg:ro" \
registry.bitdeals.org/haproxy -c -f /tmp/haproxy.cfg registry.bitdeals.org/haproxy -c -f /tmp/haproxy.cfg
``` ```
## Журнал
`docker compose logs haproxy` на работающем узле:
```text
haproxy-1 | XFF_HMAC_KEY was not set — generated one for this container.
haproxy-1 | [NOTICE] (1) : Automatically setting global.maxconn to 32745.
haproxy-1 | rlj13BvDLpJLzzHbutTiC5fjK0OR4YRlPrYnJIHpO7Y= [18/Aug/2026:10:25:25.196] http 1/1 Success
haproxy-1 | wgM6JB1uN2AGFKkl67+O7SCx+DHrGttufQw0HDQMSIU= [18/Aug/2026:10:45:10.700] https~ 1/1 SSL handshake failure
haproxy-1 | 5056er7Wogz59zFJfaNNelKpEnxzEISztzbgn/omnHg= [18/Aug/2026:10:54:38.337] https~ 1/1 Connection closed during SSL handshake
haproxy-1 | 6TPbf9FXhRxBoy+SSpFrOuTvYjZF3RjTQmdCteZWH3s= [19/Aug/2026:04:13:17.521] https~ default-backend-http/main 400 289 0/497 SSTP_DUPLEX_POST /sra_{BA195980-CD49-458b-9E23-C84EE0ADCD75}/
```
**Ни в одной строке нет IP-адреса, и появиться ему неоткуда.** Первое поле —
псевдоним из `X-Client-Id`, HMAC-SHA256 от адреса посетителя на ключе
`XFF_HMAC_KEY` в base64, — и это всё, что журнал знает о том, кто подключился.
Оба логгера выписаны вручную именно поэтому: их умолчания начинаются с
`%ci:%cp`, то есть с адреса и порта. См. «Замечания».
Четыре строки обращений — это два формата:
- уровень соединения, `%[var(sess.cid)] [%tr] %ft %ac/%fc %[fc_err_str]`:
псевдоним, время, фронтенд, счётчики соединений, чем соединение кончилось.
Сюда попадает всё, что умирает до появления запроса: клиент, не предлагающий
ничего выше TLS 1.1, сканер, обрывающий рукопожатие на середине, проба,
которая открыла порт и ушла.
- уровень транзакции, `… %ft %b/%s %ST %B %TR/%Ta %HM %HP`: псевдоним, время,
фронтенд, бэкенд/сервер, статус, байты, таймеры, метод, путь. Последняя строка
— 400 в ответ на случайную SSTP-пробу. Путь заканчивается там, где начинается
строка запроса: её в журнале нет никогда.
Успешные запросы не пишутся вовсе (`option dontlog-normal`), поэтому настолько
тихий журнал — нормальное состояние работающего узла, а не признак того, что
логгеры настроены неверно.
## Сборка и публикация ## Сборка и публикация
Push в `main` собирает и публикует образ (`.gitea/workflows/build.yaml`) с тремя Push в `main` собирает и публикует образ (`.gitea/workflows/build.yaml`) с тремя