v0.25.1
sleep3r/mtproto.zigv0.25.1Jun 4, 2026by sleep3r
Upgrading?
AI Summary
Fixes a systemd timer issue where the tunnel pool timer would become 'elapsed' and stop running periodic failover checks.
Key Highlights
- Tunnel pool timer now uses `OnUnitInactiveSec` to correctly repeat after each run.
- Proxy restart is no longer the only way to refresh tunnel routing.
- Regression test added to prevent future generation of elapsed timers.
Full Release Notes
<details open> <summary>🇷🇺 Что нового (RU)</summary> ## Что решает этот релиз `v0.25.1` — patch-релиз для операторов, которые используют AmneziaWG / WireGuard tunnel mode через `mtbuddy setup tunnel`. В `v0.25.0` tunnel pool получил нормальный lifecycle management: TUI и dashboard научились видеть, заменять и удалять tunnel interfaces. Но в production-варианте обнаружился отдельный systemd edge case: `mtproto-tunnel-pool.timer` мог быть enabled, но больше не запускать periodic failover checks. Выглядело это так: ```text mtproto-tunnel-pool.timer: active (elapsed) Trigger: n/a LastTriggerUSec: Sat 2026-05-23 ... ``` Из-за этого `setup_tunnel.sh` не перепроверял tunnel health и не переустанавливал `fwmark 200 -> table 200 -> awg0`. Если route/tunnel state деградировал, пользовательские соединения могли зависать на MTProto handshake, а ручной restart `mtproto-proxy` временно всё лечил, потому что `mtproto-proxy.service` снова запускал: ```text ExecStartPre=/usr/local/bin/setup_tunnel.sh ``` Корень проблемы был в systemd timer contract для oneshot service: timer использовал `OnUnitActiveSec=30s`, а `mtproto-tunnel-pool.service` — это короткий `Type=oneshot`. Для таких health-check jobs надёжнее планировать следующий запуск от момента завершения unit, то есть через `OnUnitInactiveSec=30s`. `v0.25.1` меняет timer template именно на это поведение и добавляет regression test, чтобы future `mtbuddy setup tunnel` больше не генерировал одноразовый elapsed timer. > [!NOTE] > Обновление бинарника само по себе не переписывает уже установленный `/etc/systemd/system/mtproto-tunnel-pool.timer`. После обновления заново выполните tunnel setup через `sudo mtbuddy --interactive` → `Setup tunnel` или повторите `sudo mtbuddy setup tunnel ...` с текущим tunnel config/link, чтобы regenerate systemd units. > [!TIP] > После regeneration проверьте: > > ```bash > systemctl list-timers mtproto-tunnel-pool.timer --all > systemctl status mtproto-tunnel-pool.timer > ``` > > У здорового timer должен быть будущий `NEXT` trigger и состояние `active (waiting)`, а не `active (elapsed)` / `Trigger: n/a`. ## Что изменено ### Tunnel pool timer снова повторяется после oneshot run ([#291](https://github.com/sleep3r/mtproto.zig/pull/291)) - `mtproto-tunnel-pool.timer` теперь генерируется с `OnUnitInactiveSec=30s`. - Следующий запуск планируется после завершения `mtproto-tunnel-pool.service`, что подходит для `Type=oneshot`. - Periodic failover checks снова продолжают: - поднимать/проверять configured tunnel interfaces; - обновлять route table 200; - подтверждать `ip route get ... mark 200`; - писать свежий `/run/mtproto-proxy/tunnel-pool.state`. ### Рестарт прокси больше не должен быть единственным способом «оживить» tunnel route ([#291](https://github.com/sleep3r/mtproto.zig/pull/291)) - До фикса route refresh мог происходить только при `systemctl restart mtproto-proxy`, потому что proxy unit запускал `setup_tunnel.sh` в `ExecStartPre`. - После regeneration timer сам продолжает выполнять tunnel pool controller. - Это закрывает класс ситуаций, где MTProto connections застревают в `hs_inflight`, а ручной restart выглядит как единственное восстановление. ### Тесты mtbuddy теперь реально подтягивают tunnel command tests ([#291](https://github.com/sleep3r/mtproto.zig/pull/291)) - Добавлен test hook для `src/ctl/tunnel.zig` из `mtbuddy` test target. - Добавлен regression test на `OnUnitInactiveSec=30s` в timer template. - Обновлён один tunnel test под текущий Zig 0.16 file IO API. ## Проверено - `zig build test --summary all` - GitHub Actions: - `Test & Build` - `Bench (No Soak)` - `E2E Integration` - installer e2e: `debian:12` - installer e2e: `ubuntu:24.04` - На affected host проверено, что обновлённый timer переходит в `active (waiting)` и повторно запускает `mtproto-tunnel-pool.service`. </details> --- <details> <summary>🇬🇧 Release notes (EN)</summary> ## What this release addresses `v0.25.1` is a patch release for operators using AmneziaWG / WireGuard tunnel mode through `mtbuddy setup tunnel`. `v0.25.0` added proper tunnel pool lifecycle management: the TUI and dashboard can now inspect, replace, and delete tunnel interfaces. A separate production systemd edge case showed up afterwards: `mtproto-tunnel-pool.timer` could remain enabled while no longer scheduling periodic failover checks. It looked like this: ```text mtproto-tunnel-pool.timer: active (elapsed) Trigger: n/a LastTriggerUSec: Sat 2026-05-23 ... ``` As a result, `setup_tunnel.sh` stopped rechecking tunnel health and stopped refreshing `fwmark 200 -> table 200 -> awg0`. If route or tunnel state degraded, user connections could get stuck during MTProto handshake, while manually restarting `mtproto-proxy` appeared to fix it because the proxy unit ran: ```text ExecStartPre=/usr/local/bin/setup_tunnel.sh ``` The root cause was the timer contract for a oneshot service: the timer used `OnUnitActiveSec=30s`, while `mtproto-tunnel-pool.service` is a short `Type=oneshot` job. For this kind of health check, the next run should be scheduled after the unit exits, using `OnUnitInactiveSec=30s`. `v0.25.1` changes the generated timer template to that behavior and adds a regression test so future `mtbuddy setup tunnel` runs no longer create a one-shot elapsed timer. > [!NOTE] > Updating the binary alone does not rewrite an already installed `/etc/systemd/system/mtproto-tunnel-pool.timer`. After updating, rerun tunnel setup through `sudo mtbuddy --interactive` → `Setup tunnel`, or rerun `sudo mtbuddy setup tunnel ...` with the current tunnel config/link to regenerate the systemd units. > [!TIP] > After regeneration, check: > > ```bash > systemctl list-timers mtproto-tunnel-pool.timer --all > systemctl status mtproto-tunnel-pool.timer > ``` > > A healthy timer should have a future `NEXT` trigger and show `active (waiting)`, not `active (elapsed)` / `Trigger: n/a`. ## What changed ### Tunnel pool timer repeats after each oneshot run again ([#291](https://github.com/sleep3r/mtproto.zig/pull/291)) - `mtproto-tunnel-pool.timer` is now generated with `OnUnitInactiveSec=30s`. - The next run is scheduled after `mtproto-tunnel-pool.service` finishes, matching its `Type=oneshot` behavior. - Periodic failover checks keep: - bringing up/checking configured tunnel interfaces; - refreshing route table 200; - validating `ip route get ... mark 200`; - writing fresh `/run/mtproto-proxy/tunnel-pool.state`. ### Restarting the proxy should no longer be the only way to refresh tunnel routing ([#291](https://github.com/sleep3r/mtproto.zig/pull/291)) - Before this fix, route refresh could happen only on `systemctl restart mtproto-proxy`, because the proxy unit ran `setup_tunnel.sh` in `ExecStartPre`. - After regenerating the units, the timer continues running the tunnel pool controller by itself. - This closes the class of incidents where MTProto connections accumulate in `hs_inflight`, while a manual proxy restart looks like the only recovery path. ### mtbuddy tests now include tunnel command tests ([#291](https://github.com/sleep3r/mtproto.zig/pull/291)) - Added a test hook so the `mtbuddy` test target references `src/ctl/tunnel.zig`. - Added a regression test for `OnUnitInactiveSec=30s` in the generated timer template. - Updated one tunnel test to the current Zig 0.16 file IO API. ## Verified - `zig build test --summary all` - GitHub Actions: - `Test & Build` - `Bench (No Soak)` - `E2E Integration` - installer e2e: `debian:12` - installer e2e: `ubuntu:24.04` - Verified on the affected host that the updated timer enters `active (waiting)` and repeatedly triggers `mtproto-tunnel-pool.service`. </details> ## Changelog * fix: keep tunnel pool timer recurring ([#291](https://github.com/sleep3r/mtproto.zig/pull/291)) ([59e2608](https://github.com/sleep3r/mtproto.zig/commit/59e2608f6f71c88e8d3173f832848956f002a9ac)) * chore(main): release 0.25.1 ([#293](https://github.com/sleep3r/mtproto.zig/pull/293)) ([1cc4f1b](https://github.com/sleep3r/mtproto.zig/commit/1cc4f1b))
Related Repositories
lightpanda-io/browser★ 36,854
Lightpanda: the headless browser designed for AI and automation
tigerbeetle/tigerbeetle★ 17,229
The financial transactions database designed for mission critical safety and performance.
nullclaw/nullclaw★ 8,131
Fastest, smallest, and fully autonomous AI assistant infrastructure written in Zig
zml/zml★ 4,194
Any model. Any hardware. Zero compromise. Built with @ziglang / @openxla / MLIR / @bazelbuild
dmtrKovalenko/odiff★ 3,280
A very fast SIMD-first image comparison library (with nodejs API)