Upgrading a self-hosted box to 1.2.0
The install guide says an upgrade is a binary swap and a restart, and that a release needing more says so on this blog. 1.2.0, coming from 1.1.0, needs more. This post is the whole list.
1. Take a backup first
Startup runs 1.2.0’s schema migrations, and they only go forward. Its first start with your secret key also reseals stored secrets in a form 1.1.0 can’t read (step 3). Back up before you replace the binary:
- SQLite: stop the
pingtowerunit and copy the data directory, or keep a recent backup that-backup-dirwrote. - PostgreSQL: back it up the way you back up any PostgreSQL server, for
example with
pg_dump.
See Storage for what lives where.
2. Migrations run once, forward only
When the new pingtower binary starts, it migrates the control database and
every tenant’s storage. For a box coming from 1.1.0, the migrations add room
for:
- A team’s IP allowlist, off until an owner adds a range. See IP allowlist.
- The tools each connected AI app may use, per member. See Limit an app’s tools.
- Whether each push registration is verified. A registration that never verified still gets pages as before.
- Who added each member, and how, and the member reviews a password change raises. See Member reviews.
- When each source’s agent token was minted, against when each check’s
envwas last saved. Checks and tokens from before the upgrade keep running as they did. See A new agent token withholds secrets. - A log-query rule’s settings.
- A per-minute history of what each log-query rule counted, for the change and anomaly modes. It starts empty: those rules learn from the upgrade on.
These migrations run by themselves at startup. They add tables and columns and delete nothing, and they need nothing from you beyond the backup in step 1.
3. Your secret key reseals secrets: a binary-only downgrade breaks them
The first time 1.2.0 starts with your -secret-key
(PINGTOWER_SECRET_KEY), it reseals every action’s headers and body and
every typed channel’s config (Slack, Discord, Telegram and the other
integrations that aren’t a plain webhook), each bound to its own record. It
does this for each team the first time it opens that team’s data.
1.1.0 can’t read the resealed values. Putting the 1.1.0 binary back on a box that has run 1.2.0 breaks every action with headers or a body and every typed channel until you restore the backup you took in step 1. Their deliveries fail. To go back, stop the unit, put the old binary back, and restore the backup.
4. Keep the secret key set
A pingtower started without a -secret-key refuses to start when the data
it serves holds sealed secrets. 1.2.0 also counts sealed issue-tracker
tokens and webhook secrets, so a box that holds only those now refuses a
keyless start too. It logs which team holds them and exits:
pingtower: FATAL: tenant <id> holds secrets sealed under a master key, but no --secret-key (PINGTOWER_SECRET_KEY) is set; every sealed tenant would refuse to open. Restart with the key this data was sealed under.
Start it with the key the data was sealed under. A key under 16 characters still stops the box, and under 32 logs a warning.
5. Move your agents to addons 0.6.0
Upgrade the tower to 1.2.0 first, then upgrade each addons agent to addons agent 0.6.0. The tower still accepts agents from 0.4.0 on, so nothing warns you about an older one: this note is the warning.
- A 0.5.0 agent refuses a WebSocket check that carries
env. Sealed headers on a WebSocket check need 0.6.0. A 0.5.0 agent rejects that check and runs the rest of its checks, so the check silently stops running from that agent. The agent’s heartbeat counts it inassignments_rejected. - 0.6.0 refuses a plain
http://tower.urlwhose host is notlocalhostor a loopback IP, and does not start with it. Before you upgrade, put TLS in front of the tower (Reverse proxy & TLS) and switchurltohttps://. To keep plainhttp://, addallow_insecure_http: trueunderagent.towerafter installing 0.6.0, never before: 0.5.0 doesn’t know the key and refuses to start with it. Seetower.url. - 0.6.0 never follows a redirect from the tower. A
3xxis an error naming its status andLocation. If your agent reaches the tower through a redirect, pointurlat the final address.
6. New: moving between SQLite and PostgreSQL
1.2.0 adds pingtower move-data, which copies every database of a stopped
install from SQLite to PostgreSQL or back, checks the copy, and prints the
database line to set in config.yaml. The source is only read. Start
1.2.0 on the source once first, so it is on 1.2.0’s schema, then stop it.
The target must be empty. See
Moving between SQLite and PostgreSQL.
So that move-data can tell a stopped install from a running one, a
running 1.2.0 holds the lock file pingtower.lock in its data directory. A
second pingtower started on the same directory now refuses with
another pingtower process is using this directory. A one-shot -backup
and pingtower pair take no lock, so a cron’d backup of the running box
still works. See Storage.