Updating is intentionally simple.
Upgrade one major version at a time. Skipping major versions is not supported. If your target is more than one major version ahead, upgrade through each intervening major version in order. Verify that the installation is working after each upgrade before continuing.
If this server was installed before v2.2.1, do the one-time installer refresh first. After that, the steps below apply.
When upgrading from v2 to v3, follow upgrading from v2 to v3 if you need to retain existing Blobstore data. That guide also explains how to start the Blobstore upgrade fresh when retaining the existing data is unnecessary.
Standard (online) server
bootstrap.sh is only used for the initial installation. The installed setup.sh handles subsequent upgrades.
Edit
/opt/3b/.envand changeVERSIONto the new release.Run the installed setup script:
sudo bash /opt/3b/setup.sh
The setup script compares the requested VERSION with the release stamped into its installed bundle. When they differ, it downloads and verifies the requested bundle, replaces its installer, Helm chart, and bundled tools, and re-executes the new setup.sh before touching Helm or application images. Your data in Kubernetes persistent volumes is preserved, and your configuration and secrets in /opt/3b/.env are reused. Nothing rotates.
The server needs outbound access to oci.tines.com for every update, just like the first install.
Air-gapped (offline) server
The offline server can’t reach the registry, so you build the new version’s bundle on a connected machine, copy it across, extract it into /opt/3b, and re-run setup.sh.
On a machine that meets the build host requirements, run the air-gapped bundle builder and provide your registry credentials:
VERSION=<new-version> \ REGISTRY_USERNAME="$OCI_USERNAME" \ REGISTRY_PASSWORD="$OCI_PASSWORD" \ bash -c "$(curl --proto '=https' --tlsv1.2 -fsSL https://sh.3b.dev/airgapped.sh)"
This creates 3b-self-hosted-<new-version>.zip in the current directory. Copy it to the offline server by whatever means you use. Change VERSION in /opt/3b/.env, replace the previous chart, images, and bundled tools, and re-run the installer:
sudo rm -rf /opt/3b/chart /opt/3b/images /opt/3b/bundled sudo unzip -o 3b-self-hosted-<new-version>.zip -d /opt/3b cd /opt/3b && sudo bash setup.sh
Your configuration and secrets in /opt/3b/.env are preserved. For the full flow, see updating an air-gapped server.
Tunnel networks
If tunnel networks are enabled, an upgrade stops the gateway before starting its replacement. Tunnel connectivity is interrupted, and requests still running after the 30-second shutdown window can fail. Exit nodes reconnect automatically once the replacement is ready; recovery time depends on image pulls, scheduling, and startup. Schedule a maintenance window for workloads that depend on tunnels.
The installer preserves the gateway CA and authentication token across upgrades and disable/re-enable cycles. Keep the generated gateway secrets in /opt/3b/.env and the Kubernetes tunnel-secrets Secret: replacing the CA would prevent existing exit nodes from reconnecting.
Verify
After the installer finishes, confirm everything rolled out and the UI responds. See verifying the install.
Recommendations
Back up
/opt/3b/.envand the database before updating anything you care about.The installer is safe to re-run. If an update is interrupted, run
sudo bash /opt/3b/setup.shagain.
