Announcing Proliferate
Proliferate

Updates & versioning

One-command server updates, and how desktop versions follow.

Updating a self-hosted Proliferate is one command on the server. The server image bakes in the compiled Web app, so pulling a new image updates the Web app and the API atomically, in the same step; there is no separate Web deployment to coordinate. Connected desktop apps follow the update automatically too; you never coordinate a separate desktop rollout.

Update the server

Run ./update.sh from your deploy directory (the extracted proliferate-deploy bundle you deployed from). Under the hood it runs the sequence:

Pull

Pull the server image at the tag configured in .env.static (PROLIFERATE_SERVER_IMAGE_TAG).

Migrate

Run database migrations in a one-shot container before the new server starts.

Restart

Restart the stack (docker compose up -d).

The script also re-checks that generated secrets exist, refreshes the runtime binaries on the host under /opt/proliferate/bin when the cloud sandboxes add-on's runtime-binary variables are set, and health-checks the stack before it exits, so a completed run means the new version is actually serving.

Info:

Model gateway operators: update.sh also pulls, restarts, and health-waits on litellm/litellm-db automatically whenever AGENT_GATEWAY_ENABLED=true — the same one command covers the gateway, no separate profile command needed. See Model gateway. Installs without the gateway can ignore this.

To confirm the version after an update:

curl -s https://proliferate.company.com/meta

Version pinning: a release tag vs stable

The server image is ghcr.io/proliferate-ai/proliferate-server, published with per-release version tags and a stable tag. You choose which one you track with PROLIFERATE_SERVER_IMAGE_TAG in .env.static:

  • Pin a release tag (for example 0.3.0) for change-controlled environments. update.sh then only moves you when you edit the tag, so an update is an explicit, reviewable change.
  • Track stable to pick up releases whenever you run update.sh, with no file edits.

Releases are published on GitHub as server-vX.Y.Z, and the deploy bundle (proliferate-deploy.tar.gz) is attached to each release. The support intent is N releases back: staying a few releases behind is fine, and update.sh is the one operator motion that catches everything up.

How desktops stay in lockstep

The server you run is the version root for the whole fleet:

  • GET /meta on your server reports serverVersion, desktopVersion, runtimeVersion, and minDesktopVersion. Each server release is stamped with the desktop and runtime versions it shipped with.
  • Connected desktop apps check GET /desktop/updater/latest.json on your server, which responds with a 302 redirect to the official CDN update manifest for the version your server pins. When the manifest for that exact version is not published (a server built ahead of a desktop release, or a release that predates versioned manifests), the server redirects to the latest stable manifest instead, so update checks always land on a valid manifest. Your server carries only a version number; it never builds or serves desktop binaries.
  • The desktop app verifies every update against the signing key baked into the official build, no matter which endpoint served the manifest. A server can choose which version desktops run, but it can never ship a modified build.
  • minDesktopVersion is the compatibility floor: desktops older than it are told to update before they can keep working against your server.

The net effect: when you run update.sh, your users' apps converge on the matching desktop version on their own.

Data retention & backups

There is no built-in backup command yet; back up these two things on whatever schedule your organization requires.

1. The database. Everything about your orgs, users, sessions, and invitations lives in the db service's named volume (Postgres). If you enabled the model gateway, its litellm-db volume holds LiteLLM's own keys and spend records separately. Back up either with pg_dump against the running container, or a volume snapshot:

docker compose --env-file .env.runtime -f docker-compose.production.yml \
  exec db pg_dump -U proliferate proliferate > proliferate-$(date +%F).sql

Taking a backup before running ./update.sh is cheap insurance, since migrations move the schema forward and are not designed to move backward.

2. Host-side config and key material, which the database backup above does not cover:

PathWhy it matters
.env.generatedThe JWT signing secret and the credential-encryption key. Losing this file without a backup means every session is invalidated and stored credentials become unrecoverable — restoring the database alone is not enough.
.env.static / .env.localYour configuration. Reconstructible by hand from this doc, but faster to restore from a copy.
GITHUB_APP_PRIVATE_KEY_HOST_PATH (default /opt/proliferate/secrets/github-app)The GitHub App's private key, if you configured cloud sandboxes. Re-downloadable from GitHub if lost, but faster to back up.
Caddy's caddy_data / caddy_config volumesIssued TLS certificates. Not critical — Caddy reissues them automatically on next boot if lost — but backing them up avoids a brief re-issuance window.

Restore verification. After restoring the database volume and .env.generated onto a fresh host running the same server version, boot the stack and confirm GET /health and GET /meta respond, then sign in as an existing user — a successful sign-in confirms the JWT/encryption keys and the user data are consistent with each other. Do not restore .env.generated from one backup and the database from a different one; they must be a matched pair, or existing sessions and encrypted credentials will not decrypt.

  • Data is kept until you delete it. The server does not yet ship automated retention windows for session data; scheduled purging is on the roadmap. If you have a hard retention requirement today, get in touch.
  • Telemetry is separate from retention and is covered in Telemetry & privacy.

On this page