Changelog

Every release, and what changed

Calendar versioned as YY.MM.PATCH. Breaking changes are stated at the top of the release that contains them, not left for you to find in production.

26.09.0

Latest

Things that had never worked

66 fixes, and the theme is not regressions — it is features that had never worked at all. Every MFA recovery code the system had ever issued was rejected before verification. Restoring a config-only backup NULLed every credential secret in the organization and reported success. Plugin install was impossible on any production deployment. The HA overlay could not start, and streaming replication had never once worked. Nearly all of it was found by RUNNING the product on a clean Linux box, from a fresh clone, rather than by reading it.

Upgrading: Pull, rebuild, restart. The migration chain runs itself and was verified in place from 26.08.4 on existing volumes. Two things do not apply themselves: docker/postgres/init-replication.sh only runs on a FRESH Postgres volume, so enabling --ha over an existing single-node install needs the manual command in that script's header; and .env.max.example no longer enables the dr profile, which started an rclone container that cannot work without operator credentials.

  • FixedMFA recovery codes are minted at 10 characters and the login schema capped the field at 8, so every recovery code the system had ever issued was rejected before verification.
  • SecurityA camera stream token, designed to be safe in a URL query string, authenticated the entire REST API with its owner's full role. The scope check existed on the WebSocket and on no other route.
  • FixedRestoring a config-only backup with “Overwrite existing” NULLed every credential secret in the organization and reported success.
  • FixedPlugin install was impossible on any production deployment: the volume mounted over a path the image never creates, so it was root-owned while the container runs as uid 1001. Firmware upload, evidence export and the backup destination had the same fault.
  • Fixed./install.sh was not executable. Fifteen of nineteen tracked shell scripts were committed non-executable, so the documented first command failed with Permission denied on every fresh clone.
  • FixedEvery event a Celery task published was silently discarded: the bus only fanned out to Redis when a client was set, and nothing in the Celery bootstrap ever set one.
  • FixedThe HA overlay could not start. pgbouncer's tmpfs was owned by uid 999 while its image runs as uid 70, and the streaming-replication role had never been created by anything. --tier max --ha now brings up 19/19 healthy and passes a Sentinel failover drill with the replica promoted in about eight seconds.
  • FixedChanging your own password and enrolling MFA were unreachable from the shipped UI.
  • FixedThree API endpoints were unreachable because a catch-all route was registered ahead of them, including a certificate delete that dispatched to the VM-delete handler.
  • SecurityThe edge CSP no longer permits arbitrary WebSocket hosts; the hardening had been applied to API responses and not to the page. A factory reset could be confirmed with the string “false”.

26.08.2

Writes that said they worked, and did not

A large patch release: 55 fixes and no schema changes. The theme is device writes that reported success without the device agreeing, which is the failure mode this project exists to avoid. It also fixes a session bug that logged every user out roughly an hour after signing in.

Upgrading: Pull, rebuild, restart. No migration. Three breaking API changes, all removals of parameters that never did anything.

  • FixedSessions no longer end after one hour. The refresh endpoint required the token in the request body while documenting itself as accepting the httpOnly cookie, so the browser sent an empty object and received a validation error. The frontend treats a failed refresh as a dead session, so every user was returned to the login screen at token expiry.
  • FixedA device write that a Grandstream phone refused reported success. Seven call sites discarded the result. The reboot path could not report a refusal at all, because every failure branch returned success, including authentication failure.
  • FixedFirmware rollback ran a full permission check and then returned success from a stub that performed no rollback. It now answers 501 and says why: no adapter exposes a rollback primitive.
  • FixedNotification providers that were configured now actually send. Eight of fifteen, including Mailgun, SendGrid, Brevo, Postmark, Resend, Amazon SES and both Twilio channels, were constructed as a webhook with no URL and delivered nothing while reporting healthy.
  • FixedScheduled work runs. Firmware upgrade schedules had never executed because their next run time was never written, and SLA report schedules were broken at both ends.
  • FixedThe audit trail records the actor's email again. It was accepted by the logging call, documented, and discarded before the row was written, leaving only a user id that stops resolving once the account is deleted.
  • FixedTraffic analysis reports real numbers. Every NetFlow v5 record carried wrong values, flushes dropped batches under load, and custom deep packet inspection rules classified nothing.
  • SecurityAn imported OpenVPN profile was stored in plaintext, private key included. It is encrypted at rest now.
  • SecurityAn API key kept the permissions of its owner's previous role after a demotion. Scopes are intersected with the owner's current role on every request.
  • SecurityA single-camera stream token opened the organization-wide realtime socket.
  • SecurityZero-touch provisioned Grandstream phones were sent the wrong SIP password, and one endpoint returned a SIP secret in its response body.
  • BreakingTwelve endpoints no longer accept a site_id parameter. They ignored it before, so responses are unchanged; the records behind them have no site column to filter on.
  • BreakingPOST /firmware/devices/{id}/rollback returns 501 rather than 200. It never performed a rollback.
  • BreakingThe OpenVPN import endpoint no longer accepts a description. There was no column to store it in.

26.08.1

Every open dependency advisory closed

A patch release with no new features and no schema changes. Every change is a security fix, a correctness fix, or a documentation correction. The project went from 28 high and 20 moderate dependency advisories to zero.

Upgrading: Pull, rebuild, restart. No migration.

  • SecurityAll open dependency advisories resolved, including cryptography 49.0.0 (a PKCS#7 Bleichenbacher oracle) and aiohttp 3.14.1 (an out-of-bounds read in the C HTTP parser).
  • FixedWebhook retries were never delivered. A failed delivery was queued to a Celery queue that no worker declared or consumed, so it sat in a retrying state permanently and never reached the dead-letter table. Nothing surfaced an error, so the only visible symptom was a webhook that quietly stopped arriving.
  • FixedSingle sign-on could not be started. OIDC, SAML and LDAP providers could be configured and the callback route worked, but the login screen offered password authentication only, so a configured provider was unreachable.
  • FixedAn access-control relock task was registered with no worker to run it, so a door unlock window could elapse without the database row being restored to locked.
  • FixedThe agent registration command failed against any current controller, which is the first command an operator runs.
  • DocsThe write-safety default was documented backwards across roughly thirty pages. They claimed the adapter read-only flag defaults to true and that a fresh install cannot touch hardware; the shipped Compose stack has defaulted to read-write since June, because FreeSDN is expected to manage your gear out of the box.

26.06.1

First public release

The first public release of FreeSDN: a vendor-neutral, self-hosted infrastructure controller providing one interface, one API and one credential vault for the network switches, firewalls, cameras, VoIP, hypervisors and storage you already own.

Upgrading: Initial release.

  • NewTen independently loadable modules covering network, firewall, cameras, VoIP, hypervisor, storage, backup, observability, access control and an AI assistant.
  • NewVendor adapters for TP-Link Omada, Ubiquiti UniFi, MikroTik, OpenWrt, OPNsense, pfSense, Hikvision, ONVIF, FreePBX, Grandstream, Proxmox VE and TrueNAS, each carrying a published maturity label.
  • NewThe staged-write pipeline: every device mutation is recorded, shown, and applied only behind a platform-wide flag and an explicit per-request confirmation.
  • NewMulti-organization role-based access control with per-user site grants, credential encryption at rest, and an immutable audit log.
  • NewA typed plugin SDK with a permission-declared runtime, and an MIT-licensed edge agent for discovery inside remote networks.
  • DocsPublished honestly as young software with limited field exposure beyond its maintainer's own mixed-vendor deployment, with no third-party security audit or certification claimed.

Full release bodies, source archives and signed tags are on GitHub Releases. Upgrade instructions are in the upgrade guide.

Running an older version?

Upgrading is a pull, a rebuild and a restart. Take a backup first, as with any infrastructure component.