Skip to content

Versioning and Releases

FreeSDN uses Calendar Versioning (CalVer) in the format YY.MM.PATCH:

ComponentMeaningExample
YYTwo-digit year26 = 2026
MMTwo-digit month (zero-padded)06 = June
PATCHPatch increment within the month, starting at 11, 2, 3

Current release: 26.06.1

Examples of what version numbers communicate:

  • 26.06.1 - first release of June 2026.
  • 26.06.2 - patch release in the same month (bug fix or security patch).
  • 26.07.1 - first release of July 2026.

There is no separate “major” or “minor” bump - the date carries that information. Breaking changes are called out explicitly in the release notes.


FreeSDN targets a monthly release cadence aligned to the CalVer month component. Security patches are released as PATCH increments as soon as they are ready - they do not wait for the monthly cycle.

Dependency update policy:

  • Python and Node packages are not adopted on release day. The 3-day rule applies: new versions are evaluated after they have been on PyPI/npm for at least 72 hours, which catches withdrawn releases and compromised-maintainer incidents.
  • CVE patches override the 3-day rule and are applied as soon as the upstream patch is signed.

Production images are published to the FreeSDN GitHub Container Registry:

ghcr.io/freesdn/freesdn/backend:<version>
ghcr.io/freesdn/freesdn/frontend:<version>

The logdb service is not a pre-built registry image - it is built locally from docker/Dockerfile.logdb (PostgreSQL 18 + TimescaleDB extension) and tagged as freesdn-logdb:local by default. Override the tag with the LOGDB_IMAGE environment variable if you need to pre-build and cache it.

To use the registry images you must first set the image variables in your env file (the compose defaults fall back to locally-built tags). Add these two lines to .env.pro before pulling (substitute the release version):

Terminal window
# In .env.pro - set the registry image tags:
BACKEND_IMAGE=ghcr.io/freesdn/freesdn/backend:26.06.1
EDGE_IMAGE=ghcr.io/freesdn/freesdn/frontend:26.06.1

Then run the standard deploy workflow:

Terminal window
# Pull the images specified above
docker compose --env-file .env.pro pull
# Restart with zero-downtime rolling update (single-host)
docker compose --env-file .env.pro up -d --no-build

Always run migrations after pulling a new release:

Terminal window
docker compose --env-file .env.pro exec api python scripts/migrate.py

Tagged releases are available on the FreeSDN GitHub repository. The public release is a flattened snapshot (no development history):

https://github.com/freesdn/freesdn

The freesdn-agent desktop + headless daemon is distributed separately (MIT-licensed, Python ≥ 3.11, Windows / Linux / macOS):

https://github.com/freesdn/freesdn-agent

Current agent version: v1.0.0 (alpha). The agent uses ECDSA-P256 signed auto-updates (fail-closed - an agent with a bad signature stays on the previous version rather than installing a corrupt update).


The FreeSDN core platform is licensed under the GNU Affero General Public License v3.0 only (AGPL-3.0-only).

Key points of AGPL-3.0:

  • You may use, study, modify, and distribute the software freely.
  • If you run a modified version as a network service (SaaS), you must make the modified source available to users of that service under the same licence.
  • Distribution of binaries requires providing the corresponding source.
  • The licence applies to the entire platform codebase under SPDX-License-Identifier: AGPL-3.0-only.

Full licence text: LICENSE in the repository root, and https://www.gnu.org/licenses/agpl-3.0.html.

The freesdn-agent package is separately licensed under the MIT License. You may embed or redistribute it without the AGPL network-service clause.

Full licence text: LICENSE in the freesdn-agent repository.


  1. Read the release notes for any breaking changes or required migration steps. They are published alongside each tagged release.

  2. Take a database snapshot before upgrading:

    Terminal window
    docker compose --env-file .env.pro exec pg-backup bash -c '
    STAMP=$(date +%Y%m%d_%H%M%S)
    pg_dump -h postgres -U "$PGUSER" -d "${POSTGRES_DB:-freesdn}" \
    | gzip > /backups/preupgrade_$STAMP.sql.gz
    pg_dump -h logdb -U "$LOGDB_USER" -d "$LOGDB_DB" \
    | gzip > /backups/preupgrade_logdb_$STAMP.sql.gz
    '
  3. Pull new images:

    Terminal window
    docker compose --env-file .env.pro pull
  4. Apply migrations (idempotent - safe to run even when already at head):

    Terminal window
    docker compose --env-file .env.pro up -d api
    docker compose --env-file .env.pro exec api python scripts/migrate.py
  5. Start the rest of the stack:

    Terminal window
    docker compose --env-file .env.pro up -d
  6. Verify health:

    Terminal window
    curl -fsS http://localhost:8080/api/v1/health/ready

    Port 8080 is the default Caddy edge port (override via EDGE_HTTP_PORT). In a production stack, the API container port 8000 is not published on the host - only the edge is. To check health from inside the container instead: docker compose --env-file .env.pro exec api python -c "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/api/v1/health/ready', timeout=5); print('ready')"

For full disaster-recovery procedures see docs/DR_PROCEDURE.md in the repository.


The honesty matrix of all 13 adapters (maturity tier, write capability, known limitations) is maintained at docs/SUPPORTED_VENDORS.md in the repository. It is updated with each release. Do not rely on marketing summaries - check that file for your specific vendor before deploying.

All product names, logos, and brands are property of their respective owners. FreeSDN is an independent project and is not affiliated with or endorsed by the vendors it integrates with. See Trademarks.