Upgrading Your Installation
An upgrade replaces the release directory and nothing else. That works safely only because everything worth keeping lives outside it. Read this page before your first upgrade, not during it.
What Survives an Upgrade
| Location | Content | Survives |
|---|---|---|
|
The observation dataset, and with it your inventory, its runs, its tags, its trends, and your migration waves |
Yes, outside the release directory |
|
The sealed deliveries that have not been ingested yet, and the delivered files kept after ingestion |
Yes, outside the release directory |
|
Tenants, accounts, Forwarder registrations and tags, the delivery ledger, quota counters, wave schedules, exclusion groups, audit entries, and API tokens |
Yes, outside the release directory |
|
The active and the previous vulnerability dataset |
Yes, outside the release directory |
|
Your settings, including the secrets |
Yes, outside the release directory |
The TLS keystore ( |
The certificate and private key the installation serves HTTPS with |
Yes, when it is kept outside the release directory |
The release directory ( |
Application code |
No, the upgrade adds a new one beside it |
The Java of the host is not part of the release, and an upgrade does not replace it. Check that the new release’s Java minimum is met before you start.
|
Warning
|
Keep the data and /etc/ljvmi/ljvmi.env outside /opt/ljvmi/<release>. A release directory is replaced at an upgrade, and everything inside it goes with it. See Storage Locations.
|
Nothing else needs to move. Your Forwarders learn their write path and the storage backend from check-in, so an upgrade that changes where deliveries land needs no visit to a Forwarder host.
Before You Start
-
Read the release notes of the version you move to. They open with the upgrade impact: required configuration changes, whether a database migration runs, whether the Java minimum changes, and whether your Forwarders need an upgrade too.
-
Read Upgrade Notes by Version for every release between yours and the target. Some releases need a configuration change before the first start.
-
Check that the disk that receives your backup has room for a full copy of
/var/lib/ljvmi, and keep that copy off the data disk. With the defaultINBOX_RETAIN_AFTER_INGEST=true, the inbox can be the largest part of it.
The Procedure
The jar bundle has no upgrade script. You upgrade by hand, in these steps.
-
Verify the new bundle and extract it beside the running release. Nothing changes yet.
sha256sum -c ljvmi-<new-version>-<sha>-jar.tar.gz.sha256 sudo tar -xzf ljvmi-<new-version>-<sha>-jar.tar.gz -C /opt/ljvmi cd /opt/ljvmi/ljvmi-<new-version>-<sha>-jar sha256sum -c --quiet CHECKSUMS.txt -
Compare the example configuration of both releases, and add any new settings to
/etc/ljvmi/ljvmi.env. You do not copy an env file into the bundle.diff /opt/ljvmi/current/ljvmi.env.example /opt/ljvmi/ljvmi-<new-version>-<sha>-jar/ljvmi.env.exampleDo not change
SESSION_SECRETorFORWARDER_KEY_SECRET. A newFORWARDER_KEY_SECRETmakes every stored Forwarder key unreadable. -
Stop the service, then take a backup. Stopping first matters, because the data files cannot be copied from under a running process. Keep the copy off the data disk. Forwarders keep delivering while the installation is down, and your installation picks the deliveries up after it starts again. With S3 storage, keep the downtime shorter than the upload grant lifetime, 15 minutes by default, because uploads stop once a Forwarder’s grant expires. Don’t restart Forwarders while your installation is down, because a Forwarder can’t start until your installation is reachable.
sudo systemctl stop ljvmi sudo tar czf /backup/ljvmi-$(date +%Y%m%d).tar.gz -C /var/lib ljvmi -
Switch
currentto the new release and start the service:sudo ln -sfn /opt/ljvmi/ljvmi-<new-version>-<sha>-jar /opt/ljvmi/current sudo systemctl start ljvmi -
Verify before you let Forwarders back in. Readiness waits for the database migrations, so the command retries instead of failing at the first refusal:
curl -fs --retry 30 --retry-delay 2 --retry-connrefused http://127.0.0.1:9000/q/health/ready journalctl -u ljvmi | grep -i flywayThe first command shows that the application is ready. The management port serves plain HTTP in every setup, so the command needs no change for HTTPS. The second command shows which database migrations ran. Sign in at the address you normally use,
https://<your-host>:8443with direct TLS, and check that the inventory shows the estate you had before the upgrade.
Keep the previous release directory until you are sure you will not go back.
What Happens to the Observation Dataset
The dataset stays in the one DuckDB file under /var/lib/ljvmi/events, and an upgrade does not rewrite it.
The inventory list and Security Exposure read a derived table, inventory_installations. When a release changes how that table is derived, the installation rebuilds it in buckets during the ingestion passes after the start. Until that finishes, inventory reads are computed for each request, which is slower, and Security Exposure shows that it is still preparing. The release notes flag a release that does this.
A change to the rules that derive a value at ingestion, such as the license of an observation or whether an installation is system-wide, applies to observations delivered from then on. It does not rewrite the ones already stored. To apply the new rules to everything, re-ingest the kept deliveries. See Re-ingesting the kept deliveries.
What Happens to the Database
The new release compares the migrations it carries against the migrations your database already records, and applies only the ones that are missing, in order. A release that adds no migration touches nothing. The application never generates schema changes on its own, so migrations remain the only path by which the database changes.
Going Back
Migrations run forward only. Once a migration has run, starting the previous release alone does not undo it, because the older code does not understand the newer database. Without the restored data, the old version refuses to start, and the migration check stops it with Detected applied migration not resolved locally.
To go back:
-
Stop the service:
sudo systemctl stop ljvmi. -
Restore the backup over
/var/lib/ljvmi. -
Point
currentback at the previous release directory:sudo ln -sfn /opt/ljvmi/<previous-release> /opt/ljvmi/current. -
Start the service:
sudo systemctl start ljvmi.
That backup is the entire rollback plan, which is why the procedure takes one before it changes anything.