Content changes do not require a new release: save them in the admin interface. A new release is needed when application code changes.
1. Prepare the code
Change fields, relationships, forms, and access in Generator UI, then run Generate. Change your own Go/React code in custom zones. You can combine these approaches for each update.
Generate preserves existing custom files, but model changes may require your code to handle new fields and types. Generation itself does not update the running application.
2. Build a new version
Choose the instructions for your mode:
| Mode | Where to build |
|---|---|
| Source | Update the Git checkout and build directly on the VPS |
| Archive | On your workstation or in CI; keep JSON and archive together |
| Registry | On your workstation or in CI; images are published to a registry |
| Prod-local | On the computer with the local environment |
For prod-local:
bash ./deploy/control build --env local --output local-release-02.json
For a server environment (Source — after git pull --ff-only on the VPS):
bash ./deploy/control build --env production --output release-02.json
--output names the new file build creates. Do not edit release JSON or overwrite a previous build with it. The current application keeps running during the build.
Another provision is unnecessary. If only delivery/backup settings changed, use reconfigure rather than releasing new code.
With CI, the build job performs this step after a push to main.
3. Install the release
For prod-local:
bash ./deploy/control deploy --env local --release local-release-02.json --confirm local
bash ./deploy/control status --env local --json
For a server:
bash ./deploy/control deploy --env production --release release-02.json --confirm production
bash ./deploy/control status --env production --json
Run Source commands on the VPS and Archive/Registry commands from the controlling computer. In CI, run the deploy job for the desired build instead.
The application is temporarily unavailable during deploy. The controller stops writes, backs up the current successful release if backup is enabled, applies migrations, and starts the new code. With backup.kind: none, no backup is created. The new release is recorded as current only after readiness checks.
After successful completion, open the application. up is not an update command: it starts the previously recorded release.
If you decide not to release a built version
If build finished but deploy has not started, the server has not changed. Simply do not release that build. Abandon is unnecessary for build output: no server operation has been created yet.
If an update is interrupted
Do not start another deploy over an unfinished operation. Check status first and follow operation recovery. This is especially important on first installation: tables may already exist even though there is no successful release yet.
Return to previous code
Take the ID of a previously successful release from environment history:
bash ./deploy/control rollback --env production --release RECORDED_RELEASE_ID --confirm production
Here --release accepts an ID, not a JSON path. Rollback restores code but does not undo SQL migrations or data changes. The controller checks whether the old code is compatible with migrations. To restore data, use restore from backup.
Change delivery or backup through reconfigure, separately from code releases.
After a successful release
Backend and frontend are replaced with the new release's containers. PostgreSQL and its persistent data are preserved. Old images and archives are not cleaned up automatically. If disk fills up, follow disk cleanup: retain the current release and one previous release for rollback. This also applies to ops, alongside backend and admin.