Repository navigation
Releases
v2.8.0
ser2net v2.8.0 — Turkish web UI, Linux arm64, Windows service, Docker image, notifications, Modbus write + Sparkplug B, classic ser2net import (#28–#32)
Upgrading from 2.7.x
Nothing to migrate: replace the program (or pull the new image) and restart. config.json and data/ are used as they are.
- Backups: the first configuration change keeps the old
config.jsonindata/backups/. - Trace paths: a trace path in an old config becomes a file name under
data/traces/, and the start-up log names the move. This is a security fix (below). - Docker: the image runs as an unprivileged user (uid 10001). A
/datavolume written by the old root image is taken over on its first start. The image is now on GHCR:ghcr.io/haliskilic/ser2net:2.8.0(also2.8andlatest), for amd64 + arm64.docker-compose.ymluses it. - Web UI language: English or Turkish, by the browser's language, unless a visitor picks TR / EN or the admin sets Settings → Web UI access → Default language.
- Import: importing now shows a preview first. Scripts that post the 2.7-style one-step import still replace every mapping, as before.
Security
- Updating is recommended: v2.7.1 ships dependency versions with known vulnerabilities. They are fixed here:
- starlette: GHSA-82w8-qh3p-5jfq (high), form size limits ignored for URL-encoded bodies, which affects the sign-in form; GHSA-jp82-jpqv-5vv3 (low).
- anyio: GHSA-82r6-8w77-94w6 and GHSA-5p39-cfhj-2xmp.
- pyasn1 0.6.5 (ldap3), bundled in the executables.
- Traces can no longer write outside the data directory. A mapping's trace was a free file path, so an operator (not only an admin) could have network bytes appended to any file the service may write:
config.json, a startup script, and as root in Docker. Traces now always go to<data>/traces/<mapping id>-<file name>. - The Docker image no longer runs as root.
- Audit records can't be forged with control characters in a user-supplied name.
Added
-
Turkish web UI next to English. Logs, the audit log and the REST API stay English; notifications use the admin's default language.
-
USB identity: a mapping can find its device by VID:PID + serial number, so re-plugging an adapter as another
ttyUSB*/COM*keeps it working.- The port list shows
/dev/serial/by-idnames, and they can be selected. - The kernel's placeholder
ttySports without hardware are hidden.
- The port list shows
-
Notifications by webhook (JSON, Slack/Mattermost, Microsoft Teams, Discord, Telegram) and/or e-mail (SMTP) when:
- a serial device is lost or comes back;
- a mapping fails to start;
- clients connect or disconnect;
- a sign-in fails.
Repeats are suppressed and the rate is limited; Settings → Notifications can send a test message.
-
Dashboard: search, state filter, sort, and start / stop / restart of the selected mappings. The table is redrawn only when it changed, so it no longer flickers or loses the selection.
-
Traces in the UI: download a mapping's trace files (current + rotated), and a live hex view in the console with both directions and timestamps.
-
Modbus write from MQTT: points with
"writable": truetake values from<topic>/<point>/set.- Coils use FC5/FC15, holding registers FC6/FC16. The result goes to
…/set/result. - Coils and discrete inputs (FC1/FC2) can be polled too.
- Coils use FC5/FC15, holding registers FC6/FC16. The result goes to
-
Sparkplug B: a Modbus-polling mapping can be an edge node whose devices are the Modbus units it polls (
unit1,unit2, …).- NBIRTH/NDEATH carry
bdSeq; DBIRTH/DDATA carryseq. - Points are written through DCMD; NCMD triggers a rebirth.
- No protobuf dependency.
- NBIRTH/NDEATH carry
-
Import from the classic ser2net:
ser2net.yaml(4.x) andser2net.conf(3.x) go through the import preview. Options without an equivalent are listed as warnings.- ser2net opens a device only while a client is connected, but a mapping here keeps it open. So of several ports on one device, the first comes in enabled and the others disabled.
-
Configuration backups (newest 50, download / restore; a restore can be undone), an import preview (merge or replace) and an audit log viewer (search, filters, CSV) in Settings.
-
Linux arm64 executable (
ser2net-linux-arm64, glibc ≥ 2.28): Raspberry Pi 3/4/5 with a 64-bit OS, ARM gateways. -
Windows service with no extra software:
ser2net.exe --install-service/--uninstall-service.- It starts at boot and restarts after a failure;
--service-nameallows several instances.
- It starts at boot and restarts after a failure;
-
Release integrity:
SHA256SUMS, a CycloneDX SBOM per executable, and GitHub build-provenance and SBOM attestations. -
--about: component versions for bug reports. -
--licenses: the license texts of every bundled component. -
--healthcheck: used by the Docker HEALTHCHECK. -
SER2NET_LIB_OVERRIDE: loads a replacement ldap3 (LGPL).
Fixed
- The session lifetime setting now takes effect: sessions always lasted 8 hours before. It is under Settings → Web UI access.
- Writing a trace no longer blocks the event loop, and trace files rotate at a size limit (default 10 MB, 3 old files kept).
- The Docker HEALTHCHECK no longer reports a fresh container unhealthy while it waits for the first-run setup.
Changed
- Dependencies updated: starlette 1.10.0, uvicorn 0.54.0, websockets 17.4, python-multipart 0.0.33, anyio 4.16.0.
- Python 3.10 keeps the last releases that support it.
- The offline wheels in
vendor/wheels/match.
- CI adds mypy, pip-audit, coverage and Dependabot, and
mainis protected. - New repository files:
SECURITY.md,CONTRIBUTING.md,CHANGELOG.md.
Tested before publishing
- Every PR runs the test suite on Linux and Windows × Python 3.10–3.13.
- The executables are built and tested before they are attached. That includes the arm64 one, in 9 clean distributions each, and a real Windows service install / restart-after-crash / stop / uninstall.
- The dashboard, the mapping views and the settings page are checked in a browser at 1440 → 390 px, in English and Turkish.
- The Docker image is smoke-tested on amd64 and arm64, including the upgrade from a v2.7.1 volume.
Verify a download
sha256sum -c SHA256SUMS --ignore-missing
gh attestation verify ser2net-linux-x64 --repo haliskilic/ser2net
Türkçe özet
- Türkçe arayüz: üst menüde TR / EN; seçilmemişse tarayıcının dili ya da admin'in varsayılan dili. Log'lar, audit log ve REST API İngilizce kalıyor.
- Güncellemen önerilir: v2.7.1'deki starlette ve anyio sürümlerinde bilinen güvenlik açıkları var, bu sürümde kapandı.
- Trace güvenlik düzeltmesi: trace dosyaları artık yalnızca
data/traces/altına yazılabiliyor. Eskiden bir operator herhangi bir dosyaya yazdırabiliyordu. - Yeni özellikler:
- USB kimliğiyle cihaz bulma;
- webhook ve e-posta bildirimleri;
- panoda arama, filtre ve toplu işlem;
- trace indirme ve canlı hex görünümü;
- MQTT'den Modbus yazma;
- Sparkplug B (her Modbus unit'i bir cihaz);
- klasik
ser2net.yaml/ser2net.confiçe aktarma; - config yedekleri ve geri yükleme;
- içe aktarma önizlemesi;
- audit log ekranı.
- Dağıtım:
- Linux arm64 binary'si;
- ek program gerektirmeyen Windows servisi;
- GHCR'de amd64 + arm64 Docker imajı (root olmayan kullanıcıyla);
SHA256SUMS, SBOM ve build provenance.
- Yükseltme: v2.7.x'ten geçişte bir şey yapmana gerek yok.
config.jsonvedata/olduğu gibi kullanılıyor; ilk değişiklikte eski configdata/backups/içine yedekleniyor.
Downloads: ser2net-windows-x64.exe (Windows 10/11, Server 2016+) · ser2net-linux-x64 (x86_64, glibc ≥ 2.28) · ser2net-linux-arm64 (aarch64, glibc ≥ 2.28). They are standalone: nothing else to install. Docker: docker pull ghcr.io/haliskilic/ser2net:2.8.0.
v2.7.1
ser2net v2.7.1 — long names in the web UI, truly standalone executables (#26)
Fixed
- Long names no longer push the row buttons out of the web panel. Long mapping names,
/dev/serial/by-id/…paths, remote host names and error messages used to make the mappings and cluster tables wider than their panel: the Start/Stop/…/Delete buttons sat outside it and the page scrolled sideways.- Long text now wraps at separators (
/ _ . : -). - The row buttons wrap inside their cell in two groups, and stay on one line when there is room.
- Errors are clamped to 3 lines, with the full text in the tooltip.
- Below 940 px the lists become cards.
- The top bar, the log and console headers and the forms also handle long names and phone screens.
- Long text now wraps at separators (
- The Linux executable runs on glibc ≥ 2.28. The v2.7.0 binary needed glibc 2.38 and did not start on Ubuntu 22.04/20.04, Debian 12/11 or RHEL/Alma/Rocky 8–9.
- It is now built in an AlmaLinux 8 container with a python-build-standalone CPython.
- It runs on RHEL/AlmaLinux/Rocky 8+, Debian 11+, Ubuntu 20.04+, Fedora and openSUSE Leap 15 (x86_64; not musl/Alpine — use Docker there).
- It is also smaller: ~24 MB instead of ~34 MB.
- "Generate self-signed certificate" no longer needs the
opensslprogram; before, it never worked on Windows. The certificate is now made in-process with the bundledcryptography, with SAN localhost / 127.0.0.1 / ::1 / host name. - The Linux executable finds the distribution's CA certificates (Debian/Ubuntu, RHEL/Fedora, openSUSE and Alpine layouts) for certificate checks in MQTT over TLS and OIDC sign-in. Set
SSL_CERT_FILEto override; the startup log names the bundle in use. - Windows hardening:
icacls(data-folder permissions) is run by its full System32 path, so anicacls.exeplanted next to the exe can't run instead.
Tested before publishing
From this release on, the executables are only attached after these checks pass on every PR and release:
- the bundle needs nothing but OS-base libraries (glibc ≤ 2.28 / Windows system DLLs), and the VC++ runtime and Python are inside;
- they run with an empty
PATH(no Python, noopenssl): web UI, TCP mapping, MQTT/LDAP/OIDC libraries, certificate generation, OIDC over certificate-checked HTTPS; - every library the running process loads comes from the bundle or the OS;
- the Linux binary runs in clean AlmaLinux 8/9, Debian 11/12, Ubuntu 20.04/22.04/24.04, openSUSE Leap 15.6 and Fedora containers.
A browser test (Chromium, 1440 → 390 px) also guards the long-name layout.
Upgrading from 2.7.0
Nothing to migrate: replace the program and restart. config.json and data/ stay as they are. Coming from 2.6.x, see the v2.7.0 notes as well.
- Linux binary: it unpacks itself to
$TMPDIR(default/tmp) at start. If/tmpis mountednoexec, pointTMPDIRat a directory that isn't. - Web UI: the mappings and cluster tables now have 7 columns: serial parameters under the port, mode/type under the address. Browsers fetch the new CSS by themselves (versioned asset URLs).
- Log: the Linux binary logs
TLS: using the system CA bundle …at start, or a warning when it finds none.
Türkçe özet
- Web panelinde uzun eşleme adları,
/dev/serial/by-id/…yolları ve hata mesajları artık butonları panelin dışına taşırmıyor; dar ekranlarda liste kart görünümüne geçiyor. - Linux binary'si artık glibc 2.28 ve üzeri her x86_64 dağıtımda çalışıyor; önceden glibc 2.38 istiyordu.
- "Self-signed sertifika üret" harici
opensslgerektirmiyor. - Linux binary'si dağıtımın CA sertifikalarını kendisi buluyor.
- Binary'ler her PR'da ve her sürümde test ediliyor: boş PATH ile çalıştırma, yüklenen kütüphanelerin kaynağı ve 9 temiz dağıtım konteyneri. Yayın ancak bunlar geçince yapılıyor.
Downloads: ser2net-windows-x64.exe (Windows 10/11, Server 2016+) · ser2net-linux-x64 (x86_64, glibc ≥ 2.28) — standalone, nothing else to install.
v2.7.0
ser2net v2.7.0 — connection lifecycle & optional login (#24)
Fixed
- Dead TCP clients no longer stay
ESTABLISHEDforever. A client that vanished without closing (power cut, cable pull, Wi-Fi/VPN/NAT drop) kept its slot on a quiet raw bridge — and withmax_connections = 1every reconnect was refused withBusy. Every TCP data socket (server, connect-out, Modbus gateway) now uses TCP keepalive, on by default: a dead peer is dropped in ≈ 90 s (60 s idle + 3 × 10 s probes; configurable per mapping), also while the device keeps sending (LinuxTCP_USER_TIMEOUT, when shorter than the kernel's ~15 min); pre-1709 Windows (e.g. Server 2016) is supported viaSIO_KEEPALIVE_VALS. Verified with real half-open connections on Linux and Windows in CI. - Viewers can no longer open the mapping edit form or the mappings export, which expose stored MQTT credentials (now operator+); a viewer API token gets the MQTT password redacted.
- 2.6.x configs with an unvalidated
idle_timeout_s(-1,"300") keep booting (Docker/headless re-saves the config on start); such values are normalised.
New
- Connect timeout for connect-out mappings (default 10 s, 0 = OS default) — covers the TCP and TLS handshake.
- Max connection time per mapping (0 = unlimited, e.g. 86400 = 24 h).
- Idle timeout now also applies to the Modbus gateway.
- Every disconnect is logged with its reason (closed by peer, peer stopped responding, idle timeout, max connection time, kicked, …).
- Optional web login: Settings → Web UI access — switch "Require login" off on trusted networks and choose the role visitors get (viewer / operator / admin). Signing in still works, the REST API still needs its token, open access applies only when the UI is reached by IP /
localhost/ its own host name (DNS-rebinding guard; behind a reverse proxy passX-Forwarded-Host), other cluster nodes still need a real login, and open consoles close when access is revoked. Login stays required by default. - All of the above in the mapping form, REST API and JSON import.
Upgrading from 2.6.x
No config migration and no new dependencies: config.json (mappings, users, API token, cluster, TLS) is read as-is; new settings take their defaults. Back up the data/ folder, replace the program, restart:
- Standalone binary: stop it/the service, replace
ser2net(.exe), keepdata/next to it, start. - Source install / systemd:
git pull(or unpack the new source) over the old one, thensystemctl restart ser2net. - Docker:
git pull && docker compose up -d --build— the/datavolume is kept. - LAN cluster: upgrade every node; mixed versions keep working meanwhile.
Behaviour changes to be aware of:
- TCP keepalive is on for every TCP mapping (that is the fix): a vanished peer is dropped after ≈ 90 s. To restore the old behaviour for a mapping, untick TCP keepalive (or
"tcp_keepalive": false); for faster detection lower idle/interval/count. - Connect-out gives up a hanging attempt after 10 s and retries (was the OS default: ~21 s Windows / ~2 min Linux). For very slow links raise Connect timeout, or set 0.
- Modbus gateway now honours Idle timeout — it was ignored there before; if a Modbus mapping has one set, masters that stay silent longer get disconnected.
- Linux: a client that stops reading for longer than idle + interval × count while the device keeps sending is disconnected (
TCP_USER_TIMEOUT). - Viewer role: no longer opens the mapping form or the export (403); a viewer API token sees the MQTT password as
********. - Log format: disconnect lines now end with
— <reason>, and the startup line shows the keepalive setting — adjust any log parsers. - Login is still required by default; open access only if an admin turns it on.
- Rolling back to 2.6.x is safe: it ignores the new keys (and drops them on its next save).
Türkçe özet
FIN/RST göndermeden kaybolan istemcilerin bağlantısı artık sonsuza dek ESTABLISHED kalmıyor: tüm TCP soketlerinde TCP keepalive varsayılan olarak açık (~90 sn'de temizlenir). Bunun yanında connect timeout, maksimum bağlantı süresi, Modbus gateway için idle timeout, kopma nedeni loglama ve isteğe bağlı web girişi (Ayarlar → Web UI access) geldi. Ayrıca viewer rolü artık MQTT parolası içeren düzenleme formunu ve dışa aktarmayı göremiyor.
Downloads: ser2net-windows-x64.exe · ser2net-linux-x64 (standalone, no Python needed).
v2.6.3
v2.6.3: RS-485 hardware auto-RTS in the mapping UI
v2.6.2
v2.6.2: review hardening — admin bind-IP validation, TLS e2e test, do…
v2.6.1
v2.6.1: cluster remote edit of a peer's mapping
v2.6.0
v2.6.0: cluster remote control + manual peers + per-node health
v2.5.0
v2.5.0: LAN cluster — auto-discovery + unified read-only fleet view
v2.4.0
v2.4.0: Modbus RTU<->TCP gateway, Modbus->MQTT, RBAC, LDAP/AD, standa…
v2.3.0 — REST API, theme, OIDC SSO
REST API (/api/v1) with role-scoped bearer tokens, light/dark theme toggle, and OIDC single sign-on (authorization-code flow). Standalone binaries begin at v2.4.0 (packaging landed after this milestone).