Updating
Updating a server means pulling new source from Git, building a new originchats-osl, and restarting. On the first start after an update, the server may migrate stored data to a newer layout. This page covers each step and how to roll back.
Before you update
Section titled “Before you update”-
Back up the database. Migrations can change files in ways an older version can’t read, so a backup is your only way back. Follow Make a backup.
-
Note the current version, so you can return to it:
Terminal window git -C ~/originchats-osl rev-parse HEAD -
Make sure the checkout is clean. The updater refuses to run if
git statusshows any change, including untracked files. A database directory inside the checkout counts, unless it’s the ignored./db.
For a large server, test the update on a copy first: restore the backup into another directory, build the new version in a separate checkout, and start it on a different port.
Update from a client
Section titled “Update from a client”When the server runs under scripts/run.sh, the owner can update it without shell access by sending server_maintenance:
{ "cmd": "server_maintenance", "action": "update", "confirm": true}What happens next:
- The server replies with its status and stays online.
- It runs
scripts/update.sh, which downloads and builds the new version. See What the updater does. - If the update fails, the state becomes
failedand the current version keeps running. The owner can read the updater’s output in the statusdetailsfield. - If it succeeds, the server records a
server_maintenanceaudit entry, exits with status 75, and the launcher starts the new build. - The new build runs startup migrations, then accepts connections. Clients reconnect on their own.
Send "action": "status" to follow progress. The update and restart actions are available only to the owner.
This path doesn’t stop the server for a backup. Take one first, or use a filesystem snapshot.
Update from the shell
Section titled “Update from the shell”To update by hand:
# 1. Stop the server (Ctrl+C, or: sudo systemctl stop originchats)# 2. Back up the database# 3. Build and install the new versioncd ~/originchats-osl./scripts/update.sh# 4. Start the server again./scripts/run.shrun.sh rebuilds from source every time it starts. So git pull --ff-only followed by ./scripts/run.sh also updates the server. update.sh adds safety checks and installs the binary only after a successful build.
You can also run update.sh while the server is running. The new binary takes effect at the next restart.
What the updater does
Section titled “What the updater does”scripts/update.sh works on the checkout it lives in, whatever directory you run it from. In order, it:
- Refuses to continue if the checkout has any local change:
Update refused: the source checkout has local changes. - Finds the current branch’s upstream, and stops if there isn’t one:
The current branch needs a remote upstream.It also stops if the checkout isn’t on a branch. - Fetches the upstream branch, without tags.
- Refuses if your branch has commits the upstream doesn’t:
Update refused: the upstream has diverged. - Checks out the fetched commit in a temporary Git worktree under
.update-XXXXXX/, and buildsoriginchats-oslthere without the build cache. - Stops if the build produced no executable:
The build did not produce an executable. - Fast-forwards your branch to the fetched commit, and replaces
originchats-oslwith the new build. - Prints
Installed <commit>and removes the temporary worktree.
If any step fails, the checkout and the installed binary are left as they were. The updater never touches the database.
Migrations on startup
Section titled “Migrations on startup”Migrations convert data written by older versions into the current layout. They run on their own. There’s no command to run them or to check their progress, apart from the logs.
On every start, before accepting connections, the server:
- Undoes any interrupted write.
- Loads users, roles, channels, webhooks, access settings, and unread state, migrating unread state if needed.
- Builds mention history if it hasn’t been built yet.
- Migrates attachment details if needed.
If step 1, 3, or 4 fails, the server logs the error and exits. run.sh doesn’t retry after that. Restore the backup, or fix the cause and start again.
Two more migrations run later, the first time the data is used.
What migrations change
Section titled “What migrations change”| Migration | When it runs | What changes | If it fails |
|---|---|---|---|
| Unread state | At startup, if unreads.json exists |
Each account’s unread state moves to users/<id>/unreads.json. unreads.json is renamed to unreads.json.migrated. Ping counts start at 0. |
Startup continues. unreads.json is kept and the migration runs again on the next start. |
| Mention history | At startup, if mentions-version.json doesn’t exist |
Scans every channel and thread once and writes each account’s mention history to users/<id>/mentions/. Then writes mentions-version.json. |
The server logs unable to build persistent mention history and exits. |
| Attachments | At startup, if attachment_ids.txt or attachment_stats.json is missing |
attachments.json is split into one attachments/<id>.json per attachment, plus the ID index and totals. attachments.json is renamed to attachments.json.migrated. |
The server logs unable to migrate metadata and exits. |
| Audit log | The first time the audit log is read or written | modlog.json is converted to modlog.jsonl and deleted. |
The audit log is unavailable until it succeeds. |
| Thread messages | The first time a thread with no messages in the current layout is read | The first non-empty old thread file (threads/<id>.jsonl, threadMessages/<id>.jsonl, or their .bak copies) is copied into threads/<id>/0000.jsonl. The old file is left in place. |
Not reported. Check old threads after updating. |
Things to know:
- The mention history build reads all message history. On a large server the first start after it’s introduced can take a while. Progress is logged under
mentions.migrate. - Mention history is built from members’ current roles and permissions, because the server can’t know who held which role when an old message was sent.
- If
modlog.jsoncan’t be parsed, it is deleted, not converted. Keep a backup if you care about old audit entries. *.migratedfiles are kept for reference. Delete them once you’re sure the migration worked and you have a backup.
See legacy formats for the full list of older layouts the server reads.
Roll back
Section titled “Roll back”A migration can’t be reversed in place, and an older build may not understand migrated data. To go back, restore both the old code and the old data:
# Stop the server first.cd ~/originchats-oslgit reset --hard <commit you noted before updating># Restore the database backup you took before updating../scripts/run.shrun.sh rebuilds the old version when it starts. The next update.sh run will fast-forward to the latest version again.
Check the update
Section titled “Check the update”After the restart:
- Check the logs for
server listeningand for any migration errors. - Send
server_maintenancewith"action": "status".started_atshows when the running process started. Theversionfield comes fromservice.versionin the config, so it doesn’t change with updates. Usegit log -1in the checkout to see which commit is installed. - Log in as an ordinary member and read and send a message.
