Release notes — Version 2.1
What changed in each version 2.1 release, newest first, as published with the release.
v2.1.4.1
Released 2026-09-19
- The watchdog no longer writes a false error line into the system journal on every single run. Until now it produced around 900 of them a day, and they were the only thing a search for "error" or "failed" in that journal would find.
- Two places were building a shell pipe whose reader can stop early - one counting silent minutes, one reading the process list. The writer then got a broken pipe and said so, once a minute, although the value it produced was always correct.
- Nothing about what the watchdog reports has changed; only the noise is gone. Measured after the fix: five runs, zero error lines, against 913 on the same machine earlier the same day.
v2.1.4
Released 2026-09-19
- The watchdog no longer invents the numbers it alarms on. Where the software itself already works with a limit, the watchdog now reads that limit instead of carrying its own.
- Concurrent calls: the alarm used to fire at 500 and 1500 channels, two numbers with no relation to anything. It now takes the ceiling from your licence, warns at 80% and reports critical at 95% of it, and counts calls rather than channels - the same figure the licence checks against.
- If your licence sets no channel limit you can name your own ceiling under Settings > Notifications, because only you know what your hardware carries. Leave it at zero and the alarm stays silent: there is then nothing it could measure against.
- Disk space: measured in free gigabytes against the limit the software already mails about, instead of percent used.
- Licence check overdue: derived from the grace period the licence package works with, instead of two hand-written hour counts, one of which was never used.
- Firewall exemptions: the two list checks now compare against the same column the firewall job builds those lists from. A device behind NAT would previously have produced a permanent false alarm.
- The delivery log shows what was reported, not only that something was reported: every entry now carries its message title and, behind a click, the full text.
- Single quotes in a log entry are kept instead of being silently deleted.
- CID pools: a pool with a fallback pool no longer raises a critical alarm when it runs empty, a pool with no numbers at all is reported again instead of being filtered out, and two pools sharing a name are no longer merged into one alarm.
- A new automated release check keeps the watchdog tied to those product numbers, and says in plain words what it cannot check.
- Seven notification texts that were still German are now English.
v2.1.3.2
Released 2026-09-19
- CID pool alarm now uses the same number the routing engine uses: usable numbers divided by total, counted exactly like poolUsageFresh().
- A pool is only reported when it falls clearly below its own switch threshold (device_number_pools.switch_below_pct minus 10 points, 20% by default) - a pool that merely makes the rotation switch is the safety net working, not an incident.
- Critical is now reserved for a pool with zero usable numbers, the one state that really makes calls fail with cause 900.
- Quarantined, retired and manually blocked numbers now count as unusable, as they always did for the engine.
- The alarm no longer reads call_attempts: measured at a customer it went from 115-119 ms to 8.6 ms.
v2.1.3.1
Released 2026-09-19
- The last two watchdog messages that were still in German are now English: the overload warning and the one about Asterisk not being able to create channels. Every one of the 74 alert titles is English now.
- The channel message also says what it usually means: a dial attempt that found no route, after which the routing engine moves on to the next provider. A handful per minute is the failover working, not an outage.
v2.1.3
Released 2026-09-19
- The notification settings page now tells the truth. Until this release the values it showed were not the values the system actually used - for 14 of 36 watchdog events they differed. The page promised 2 messages a day for CID pool warnings and you received 3, measured on four days in a row.
- The six doctor switches finally work. Quiet hours, daily cap, priority and on/off now apply to voiplix-doctor as well - until now it ignored all of them. The doctor also writes to the delivery log for the first time, so you can see whether its messages arrived.
- An all-clear no longer eats the alarm's daily budget. On 18 September the channel alarm sent you five all-clears and only two of its three real alarms; the other three were silently capped. All-clears are now counted separately.
- An all-clear is only sent for an alarm you actually received. 12 of 22 all-clears were for alarms that never reached you - including pools you were never told had run empty.
- Every CID pool now has its own daily cap. All 32 pools shared a single cap of three messages, so once one pool had used it up the others stayed silent until midnight. Four pools ran empty without you hearing about it.
- CID pool warnings are measured in the same window the rotation itself uses. A pool reported as 85 percent used was 39 percent used, with not a single blocked number - and the urgent alarms arrived at 00:01, 01:01 and 02:02, four hours after the last call. Replaying 18 September, 34 alarm lines become 3.
- An all-clear no longer resets the repeat timer, so an alarm and its all-clear can no longer ping-pong every few minutes.
- Six settings that never did anything now have a sender: update available, update installed, update failed, certificate expiring, web memory high, and provider registration lost. You were not being told about failed updates or expiring certificates at all.
- Security: the background service no longer inherits the web process environment on update, and the PM2 state file is no longer readable by other services on the machine.
- Three new build gates: the event catalogue is now counted against the scripts that send in both directions, the two watchdog lists are kept identical, and SQL comments inside shell scripts are checked for quoting that would silently execute them.
v2.1.2.4
Released 2026-09-18
- A new server could not be installed at all. This release fixes that.
- Measured on a freshly set up machine: the installer stopped in phase 10 of 16 with "The database backup came out incomplete, so the update was stopped before anything changed." The content check introduced in v2.1.2 requires the tables calls, devices and users to appear in the backup, and on a brand new empty database they do not exist yet.
- The check itself was right and stays exactly as it is. It is simply no longer applied to data that does not exist yet: if no migration has ever run on this database there is nothing to lose, the backup is skipped, and the installation continues.
- Also fixed, in install.sh: the installer died silently when started detached without an email address for the certificate. Under "set -e" a read that hits end-of-file ends the whole script, and the log stopped mid-sentence at the prompt. All three prompts now let the installer's own error message do the talking.
v2.1.2.3
Released 2026-09-17
- The technical log now survives the reboot in full.
- Measured on the test server: the file the update points support to carried 15 lines, the station markers and nothing else. Everything that carries the why (disk figures, "database: reachable", "Cleared.", the note about copies that could not be removed, the error output of prisma and pnpm) went to /tmp/voiplix-update.log, and the automatic reboot wipes /tmp. At a customer that is the normal case, because auto_reboot_after_update is 1 there.
- Every line now goes to both files, each with its own timestamp, stderr included.
- The update page reads the surviving file when /tmp is empty. After a reboot, "Show technical log" used to show nothing at all.
v2.1.2.2
Released 2026-09-17
- The way out of a stuck database change now works where it is actually needed.
- Measured on the test server: the pre-flight runs in the freshly unpacked tree, which has no node_modules yet, because the dependencies are installed one station later. "npx prisma migrate resolve" spent 19 seconds trying to fetch prisma over the network and then failed. The single thing a customer without SSH needed in order to get out of a stuck migration was the single thing that could not run there.
- What "migrate resolve --rolled-back" does is one UPDATE on one column. The update now does it itself, without a tool chain.
- It is accepted by state, not by exit code: if anything is still stuck afterwards, the update still stops and says so.
v2.1.2.1
Released 2026-09-17
- The update no longer leaves its own environment behind in the running services.
- Measured on the test server: "pm2 restart --update-env" copies the update script's environment into voiplix-web and voiplix-background, and "pm2 save" keeps it across the reboot. The background service still carried VOIPLIX_HEALTH_PORT, VOIPLIX_RUN_ID, the expected checksum of an old release, and a pointer to a file under /tmp that no longer existed.
- The part that matters: an exception you confirm once (skip the checksum, install despite low disk space, install across a skipped version, clear a stuck database change) could stay in the environment of the web service and then apply to every later update without ever asking again. It now applies to that one update only.
- All PM2 calls in the update scripts go through one helper that strips those ten variables first, and both update routes drop them from the inherited environment.
- A comment in the update script claimed the opposite of what was measured; it has been corrected.
v2.1.2
Released 2026-09-17
- Update button: made safe for customers who never talk to us.
- Database backup before the first migration, accepted by content (a valid but empty dump no longer counts as a backup).
- Automatic rollback when the new version does not come up: "alive" is now defined positively, so an unreachable port can no longer pass the health check.
- Health baseline before the update: a server that was already unhealthy no longer loses a good update to a pointless rollback.
- Progress survives the reboot: every run is one row in update_runs, carrying the path to its own log.
- Every refusal is named in plain language, and the safe ones can be overridden with a second explicit confirmation.
- A database change that got stuck can be cleared from the update page, without SSH.
- Older copies of the application are removed before the update instead of after the restart (8.2 GB of leftovers measured on the test server).
- One shared helper file for all update scripts, guarded by an automated check, which also keeps the two message catalogues identical.
v2.1.1.2
Released 2026-09-16
- Two remaining German notification texts are now English as well: the detail body of the CID pool warning, and the periodic pulse message that is sent every couple of hours.
- Both were missed by two earlier passes over the source because the pulse is not a regular alarm call and the CID pool warning had an English title with a German body. They were found by reading what actually arrived on the phone.
v2.1.1.1
Released 2026-09-16
- The self-healing watchdog (voiplix-doctor) now takes its notification target from the web interface (Settings -> Notifications) instead of a root-only file. Until now it read /etc/voiplix-watch.conf, which exists on one kind of installation only - everywhere else the watchdog ran and repaired but never reported.
- If the database cannot be reached, the doctor falls back to the last target it saw, and only then to the configuration file. This matters because one of the things it reports is that the database itself is down.
- Switching a channel off in the web interface now really means silence. It no longer falls back quietly to the old file, which would have kept reporting to a topic the interface does not show.
- A channel access token is now sent by the doctor as well. Without it a token-protected channel failed silently while the test button reported success.
- All watchdog messages are now English instead of German.
v2.1.1
Released 2026-09-16
- Notifications can now be set up in the web interface (Settings -> Notifications): ntfy channels, a catalogue of 50 events, and per event a priority, a repeat interval, quiet hours, a daily cap and an all-clear switch. There is a delivery log and a test button.
- The notification target now lives in the database instead of a root-only file. Until now the watchdog and the doctor read /etc/voiplix-watch.conf, which existed on one installation only - everywhere else both were silent although they were running.
- The operations watchdog is now part of the product. Its four scripts and three systemd units ship with the release and are installed by the root step. Until now they existed only as a hand-installation on a single machine and would have been lost on the next reinstall.
- The watchdog no longer insists on its configuration file: the thresholds now have built-in defaults that an existing file may still override. Without this it refused to start at all on an installation without that file.
- Fixed: a failed delivery used to arm the repeat timer anyway, so the alert stayed silent for the full repeat window - up to six hours for one of them. The timer is now armed only after a delivery actually succeeded.
- Fixed: the channel alarm spoke of calls while measuring channels (one call uses two channels), the whitelist-miss alarm never sent an all-clear, and the missing-hangup-cause alarm sent an urgent alert against a threshold named warning.
- Device and provider IP addresses are now exempted from the Asterisk fail2ban jail automatically, taken from devices.host. Provider addresses could previously be banned for an hour, which stops outbound calls over that carrier. SSH is deliberately not covered by this exemption.
- The firewall script now reaches running installations at all. No update ever shipped it, so three installations were running three different versions of it.
- schema.prisma and the database agree again - 31 differences down to three harmless index rebuilds - and a new gate keeps it that way. Without it a future prisma migrate dev would have dropped 17 indexes, among them the one that carries the CID reputation.
- New gates: schema drift and a translation-coverage ratchet. The line-ending gate now covers the whole tree and also rejects NUL bytes, which had quietly made two files invisible to grep.
- Removed: liveChannels, a server action reachable over HTTP that had no user interface and no callers.
v2.1.0.1
Released 2026-09-15
- Statistics no longer load every call of the period into the web process: Calls per day (and its CSV export), Calls by source, System stats, Profit, Direction stats, Destination group stats and the Usage report now count and sum in the database.
- Measured at a production system before this release: Calls per day took 5.9 GB and 26 s for one page view, Calls by source 852 MB, System stats 597 MB, Direction and Destination group stats about 900 MB each, the Usage report 807 MB for a single day.
- The numbers stay exactly the same: an old-versus-new comparison with tolerance zero (to the cent) over every role, system accesses, day and month boundaries and all Usage report dimensions confirmed it.
- Usage report: a system access that is limited to selected users now sees only those users. Before, the report summed the calls of all users for such an access.
- New build guard: a new query that loads the calls table without a limit stops the release build.
- voiplix-doctor repairs by default on new installations: nginx reload/start and a restart of voiplix-web or voiplix-background after 3 red runs, at most 3 times per service per day. Asterisk, PostgreSQL and fail2ban are never restarted automatically.
- voiplix-doctor sends ntfy notifications when /etc/voiplix-watch.conf names a target - only on state changes (alarm, repaired, repair failed, repairs stopped, daily repair budget used up, recovered) and at most 3 alarms per check per day.
- Existing systems receive the new doctor with a one-time root step after the update (scripts/installer/setup_asterisk_pjsip.sh from the release tree); the update output names the files that differ.
- New acceptance tools: scripts/security/probe-web-memory.mjs (memory per page) and scripts/security/probe-stats-parity.mjs (old versus new statistics).
v2.1.0
Released 2026-09-13
- Read-only admin: a new "Read only" preset for system accesses ticks every view right plus recording download - such an access opens every page and changes nothing.
- The rights catalog is split: 52 areas now have a separate view right next to manage. Every role and system access that held manage was given view as well, so nobody loses a page.
- Pages open with the view right; every save, create and delete checks the manage right on the server. The page guard alone never protected an action.
- New separate rights for listening in on calls (call tracing) and for marking action log entries and integrity errors as processed.
- Secrets are masked on the server for accesses without the manage right: API secret key, SMTP and payment gateway passwords, SIP, AMI and SSH secrets, PINs, the license activation code and password hashes.
- System accesses now need the right itself everywhere instead of inheriting the user type of their anchor account - check system accesses that hold only view rights, for example for devices or CDR aggregates.
- Live call endpoints, the WebRTC configuration and the background socket refuse system accesses without the matching right.
- CDR export templates, aggregate templates and disputes can only be changed inside the owner's own tenant.
- Opening a page no longer writes to the database for an access without the manage right.
- Accountants can still save the general settings.
- The Providers menu entry is now shown to accountants, resellers and partners.
- Removed buttons that always ended in "No access": quality test link, PBX function edit, quickforward link in the DID widget, e-mail template buttons for accountants and resellers.
- The SMTP password field is no longer pre-filled - leaving it empty keeps the stored password.
- The REST/XML-API permission table now lists read rights; it is still not enforced, so API behaviour is unchanged.
- Release builds run four more gates: background TypeScript, public middleware prefixes, navigation rights and write rights on every server action.
- New acceptance probes for the rights catalog and the read-only admin, and a database content fingerprint tool for before/after comparisons.
- Database migration: adds rights and role assignments and updates three right descriptions - nothing is removed.