Tunnex upgrades are forward-only. There is no supported database downgrade; the rollback is a restore of the verified pre-upgrade dump under its matching master key.
The public installer pins release artifacts to a signed descriptor. Its local
upgrade helper verifies the target. With --apply, it takes and verifies a
backup, runs preflight, pulls the approved images, restarts the deployment, and
health-checks it.
Compatibility contract
Section titled “Compatibility contract”- A control plane at protocol version N supports gateway agents at N and N-1.
- An older agent outside that window refuses a too-new artifact and installs a synthetic deny-all interlock rather than partially interpreting it.
- Database migrations are designed for a one-version rolling window.
- Existing gateway forwarding continues from last-applied state during a brief control-plane restart; new management changes wait for reconciliation.
Before every upgrade
Section titled “Before every upgrade”- Confirm the release notes and exact signed target shown by the deployment.
- Confirm the separately stored master key is accessible to the recovery team.
- Test the current backup/restore procedure, not merely the existence of files.
- Resolve expired gateway certificates and agents below the N-1 window.
- Record readiness, gateway health, and actual tunnel handshakes.
- Use a maintenance window even though the data plane is designed to continue.
The current host helper uses pg_restore --list to validate its new dump. Install
the PostgreSQL client tools on the host before --apply; the public installer’s
base prerequisites do not currently check or install that command.
Run the read-only preflight manually when investigating readiness:
cd tunnexsudo docker compose -f tunnex.yml exec -T api preflightIt refuses until you explicitly confirm a verified backup and master key:
sudo docker compose -f tunnex.yml exec -T \ -e TUNNEX_PREFLIGHT_BACKUP_CONFIRMED=yes api preflightPreflight checks database reachability, migration cleanliness, gateway certificate validity, agent compatibility, and the acknowledged rollback plan. An unknown result is a refusal, not a warning.
Public-installer upgrade
Section titled “Public-installer upgrade”The default is a dry run:
cd tunnexsudo ./upgrade.shReview the exact release and actions. Apply only after the dry run and recovery checks are satisfactory:
sudo ./upgrade.sh --applyDo not hand-edit tunnex.yml. The helper checks its installer-recorded baseline
and refuses a modified managed file. Re-running the current public installer can
repair managed upgrade assets without intentionally replacing deployment secrets
or applying an upgrade.
Newer public installations can also request the same bounded host-side workflow from the dashboard. The API does not receive the Docker socket or general root command execution; it writes a constrained request for the root-owned helper.
For a deployment administrator (cp_admin):
- Open Overview.
- In Upgrade Center, review Installed, Target, Upgrade state, Database backup, manifest verification, and release notes.
- Select Upgrade control plane.
- Confirm the exact server-verified target.
- Follow request, signed-release verification, backup, preflight, pull, restart, health, and success/failure stages.
Ordinary organization administrators do not see this deployment-level control. The UI cannot choose an arbitrary release target.
Air-gap status
Section titled “Air-gap status”Disabling discovery remains useful for an operator-supplied signed manifest:
TUNNEX_RELEASE_UPDATE_CHECK=falseThe helper accepts local archives with:
sudo ./upgrade.sh --manifest ./release.json --airgap ./bundleThis command is not a side-effect-free dry run: it loads *.tar archives into
the local Docker image store before stopping at the apply guard. An absent,
altered, stale-sequence, or mismatched descriptor is a hard failure. Do not run
--apply in a disconnected environment until a release explicitly documents a
complete offline workflow.
Observe the rollout
Section titled “Observe the rollout”sudo docker compose -f tunnex.yml pssudo docker compose -f tunnex.yml logs --since=15m api node-agentsudo docker compose -f tunnex.yml exec -T api \ wget -qO- http://127.0.0.1:8080/healthzsudo docker compose -f tunnex.yml exec -T api \ wget -qO- http://127.0.0.1:9090/readyzsudo docker compose -f tunnex.yml exec -T node-agent wg showVerify all of the following:
- database migrations completed and readiness is
ok leaderorok follower; - each gateway reconnects and applies the current revision;
- no gateway reports
unsupported_policy_version; - user sign-in and one representative management action work; and
- an established and a newly initiated tunnel both pass traffic.
The helper’s automated post-restart gate checks /healthz liveness only. The
manual readiness, reconciliation, and traffic checks above are required before
calling the upgrade healthy.
Upgrade gateway agents one at a time after the control plane, keeping the fleet in the supported window.
If an upgrade fails
Section titled “If an upgrade fails”Stop and preserve the logs, signed descriptor, helper status, and pre-upgrade artifacts. Do not attempt an ad-hoc schema downgrade. Follow Backup and restore with the pre-upgrade dump, its digest-bound manifest, and the matching separately held master key.
After recovery, prove gateway identity and traffic before retrying the release.