Skip to content

NodeFlow 2.0.1 - #14

Merged
SHOKOVprod merged 9 commits into
mainfrom
release-2.0.1
Sep 25, 2026
Merged

SHOKOVprod merged 9 commits into
mainfrom
release-2.0.1

Conversation

@SHOKOVprod

Copy link
Copy Markdown
Contributor

NodeFlow 2.0.1

Panel 2.0.1 · Node Agent 2.0.1 · HAProxy renderer v21

Исправительный релиз поверх 2.0.0 и одна новая настройка ноды. Миграций базы данных нет, существующие маршруты и ноды рендерятся байт в байт как в 2.0.0.

Новое

  • «Логи соединений HAProxy» в настройках ноды. Переключатель в диалоге настроек ноды (API: поле haproxy_logs у ноды, хранится в nodes.metadata). По умолчанию включено — конфиг не меняется. Выключено: из haproxy.cfg этой ноды убираются log /dev/log … в global, log global, option tcplog и option dontlognull в defaults и option tcplog у frontend'ов, поэтому rsyslog больше не пишет каждое соединение в /var/log/haproxy.log. Нужно для нод с маленьким диском. Сообщения HAProxy о запуске и ошибках конфигурации по-прежнему попадают в journal. Переключение публикует новую ревизию конфига ноды, Agent применяет её обычным reload без разрыва соединений. Клиенты API, которые не передают поле, не сбрасывают сохранённое значение.

Исправления

  • Маршрут с одним сервером не сохранялся с ошибкой sticky_mode must be source, source_table, leastconn or roundrobin. Редактор отправляет sticky_mode: none для одиночного сервера (и для одного домена в режиме DNS-пула), а проверка одиночных маршрутов не принимала none. Теперь none принимается и означает «без закрепления», как у маршрутов с несколькими серверами. Если открыть и сохранить существующий маршрут из одного сервера с закреплением клиента, из его backend исчезнут строки balance/stick: для одного сервера они ничего не меняли.
  • Редактор маршрутов проверяет поля так же, как API. Раньше редактор пропускал значения, которые API затем отклонял с ошибкой 400:
    • IPv4 с ведущими нулями (01.2.3.4) и некорректные IPv6 (1:::2, :::) в адресе прослушивания, адресах серверов, основном IP, весах IP и доверенных адресах PROXY;
    • имена хостов с числовой последней частью (backend.1, host.0x1f) в SNI и адресах серверов;
    • подсети доверенных адресов вида 10.0.0.0/0 (разрешены только 0.0.0.0/0 и ::/0) и ::ffff:0:0/96;
    • один и тот же IPv6, записанный по-разному, в весах IP;
    • в «Основной + резервные» — резервный DNS-пул (или пул с основным IP) вместе с другими резервными;
    • имя сервера, совпадающее с именами слотов DNS-пула (x и x_1);
    • директивы balance, server, default-server, hash-type, server-template в ручных директивах backend при DNS-пуле;
    • табуляция в имени маршрута.
  • Ручная директива длиной 509–512 байт сохранялась, но потом ломала рендер конфига всей ноды (invalid_route_set, 422). Лимит длины строки теперь считается без отступа, ранее рендерившиеся конфиги не меняются.
  • Имя ноды длиннее 200 символов возвращало 500 (или обрывало задание установки ноды). Теперь 400 с понятной ошибкой, поля ввода ограничены 200 символами.
  • Загрузка релиза Agent проверяет формат версии до отправки файла (до 64 МиБ), а не после.
  • Добавлен контрактный тест редактор ↔ API: 4685 вариантов маршрутов, которые разрешает редактор, проходят через проверку и рендерер Panel, а сохранённые без изменений маршруты дают тот же конфиг байт в байт.

Обновление с 2.0.0

  1. Panel. Повторно запустите установщик:

    curl -fsSL https://raw.githubusercontent.com/NodeFlow-dev/nodeflow/main/install.sh | sudo sh

    Вручную: в /opt/nodeflow/.env укажите NODEFLOW_VERSION=2.0.1 и выполните docker compose pull && docker compose up -d. Миграций нет, откат — вернуть NODEFLOW_VERSION=2.0.0.

  2. Node Agent. «Настройки → Node Agent» → «Обновить до 2.0.1». Код Agent не менялся (обновление выравнивает версию). Переключатель логов работает и с Agent 2.0.0.

Обновляетесь с 1.0.x — сначала прочитайте заметки к релизу 2.0.0: там однократный drop-in systemd для pipe-буферов ядра.

Файлы релиза

  • NodeFlow-Panel-2.0.1-Agent-2.0.1-install-kit.tar.gz — install kit.
  • nodeflow-node-agent-2.0.1-linux-amd64, nodeflow-node-agent-2.0.1-linux-arm64 — бинарники Node Agent.

Panel поставляется образом ghcr.io/nodeflow-dev/nodeflow-panel:2.0.1 (linux/amd64 и linux/arm64). SHA-256 каждого файла — поле digest в API релиза; install.sh и install-node.sh сверяют его сами.

The route editor sends sticky_mode "none" for a pool route with one plain
server and uses the legacy single-target payload (servers: []). The flat
path (resolveStickyMode) only accepted source/source_table/leastconn/
roundrobin, so creating such a route failed with "sticky_mode must be
source, source_table, leastconn or roundrobin". A servers[] payload with a
single plain server is folded into the same path and failed the same way.

Treat "none" on the flat path as the legacy "no stickiness" value
(roundrobin, as in the 000052 backfill), so it is stored and rendered
byte-identically to the same route saved without sticky_mode.
- custom_fragment: apply the 512-byte line limit to the directive without
  indentation. Stored fragments are indented by four spaces and the renderer
  re-validates them, so a 509-512 byte directive was accepted on save and
  then failed the whole node config with invalid_route_set.
- nodes: reject names longer than 200 characters (nodes.name CHECK) in
  POST/PUT /api/v1/nodes and bootstrap validation instead of failing with a
  500 / at the create_node job stage; cap the node name inputs at 200.
The editor accepted values that validateRoute rejects with a 400 on save:
- IPv4 with leading zeros (01.2.3.4) and malformed IPv6 (1:::2, 1::2::3,
  :::, 7 groups) in listener IP, server host, preferred IP, per-IP weights
  and accept_proxy_from; parse IPv6 like Go net.ParseIP.
- host names whose last label is numeric or 0x-hex (backend.1, host.0x1f).
- accept_proxy_from x.x.x.x/0 other than 0.0.0.0/0 or ::/0, and
  IPv4-mapped IPv6 prefixes (::ffff:0:0/96).
- the same per-IP weight address in two IPv6 spellings.
- failover with a DNS-pool reserve (or a preferred IP) plus other reserves.
- server names colliding with DNS-pool slot names (<pool>_<N>).
- expert-layer balance/hash-type/server/server-template/default-server on
  a DNS-pool route.
- control characters (tab) in the route name.
The 512-byte expert line limit now counts the directive without its
indentation, matching the backend.
POST /api/v1/agent-releases rejects versions outside
^[0-9A-Za-z][0-9A-Za-z._+-]{0,63}$ with 'invalid release version or
platform' only after the whole binary was uploaded; validate the version
field up front with the same pattern.
frontend/tests/routeMatrix.ts builds route editor drafts over every control
(SNI/fallback, listener, accept PROXY, 1/2+/DNS-pool/unix servers,
pool/failover layouts, distribution, algorithms with tuning, health check,
PROXY v1/v2, slowstart, quota, bandwidth, expert layer), boundary values
and stored routes from every schema era, keeps only drafts the editor
accepts and serialises their routePayload() output to
internal/panel/testdata/ui_route_payloads.json.gz. The npm test fails when
the fixture is stale (UPDATE_UI_FIXTURES=1 npm test regenerates it).

TestUIRoutePayloadsPassBackendValidation feeds every payload through
validateRoute and the renderer and checks that an existing route saved
unchanged renders byte-for-byte identically. The flat sticky_mode none
rejection is skipped as known (fixed in fix-sticky).
Small nodes fill their disks with /var/log/haproxy.log (rsyslog writes
every TCP connection). Add a node setting «Логи соединений HAProxy»,
stored as nodes.metadata.haproxy_logs (absent = on, no migration).

- Renderer: with the setting off, drop the global 'log' targets,
  'log global', 'option tcplog', 'option dontlognull' and the per-frontend
  'option tcplog'. Default output is byte-identical (golden files
  unchanged); off renders as v21 and records haproxy_logs=false in the
  revision metadata.
- API: node responses carry haproxy_logs; POST/PUT /api/v1/nodes accept
  a boolean haproxy_logs (or metadata.haproxy_logs) and reject other
  types. An update whose metadata omits the key keeps the stored value.
- Toggling publishes a new route revision in the same transaction, so
  the Agent applies it with a graceful reload.
- UI: switch in the node settings dialog.
@SHOKOVprod
SHOKOVprod merged commit 89007de into main Sep 25, 2026
3 checks passed
@SHOKOVprod
SHOKOVprod deleted the release-2.0.1 branch September 25, 2026 02:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant