Skip to content

Releases

v3.1.1

Choose a tag to compare

@github-actions github-actions released this 14 Nov 18:29
Immutable release. Only release title and notes can be modified.
cac3d4b

A fix for the fleet view's mapping editor, a fully type-checked web layer, and a Chocolatey
package with a descriptive title and an icon.

Upgrading from 3.1.0: nothing has to change.

Fixed

  • Opening or saving a peer's mapping in the fleet view no longer fails with HTTP 500 when the
    peer answers with a mapping (or one of its sections) that is not a JSON object: the form says
    Could not load the peer's mapping., and nothing is sent to the peer (#121).

Changed

  • The web layer (ser2netweb.web) is fully type-annotated and checked by mypy in CI, for Linux
    and for Windows (#121).
  • The Chocolatey package is titled ser2netweb (serial-to-network bridge) and shows the
    application's icon (#109).

Full list: CHANGELOG.md.

Downloads

File
ser2netweb-linux-x64 Linux x86_64 executable (glibc ≥ 2.28)
ser2netweb-linux-arm64 Linux arm64 executable (glibc ≥ 2.28; Raspberry Pi 3/4/5 with a 64-bit OS)
ser2netweb-windows-x64.exe Windows x64 executable; --install-service runs it as a service
ser2netweb_3.1.1_amd64.deb package for Debian, Ubuntu and other .deb systems, x86_64
ser2netweb_3.1.1_arm64.deb package for Debian, Ubuntu and other .deb systems, arm64
ser2netweb-3.1.1-1.x86_64.rpm package for Fedora, RHEL, AlmaLinux and other .rpm systems, x86_64
ser2netweb-3.1.1-1.aarch64.rpm package for Fedora, RHEL, AlmaLinux and other .rpm systems, arm64
ser2netweb-install.sh installs a Linux executable as a systemd service, checked against SHA256SUMS
ser2netweb-standalone.service systemd unit for the Linux executables (data in /var/lib/ser2netweb)
ser2netweb-*.cdx.json CycloneDX SBOM of each executable (3 files)
ser2netweb-*.THIRD-PARTY-LICENSES.txt licence texts of the components inside each executable (3 files)
SHA256SUMS SHA-256 checksums of all of the above

The .rpm files attached here are not signed themselves; the copies in the package repository
are. SHA256SUMS and the build provenance cover both.

PyPI: pipx install ser2netweb, or pipx install "ser2netweb[all]" for MQTT, LDAP, OIDC and in-process certificates (pypi.org/project/ser2netweb, uploaded by trusted publishing with PyPI's attestations).

Docker image: ghcr.io/haliskilic/ser2netweb:3.1.1 (also 3.1 and latest), and its copy docker.io/haliskilic/ser2netweb, for linux/amd64, linux/arm64 and linux/arm/v7.

Also through: the signed APT/DNF/zypper repositories at https://haliskilic.github.io/ser2netweb/, Homebrew (brew install haliskilic/tap/ser2netweb), Scoop (scoop bucket add haliskilic https://github.com/haliskilic/scoop-bucket), the snap (sudo snap install ser2netweb), and winget and Chocolatey once their first submissions are through moderation.

Verify a download: sha256sum -c SHA256SUMS --ignore-missing, and the build provenance with gh attestation verify ser2netweb-linux-x64 -R haliskilic/ser2netweb (the image: gh attestation verify oci://ghcr.io/haliskilic/ser2netweb:3.1.1 -R haliskilic/ser2netweb). The Windows executable is not code-signed.

v3.1.0

Choose a tag to compare

@github-actions github-actions released this 14 Nov 11:31
Immutable release. Only release title and notes can be modified.
f2a7520

Device-server features from classic ser2net, MQTT 5 with Modbus pulses and safe values, trace
files and TLS files handled from the browser and the REST API, xterm.js 6 in the web console,
and signed RPM packages.

Upgrading from 3.0.x: nothing has to change; every new feature is off until it is turned on.
dnf / zypper users of the package repository: with this release every .rpm there is
signed, which changes each file once. If dnf or zypper says a package doesn't match what it
downloaded, run sudo dnf clean metadata (or add --refresh) or sudo zypper refresh. To have
each package's signature checked too, fetch ser2netweb.repo again (zypper: remove the
repository and add it again); the old file keeps working with the signed metadata checked.
Going back to 3.0.x: delete cert-notices.json from the data folder first; 3.0.x drops the
new settings on its next save (backups/ keeps the file).

Device server (#120)

  • Packing for raw TCP and UDP mappings: the device's output goes out as frames (a gap, a
    delimiter or a size), one datagram per frame over UDP.
  • One writer, read-only listeners (network.writer_client_ips): only those clients send to
    the device; the others only listen, and a listener can never push a writer out.
  • Open the serial port only while a client is connected (network.open_on_connect), so
    another program can use it in between.
  • Port pools (classic ser2net's rotators): one TCP port hands each client to the first free
    mapping of a pool.
  • Connect-out failover over network.remote_targets, with an optional return to the first.
  • The classic ser2net import carries UDP remote addresses, chardelay and rotators over.

MQTT and Modbus (#118)

  • MQTT 5 per mapping (3.1.1 stays the default): clean start, session and message expiry,
    the broker's reason codes in the log and the status.
  • Modbus pulses: a coil with pulse_ms switches itself off again.
  • Modbus safe values: a point with safe_value / safe_after_s is written to that value
    once the broker (or the Sparkplug primary host) has been away that long, once per outage.

Operations (#119)

  • Trace files in the REST API (list, download, delete; operator tokens) and timed
    recordings
    of 15 min, 1 h or 24 h that end by themselves.
  • TLS certificate about to expire notification and metric.
  • Upload TLS files in the browser (admins), checked before they are kept.
  • Clock-step watch: a clock set while ser2netweb runs is logged, audited, marked in traces
    and counted.

Web console (#102)

  • xterm.js 6.0.0 with @xterm/addon-fit 0.11.0; the console's scrollbar now fades when not
    in use.

Packaging (#117)

  • Signed RPM packages in the package repository, checked by dnf and zypper.
  • Packages built from the recipes in packaging/ know they are distribution packages
    (--about, data directory, install hints).
  • EPEL 10 builds, a conda-forge recipe, and the reverse-proxy examples of
    docs/REVERSE-PROXY.md run behind real nginx in CI.

Fixed

  • Windows: a save no longer fails with "Could not save config.json" (a 400 in the web UI)
    while config.json is open for a moment, e.g. during an antivirus scan.
  • A serial port at a baud rate without a termios constant (250000, 74880, …) got the input
    speed 38400 on musl systems (Alpine) (#117).
  • A mapping's TLS key that is a copy of the admin UI's is refused too; a !! note is written
    as text in a hex trace.

REST API 1.2.0; the snap is now released to every channel. Everything, with the upgrade notes
in full: CHANGELOG.md.

Assets

File
ser2netweb-linux-x64 Linux x86_64 executable (glibc ≥ 2.28)
ser2netweb-linux-arm64 Linux arm64 executable (glibc ≥ 2.28; Raspberry Pi 3/4/5 with a 64-bit OS)
ser2netweb-windows-x64.exe Windows x64 executable; --install-service runs it as a service
ser2netweb_3.1.0_amd64.deb package for Debian, Ubuntu and other .deb systems, x86_64
ser2netweb_3.1.0_arm64.deb package for Debian, Ubuntu and other .deb systems, arm64
ser2netweb-3.1.0-1.x86_64.rpm package for Fedora, RHEL, AlmaLinux and other .rpm systems, x86_64
ser2netweb-3.1.0-1.aarch64.rpm package for Fedora, RHEL, AlmaLinux and other .rpm systems, arm64
ser2netweb-install.sh installs a Linux executable as a systemd service, checked against SHA256SUMS
ser2netweb-standalone.service systemd unit for the Linux executables (data in /var/lib/ser2netweb)
ser2netweb-*.cdx.json CycloneDX SBOM of each executable (3 files)
ser2netweb-*.THIRD-PARTY-LICENSES.txt licence texts of the components inside each executable (3 files)
SHA256SUMS SHA-256 checksums of all of the above

The .rpm files attached here are not signed themselves; the copies in the package repository
are. SHA256SUMS and the build provenance cover both.

PyPI: pipx install ser2netweb, or pipx install "ser2netweb[all]" for MQTT, LDAP, OIDC and in-process certificates (pypi.org/project/ser2netweb, uploaded by trusted publishing with PyPI's attestations).

Docker image: ghcr.io/haliskilic/ser2netweb:3.1.0 (also 3.1 and latest), and its copy docker.io/haliskilic/ser2netweb, for linux/amd64, linux/arm64 and linux/arm/v7.

Also through: the signed APT/DNF/zypper repositories at https://haliskilic.github.io/ser2netweb/, Homebrew (brew install haliskilic/tap/ser2netweb), Scoop (scoop bucket add haliskilic https://github.com/haliskilic/scoop-bucket), winget, Chocolatey and the snap (sudo snap install ser2netweb).

Verify a download: sha256sum -c SHA256SUMS --ignore-missing, and the build provenance with gh attestation verify ser2netweb-linux-x64 -R haliskilic/ser2netweb (the image: gh attestation verify oci://ghcr.io/haliskilic/ser2netweb:3.1.0 -R haliskilic/ser2netweb). The Windows executable is not code-signed.

v3.0.1

Choose a tag to compare

@github-actions github-actions released this 13 Nov 21:17
Immutable release. Only release title and notes can be modified.
ed157aa

More ways to install ser2netweb, dependency ranges that distributions can meet, and fixes for
3.0.0. Upgrading from 3.0.0: nothing has to change, except for Docker users of the old
image name (below).

Fixed

  • SER2NETWEB_PORT without SER2NETWEB_BIND_IP was ignored. The port (also under its old
    name SER2NET_PORT) now applies on its own and keeps the bind IP config.json has;
    --healthcheck already read it that way and probed a port the server was not on. A port
    outside 1-65535 now stops the start with one line in this case too (#122).
  • Homebrew: data of 3.0.0 run by hand is found again. 3.0.0 took the formula's install for
    a pip install; while the user's data folder has a config.json and
    $(brew --prefix)/var/ser2netweb has none, it stays the default (#122).
  • A pyserial-asyncio-fast that is installed but fails to import is reported at start instead of
    being replaced silently by the built-in copy of its transport (#122).

Added

  • Signed APT, DNF and zypper repositories at https://haliskilic.github.io/ser2netweb/,
    updated with every release (docs/PACKAGES.md; key fingerprint
    B587 60E7 C0B0 515E 81D2 50F9 8164 D694 711B B799) (#109, #110).
  • Package managers: winget (haliskilic.ser2netweb), Scoop (bucket
    haliskilic/scoop-bucket), Chocolatey, Homebrew (brew install haliskilic/tap/ser2netweb),
    an AUR package ser2netweb-bin, a snap (USB serial adapters through
    sudo snap connect ser2netweb:raw-usb), and a Docker Hub mirror
    docker.io/haliskilic/ser2netweb. ser2netweb recognises these installs, keeps its data
    where an upgrade doesn't remove it, and --about names the kind (#109, #111, #113).
  • Recipes for distributions, each built and started in CI: Debian / Ubuntu, Fedora,
    openSUSE, Arch, Alpine, nixpkgs, Void, Gentoo, FreeBSD and MacPorts (packaging/,
    docs/PACKAGING.md) (#109, #114, #116).
  • A built-in copy of pyserial-asyncio-fast's transport, used when that package is not
    installed, and support for Starlette 0.46 to 1.5 (#112).

Changed

  • Docker: the image name ghcr.io/haliskilic/ser2net no longer exists. Since 2026-11-13
    every pull of it fails and the 2.x images are no longer on GHCR; the image is
    ghcr.io/haliskilic/ser2netweb (also on Docker Hub). Change image: in your compose file
    or docker run command; the data volume is used as it is (#115, #122).
  • Dependency ranges of the Python package are wider: the lowest versions that work
    (Debian 13, RHEL 10, Ubuntu 26.04), without upper limits. The executables, the Docker image
    and requirements.txt keep the tested pins; CI also runs the suite on the lowest and, weekly,
    on the newest versions (#112).
  • Release pipeline: a release starts the channel workflows itself, and one that can't be
    started no longer keeps the others from starting (#110, #122).

Everything, with the upgrade notes in full: CHANGELOG.md.

Assets

File
ser2netweb-linux-x64 Linux x86_64 executable (glibc ≥ 2.28)
ser2netweb-linux-arm64 Linux arm64 executable (glibc ≥ 2.28; Raspberry Pi 3/4/5 with a 64-bit OS)
ser2netweb-windows-x64.exe Windows x64 executable; --install-service runs it as a service
ser2netweb_3.0.1_amd64.deb package for Debian, Ubuntu and other .deb systems, x86_64
ser2netweb_3.0.1_arm64.deb package for Debian, Ubuntu and other .deb systems, arm64
ser2netweb-3.0.1-1.x86_64.rpm package for Fedora, RHEL, AlmaLinux and other .rpm systems, x86_64
ser2netweb-3.0.1-1.aarch64.rpm package for Fedora, RHEL, AlmaLinux and other .rpm systems, arm64
ser2netweb-install.sh installs a Linux executable as a systemd service, checked against SHA256SUMS; moves a 2.9.x install over
ser2netweb-standalone.service systemd unit for the Linux executables (data in /var/lib/ser2netweb)
ser2netweb-*.cdx.json CycloneDX SBOM of each executable (3 files)
ser2netweb-*.THIRD-PARTY-LICENSES.txt licence texts of the components inside each executable (3 files)
SHA256SUMS SHA-256 checksums of all of the above

PyPI: pipx install ser2netweb, or pipx install "ser2netweb[all]" for MQTT, LDAP, OIDC and in-process certificates (pypi.org/project/ser2netweb, uploaded by trusted publishing with PyPI's attestations).

Docker image: ghcr.io/haliskilic/ser2netweb:3.0.1 (also 3.0 and latest), and its copy docker.io/haliskilic/ser2netweb, for linux/amd64, linux/arm64 and linux/arm/v7.

Also through: the signed APT/DNF/zypper repositories at https://haliskilic.github.io/ser2netweb/, Homebrew (brew install haliskilic/tap/ser2netweb), Scoop (scoop bucket add haliskilic https://github.com/haliskilic/scoop-bucket), winget and the snap (edge channel).

Verify a download: sha256sum -c SHA256SUMS --ignore-missing, and the build provenance with gh attestation verify ser2netweb-linux-x64 -R haliskilic/ser2netweb (the image: gh attestation verify oci://ghcr.io/haliskilic/ser2netweb:3.0.1 -R haliskilic/ser2netweb). The Windows executable is not code-signed.

v3.0.0

Choose a tag to compare

@github-actions github-actions released this 13 Nov 04:12
Immutable release. Only release title and notes can be modified.
33497b5

ser2net is now ser2netweb. 3.0.0 renames the project to tell it apart from Corey Minyard's ser2net, the C program that Linux distributions package under that name: ser2netweb is an independent project, not affiliated with or derived from it. Apart from the names, 3.0.0 works as 2.9.0 did, and 2.9.x and 3.0 nodes of a LAN cluster work together. Read Before you upgrade for what has a new name.

  • .deb and .rpm packages for x86_64 and arm64: sudo apt install ./ser2netweb_3.0.0_amd64.deb or sudo dnf install ./ser2netweb-3.0.0-1.x86_64.rpm, then sudo systemctl enable --now ser2netweb (Linux packages).
  • A PyPI package: pipx install ser2netweb on any OS and CPU with Python 3.10 or newer (pipx / pip).
  • New names for the release files, the systemd units, the Windows service and the Docker image, with a move-over from 2.9.x for each; the Docker image is published under both its old and its new path.

Before you upgrade

config.json and the data folder are used as they are. Check what applies to you:

  • Release files have new names (ser2netweb-linux-x64, ser2netweb-windows-x64.exe, ser2netweb-install.sh, …), and there are no files under the old names: a script that downloads ser2net-linux-x64 must change.
  • Environment variables have the prefix SER2NETWEB_; the SER2NET_* names still work. When both are set, the SER2NETWEB_* one wins, also when it is empty (Environment variables).
  • --version prints ser2netweb 3.0.0, and webhooks, OIDC and cluster peer requests send User-Agent: ser2netweb/3.0.0: scripts, receivers and filters that match ser2net must accept the new name.
  • Python code that imports app.* must import ser2netweb.*.
  • Once moved over, the systemd unit is ser2netweb.service and the Windows service and its Event Log source are ser2netweb: monitoring that checks the old names must follow.
  • Unchanged: the cluster protocol, the Prometheus metric names ser2net_*, the MQTT and Sparkplug B defaults, the config.json keys, the REST API paths, the cookie names (nobody is signed out) and the default e-mail sender address ser2net@<host>.

How to upgrade

  • Docker: nothing has to change: ghcr.io/haliskilic/ser2net gets 3.0.0 as the very same image. To switch to the new path and the new docker-compose.yml (service and container ser2netweb, the volume ser2net-data kept): docker compose pull && docker compose up -d --remove-orphans (Upgrading from 2.9.x).
  • Standalone binary installed with ser2net-install.sh: put ser2netweb-linux-x64 (or -arm64), ser2netweb-standalone.service, ser2netweb-install.sh and SHA256SUMS in one folder and run sudo sh ser2netweb-install.sh (add --remove-old-user to drop the user ser2net). It moves /var/lib/ser2net to /var/lib/ser2netweb, keeps the address and your drop-ins, removes 2.9.x's unit and binary once ser2netweb.service answers, and never touches another ser2net.service, such as the classic daemon's.
  • Standalone binary run without the script: replace it with ser2netweb-linux-x64 (or -arm64) and restart it.
  • Source checkout under systemd: sudo git -C /opt/ser2net pull && sudo systemctl restart ser2net keeps it on the old names (ser2net.py starts 3.0.0). The commands to move it to /opt/ser2netweb and ser2netweb.service, and those for ser2net@ instances, are in the CHANGELOG.
  • Windows service: from an elevated prompt run ser2netweb-windows-x64.exe --install-service (for named services first --install-service --service-name NAME for each). It takes over 2.x's ser2net service, moves its data from C:\ProgramData\ser2net\ to C:\ProgramData\ser2netweb\ when it was in that default place, and puts everything back if the new service doesn't start. Then re-add the firewall rule for C:\Program Files\ser2netweb\ser2netweb.exe and delete the old ser2net rule (commands in the CHANGELOG).
  • New installs: the .deb / .rpm package, pipx install ser2netweb, the executables or Docker. The packages don't start the service by themselves and don't move a 2.9.x install.

Everything, with the upgrade commands in full: CHANGELOG.md.

Assets

File
ser2netweb-linux-x64 Linux x86_64 executable (glibc ≥ 2.28)
ser2netweb-linux-arm64 Linux arm64 executable (glibc ≥ 2.28; Raspberry Pi 3/4/5 with a 64-bit OS)
ser2netweb-windows-x64.exe Windows x64 executable; --install-service runs it as a service
ser2netweb_3.0.0_amd64.deb package for Debian, Ubuntu and other .deb systems, x86_64
ser2netweb_3.0.0_arm64.deb package for Debian, Ubuntu and other .deb systems, arm64
ser2netweb-3.0.0-1.x86_64.rpm package for Fedora, RHEL, AlmaLinux and other .rpm systems, x86_64
ser2netweb-3.0.0-1.aarch64.rpm package for Fedora, RHEL, AlmaLinux and other .rpm systems, arm64
ser2netweb-install.sh installs a Linux executable as a systemd service, checked against SHA256SUMS; moves a 2.9.x install over
ser2netweb-standalone.service systemd unit for the Linux executables (data in /var/lib/ser2netweb)
ser2netweb-*.cdx.json CycloneDX SBOM of each executable (3 files)
ser2netweb-*.THIRD-PARTY-LICENSES.txt licence texts of the components inside each executable (3 files)
SHA256SUMS SHA-256 checksums of all of the above

Docker image: ghcr.io/haliskilic/ser2netweb:3.0.0 (also 3.0 and latest), and the same image as ghcr.io/haliskilic/ser2net:3.0.0 (3.0, latest); linux/amd64, linux/arm64 and linux/arm/v7. 3.0 and latest are rebuilt weekly when the Debian/Python base image changes; 3.0.0 stays the image this release published.

PyPI: pipx install ser2netweb, or pipx install "ser2netweb[all]" for MQTT, LDAP, OIDC and in-process certificates (pypi.org/project/ser2netweb, uploaded by trusted publishing with PyPI's attestations).

Verify a download: sha256sum -c SHA256SUMS --ignore-missing, and the build provenance with gh attestation verify ser2netweb-linux-x64 -R haliskilic/ser2netweb, the packages likewise (gh attestation verify ser2netweb_3.0.0_amd64.deb -R haliskilic/ser2netweb); add --signer-workflow haliskilic/ser2netweb/.github/workflows/release.yml to require the release workflow, and each executable also has an SBOM attestation. The image: gh attestation verify oci://ghcr.io/haliskilic/ser2netweb:3.0.0 -R haliskilic/ser2netweb, which also holds for ghcr.io/haliskilic/ser2net:3.0.0; a weekly rebuild of 3.0 / latest is attested by image-refresh.yml. Files of 2.x releases were attested under the old name: verify them with -R haliskilic/ser2net. The Windows executable is not code-signed yet, so SmartScreen may warn; check it the same way (docs/WINDOWS.md).

v2.9.0

Choose a tag to compare

@github-actions github-actions released this 12 Nov 22:04
cd6789d

ser2net 2.9.0 fixes the remaining problems found in 2.8.0 (issues #48–#90) and adds the features that came with them. Several fixes change behaviour on purpose: read Before you upgrade first.

  • Two-factor sign-in (TOTP) and named REST API tokens with their own role and expiry; PATCH, a bulk import and token-protected metrics in the REST API.
  • config.json reloads without a restart (systemctl reload ser2net, ser2net --reload), and so do admin TLS certificates.
  • Reverse proxies (trusted proxies, a public URL, serving under a path) and several instances on one machine.
  • Modbus RTU replies framed reliably on USB adapters and Windows; 64-bit, float64, string and bit points, word order, block reads, a unit map, unit health with Sparkplug B DDEATH; MQTT with a private CA and client certificates.
  • The right adapter among identical USB adapters, listeners for IPv4 and IPv6 at once, telnet BREAK, UDP targets; retention and privacy controls; an event loop watchdog.
  • A Docker image for 32-bit ARM, ser2net-install.sh to run a Linux executable as a systemd service, and new guides: Modbus and MQTT, moving from the classic ser2net, single sign-on, Linux serial ports.

Before you upgrade

config.json and data/ are used as they are, and the start-up log notes each stored value that 2.9.0 reads differently. Check what applies to you (coming from 2.8.0 or older, read the 2.8.1 notes too):

  • Reverse proxy on the same machine: list it as 127.0.0.1 under Settings → Reverse proxy → Trusted proxies, or every user shows as 127.0.0.1 and all share one sign-in limit. A plain-HTTP proxy that rewrites Host must pass X-Forwarded-Host, or forms get 403. See docs/REVERSE-PROXY.md.
  • Stricter checks when a mapping is saved (also on import and for the mappings a reload changes): two enabled mappings sharing MQTT command topics (/set, /tx), a client ID or a Sparkplug B edge node, MQTT wildcards in a plain base topic, one serial port under two spellings, the admin UI's port, TLS files that don't load (a disabled mapping's too), Modbus point values of the wrong type and text for protective or only-true switches are refused, and a disabled mapping that would clash on MQTT can't be started. Stored mappings still load, with a note at start-up, but their next edit must fix them.
  • Text values in config.json are read as their setting's type: numeric text is converted, "enabled": "false" leaves a mapping stopped, "writable": "false" makes a point read-only. Switches that turn something on only for JSON true (MQTT tx_enabled, poll_with_clients, proxy_hsts, dual_stack, …) read text as off; protective ones (read_only, tls, require_login, mask_personal_data, MQTT tls_check_hostname, …) read it as on. An allow-list with no usable entry admits nobody instead of everyone. The start-up log notes each case.
  • Modbus gateway: a reply must match its request, so slaves that miscount, don't echo FC5/FC6 exactly or answer reads of unit 0 get exception 0x0B; a broadcast write to unit 0 is answered with its echo, and a read of unit 0 gets 0x0B at once.
  • Start no longer restarts a running mapping: scripts must use restart.
  • A mapping listens before it opens its device, so a taken port fails without touching the device; a client can connect a moment earlier than before, and what it sends before the device is open is dropped.
  • A telnet BREAK now reaches the device (0.25 s; not on read-only mappings).
  • TLS mappings: connect-out TLS presents its configured certificate and key; an encrypted key needs its key password set, as it no longer asks at the console.
  • SIGHUP reloads config.json instead of stopping ser2net (a reload is checked like an edit); kick_old_user no longer evicts priority clients.
  • Classic ser2net imports go through the preview only; merging a file again keeps what was set up here; ipv6n4 accepters listen on IPv4 and IPv6; port locking comes along.
  • Sign-in: 10 failures in 15 minutes give that user name HTTP 429 until they expire. Accounts get stronger password hashes at their next sign-in, which 2.8.1 and older can't read: after going back to 2.8.1, set a new password there (ser2net --set-password NAME; on 2.8.0 and older, restore a config.json from backups/ made before the upgrade).
  • New defaults: the event loop watchdog (90 s, then data/hang.log and exit code 70; SER2NET_LOOP_WATCHDOG=0 turns it off); traces pause below 256 MB free; new log and trace files are owner-only; :: takes IPv6 only (All interfaces (IPv4 + IPv6) takes both); the first start deletes trace files of mappings that no longer exist.
  • systemd: copy the new systemd/ser2net.service to /etc/systemd/system/ and run systemctl daemon-reload; systemctl reload now works with all three units (ser2net@.service and ser2net-standalone.service are new). Instances of ser2net@.service share one lib/: run sudo -u ser2net python3 /opt/ser2net/bootstrap.py after each upgrade.
  • Scripts: Settings forms answer 303 / 400 (follow redirects with the cookie jar to read a new token), and a save that switches admin TLS on or off answers 200 with the page; a dashboard bulk action that can't change a mapping answers 400 with the reasons, after doing the others; a page without a session redirects to /login?next=<page>; REST errors are JSON (400 validation, 500 save_failed); log times carry a UTC offset and IPv6 peers are bracketed; cookies on ports other than 8080 and over HTTPS have new names.
  • MQTT / Sparkplug B consumers: .../set/result comes at QoS 1 with new error texts; Sparkplug B sends a DDEATH for a unit that stops answering and bdSeq as Int64.
  • LAN cluster: mixed versions work, and an older node's edit form offers only the settings it keeps, but upgrade every node (Upgrading a cluster).
  • Windows: serial writes are paced to the line; if a virtual COM driver misbehaves, SER2NET_WINDOWS_SERIAL=pyserial restores the old write path.
  • Going back to 2.8.x: copy data/ first; older versions drop named API tokens, two-factor sign-in, dual_stack and the new TLS checks (README → Going back to an older version); put back that version's systemd unit, as 2.9's ExecReload would end it, and remove notify.conf.

How to upgrade

  • Standalone executable (Linux): replace the file and restart ser2net, or install or upgrade it as a systemd service with ser2net-install.sh (run it again to upgrade; --uninstall keeps the data).
  • Windows service: run the new ser2net-windows-x64.exe --install-service from an elevated prompt. It upgrades the service in place, keeping its data directory, and now reports an error if the service doesn't start.
  • Docker: docker pull ghcr.io/haliskilic/ser2net:2.9.0 and recreate the container; add init: true and stop_grace_period: 30s to your compose file, as the shipped one has.
  • Source install: update the files and restart; the first start refreshes lib/ from vendor/wheels by itself, offline (all.log says what to run if it can't). Under systemd, copy the new unit first; for ser2net@.service instances, run bootstrap.py as above.

Everything, with the upgrade notes in full: CHANGELOG.md.

Assets

File
ser2net-linux-x64 Linux x86_64 executable (glibc ≥ 2.28)
ser2net-linux-arm64 Linux arm64 executable (glibc ≥ 2.28; Raspberry Pi 3/4/5 with a 64-bit OS)
ser2net-windows-x64.exe Windows x64 executable; --install-service runs it as a service
ser2net-install.sh installs a Linux executable as a systemd service, checked against SHA256SUMS
ser2net-standalone.service systemd unit for the Linux executables (data in /var/lib/ser2net)
*.cdx.json CycloneDX SBOM of each executable
*.THIRD-PARTY-LICENSES.txt license texts of the components inside each executable
SHA256SUMS SHA-256 checksums of all of the above

Docker image: ghcr.io/haliskilic/ser2net:2.9.0 (also 2.9 and latest), linux/amd64, linux/arm64 and linux/arm/v7. 2.9 and latest are rebuilt weekly when the Debian/Python base image changes; 2.9.0 stays the image this release published.

Verify a download: sha256sum -c SHA256SUMS --ignore-missing, and the build provenance with gh attestation verify ser2net-linux-x64 -R haliskilic/ser2net (add --signer-workflow haliskilic/ser2net/.github/workflows/release.yml to require the release workflow; each executable also has an SBOM attestation; the image: gh attestation verify oci://ghcr.io/haliskilic/ser2net:2.9.0 -R haliskilic/ser2net, while a weekly rebuild of 2.9 / latest is attested by image-refresh.yml). The Windows executable is not code-signed yet, so SmartScreen may warn; check it the same way (docs/WINDOWS.md).

v2.8.1

Choose a tag to compare

@github-actions github-actions released this 11 Nov 22:54
98253f5

A security release. 2.8.1 fixes 16 security issues in 2.8.0 and earlier, together with the bugs found alongside them. Upgrade every installation, and every node of a LAN cluster. Several fixes change behaviour on purpose: read Before you upgrade first.

Security advisories

Advisory Severity Affected versions Summary
GHSA-47f5-rwq9-8c9p High ≤ 2.8.0 Unvalidated mapping ids and serial-port URLs allow file writes outside the data directory
GHSA-gxrq-f87q-xx96 High 2.3.0–2.8.0 LDAP/OIDC group-to-role mapping matches substrings and can grant unintended roles
GHSA-9qqv-mrqj-4fpx High ≤ 2.8.0 Unauthenticated requests can exhaust memory and push all other records out of the audit log
GHSA-g2wg-gpfm-g9fp High 2.3.0–2.8.0 The Read-only option is not enforced for Modbus gateway mappings
GHSA-jm3r-8jxr-4wh4 Medium 2.8.0 MQTT commands can write beyond the addressed Modbus point and bypass the Read-only option
GHSA-p65v-hqq3-cjr9 High 2.5.0–2.8.0 Fleet-view proxies can send the cluster key to a host that is not a cluster node
GHSA-5mrw-593x-q839 High 2.3.0–2.8.0 LDAPS and StartTLS connections do not verify the directory server's certificate
GHSA-p2cr-p4jh-x4rc Medium ≤ 2.8.0 First-run setup has no host check; sessions survive sign-out, account re-creation and restore
GHSA-7f6v-672v-7mjm Medium 2.3.0–2.8.0 LDAP/OIDC sign-ins can take over a same-named local or other-method account; OIDC gaps
GHSA-xcxp-4hgp-m666 Medium 2.8.0 Classic ser2net import enables connections without their access protections
GHSA-w2p8-66v2-rgr7 High 2.5.0–2.8.0 Cluster key is sent in clear on peer requests and can be redirected by replayed beacons
GHSA-wv6x-867g-475q High 2.8.0 Windows service runs as LocalSystem from a location standard users may be able to modify
GHSA-cjp3-9g2v-4w69 Medium ≤ 2.8.0 Unauthenticated connections can use up file descriptors or stop the process on Windows
GHSA-3wh8-pjmf-qfh5 Medium 2.3.0–2.8.0 Viewers can see data sent to devices, including typed passwords, and download trace files
GHSA-jj9j-m939-wmmm Medium ≤ 2.8.0 RFC 2217 clients can make ser2net buffer subnegotiation data without limit
GHSA-4wgx-6v57-4r26 Medium 2.0–2.8.0 UDP mappings buffer serial writes without limit and let any allowed source take over output

2.8.0's note "Traces can no longer write outside the data directory" was incomplete: the mapping id, which is part of the trace and log file names, was not validated. 2.8.1 validates it everywhere it enters (GHSA-47f5-rwq9-8c9p).

Before you upgrade

config.json and data/ are used as they are. Check what applies to you:

  • LAN cluster: upgrade every node. Legacy authentication (on by default) keeps older nodes working meanwhile; once all run 2.8.1, turn it off on each node and change the cluster key, which older versions sent in clear text.
  • LDAPS / StartTLS now check the directory's certificate. If this system doesn't trust its CA (private, AD CS or self-signed, typical on Linux and in Docker), set Settings → LDAP → CA certificate file (ldap.ca_file), or LDAP sign-in stops.
  • LDAP / OIDC group settings match whole group names only; a sign-in under a local account's name is refused, and an LDAP and an OIDC account can no longer share a name (the method used last keeps it). An OIDC sign-in in progress during the upgrade fails once. Locked out? ser2net --set-password NAME creates a local admin.
  • Viewers no longer see what is sent to devices or download traces; give the operator role to those who need them.
  • Read-only Modbus mappings refuse writes from masters and from MQTT / Sparkplug; retained MQTT /set commands are no longer replayed (there is an opt-in to keep that).
  • Backup restore keeps the current accounts, passwords, API token and cluster key unless you choose otherwise.
  • First-run setup through a reverse proxy or another host name asks for the code in data/setup-code.txt.
  • Request bodies over 2 MB get HTTP 413 (imports: 16 MB).
  • One ser2net per data directory: a second instance on the same data directory refuses to start.
  • Monitoring: bytes_in / bytes_out count at the device now (a one-time level change); some sign-in log lines are worded differently.
  • Classic ser2net imports done with 2.8.0: re-check those mappings' TLS, allowed client IPs and direction.
  • Admin UI connection limits: a connection that sends no complete request within 10 s (or then sends its body slower than about 1 KiB/s, or takes nothing of the response) is closed, and at most 64 connections per address and 256 in all are taken (optional admin_ui.request_timeout_s, max_connections_per_ip, max_connections in config.json, 0 = no limit). Behind a reverse proxy everyone shares one address: raise the per-address limit there.
  • TLS mappings: a handshake must finish within 15 s; hosts not in the allow-list are closed before it; past 32 at once from one address, further connections wait for a slot.
  • Windows keeps the selector event loop, which now refuses new connections near its 512-socket limit instead of stopping; SER2NET_WINDOWS_LOOP=proactor is an opt-in alternative without that limit (not yet soak-tested with serial devices).

How to upgrade

  • Standalone executable (Linux): replace the file and restart ser2net.
  • Windows service: run the new ser2net-windows-x64.exe --install-service from an elevated prompt. It copies itself to C:\Program Files\ser2net\ and upgrades the service in place, keeping its data directory.
  • Docker: docker pull ghcr.io/haliskilic/ser2net:2.8.1 and recreate the container; afterwards check docker logs for WARNING: config.json: lines (settings the container now leaves off instead of restart-looping).
  • Source install: update the files, then, with ser2net stopped, refresh the bundled packages in the install folder: python3 -m pip install --target lib --upgrade --no-index --find-links vendor/wheels -r requirements.txt (an in-place update keeps the old ones in lib/).

Also in this release

  • A serial device that stops taking data (CTS low, XOFF, a virtual port nobody reads) no longer freezes ser2net or hangs a mapping's stop.
  • The Modbus gateway reopens a lost serial port instead of answering 0x0B until restarted.
  • The standalone executables show the Turkish UI again and keep their web UI when temp cleaners run.
  • A rejected setting no longer restart-loops Docker or blocks every save; bind-mounted /data folders from older images and serial devices on hosts where dialout isn't GID 20 work.
  • Fleet view: remote actions work for peers behind NAT or Docker, by host name or IPv6; non-ASCII cluster keys work.
  • Active Directory direct bind with user@domain or DOMAIN\user reads groups; OIDC tolerates small clock differences.
  • RFC 2217 clients survive malformed values and a reopened serial port; serial ports and MQTT keep working with more than 1024 files open, and the open-file limit is raised at start.
  • Account recovery from the command line (--set-password, --sign-out-all), session controls, cluster key generation and planned key changes, a fixed UDP reply address.
  • Dependencies: click 8.5.1, paho-mqtt 2.2.0, authlib 1.9.5.

Everything, with the upgrade notes in full: CHANGELOG.md.

Assets

File
ser2net-linux-x64 Linux x86_64 executable (glibc ≥ 2.28)
ser2net-linux-arm64 Linux arm64 executable (glibc ≥ 2.28; Raspberry Pi 3/4/5 with a 64-bit OS)
ser2net-windows-x64.exe Windows x64 executable; --install-service runs it as a service
*.cdx.json CycloneDX SBOM of each executable
*.THIRD-PARTY-LICENSES.txt license texts of the components inside each executable
SHA256SUMS SHA-256 checksums of all of the above

Docker image: ghcr.io/haliskilic/ser2net:2.8.1 (also 2.8 and latest), linux/amd64 and linux/arm64.

Verify a download: sha256sum -c SHA256SUMS --ignore-missing, and the build provenance with gh attestation verify ser2net-linux-x64 -R haliskilic/ser2net (each executable also has an SBOM attestation; the image: gh attestation verify oci://ghcr.io/haliskilic/ser2net:2.8.1 -R haliskilic/ser2net). The Windows executable is not code-signed yet, so SmartScreen may warn; check it the same way (docs/WINDOWS.md).

v2.8.0

Choose a tag to compare

@github-actions github-actions released this 04 Nov 08:31
030c6cd

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.json in data/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 /data volume 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 (also 2.8 and latest), for amd64 + arm64. docker-compose.yml uses 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:
  • 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-id names, and they can be selected.
    • The kernel's placeholder ttyS ports without hardware are hidden.
  • 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": true take 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.
  • 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 carry seq.
    • Points are written through DCMD; NCMD triggers a rebirth.
    • No protobuf dependency.
  • Import from the classic ser2net: ser2net.yaml (4.x) and ser2net.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-name allows several instances.
  • 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 main is 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.conf iç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.json ve data/ olduğu gibi kullanılıyor; ilk değişiklikte eski config data/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

Choose a tag to compare

@github-actions github-actions released this 03 Nov 19:56
20ebbe7

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.
  • 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 openssl program; before, it never worked on Windows. The certificate is now made in-process with the bundled cryptography, 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_FILE to override; the startup log names the bundle in use.
  • Windows hardening: icacls (data-folder permissions) is run by its full System32 path, so an icacls.exe planted 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, no openssl): 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 /tmp is mounted noexec, point TMPDIR at 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 openssl gerektirmiyor.
  • 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

Choose a tag to compare

@github-actions github-actions released this 02 Nov 23:21
f19154f

ser2net v2.7.0 — connection lifecycle & optional login (#24)

Fixed

  • Dead TCP clients no longer stay ESTABLISHED forever. A client that vanished without closing (power cut, cable pull, Wi-Fi/VPN/NAT drop) kept its slot on a quiet raw bridge — and with max_connections = 1 every reconnect was refused with Busy. 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 (Linux TCP_USER_TIMEOUT, when shorter than the kernel's ~15 min); pre-1709 Windows (e.g. Server 2016) is supported via SIO_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 pass X-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), keep data/ next to it, start.
  • Source install / systemd: git pull (or unpack the new source) over the old one, then systemctl restart ser2net.
  • Docker: git pull && docker compose up -d --build — the /data volume 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

Choose a tag to compare

@github-actions github-actions released this 11 Jun 22:00
v2.6.3: RS-485 hardware auto-RTS in the mapping UI