Upgrading LicenseTrack¶
This guide covers a Docker Compose upgrade while keeping the existing database, uploaded documents, database backups, and Official Extension storage intact.
Do not delete the data volume
Do not run docker compose down -v during an upgrade unless you intentionally want to delete LicenseTrack data. The -v flag removes named volumes, including the /data volume that stores the SQLite database and uploaded documents.
What persists¶
The application container is replaceable. Persistent data lives under /data in the Docker volume mounted by Compose:
/data/licenses.db/data/storage//data/backups//data/plugins/
Startup runs Alembic migrations automatically, so an upgrade normally means replacing the application source/image and starting the container against the same /data volume.
Integrity migrations stop rather than silently discard data when they discover dangling relationships that cannot be repaired safely. If startup reports such an error, keep the pre-upgrade volume backup, do not repeatedly replace the database, and inspect the named table, column, and example row IDs before retrying the upgrade.
Before upgrading¶
Upgrading to 1.1.22¶
This patch includes migrations for non-reusable user IDs, maintenance coverage restoration when unlinking an existing successor, and independently revocable login sessions. They run through the normal startup migration process.
Existing browser sessions require a fresh sign-in after upgrading. Each login has its own sliding expiry; logging out or reaching the inactivity timeout revokes that session without signing out other devices. Browser tabs share activity, and panel scrolling counts as activity. Split API deployments retain in-memory bearer tokens and may require another sign-in after a page reload if the browser cannot send the API session cookie.
Downgrading the session migration removes login-session identities and also requires a fresh sign-in. Keep the full pre-upgrade volume backup for rollback.
From the current install directory, identify the volume mounted at /data:
cd /path/to/LicenseTrack
CID=$(docker compose ps -q license-lifecycle)
DATA_VOL=$(docker inspect "$CID" --format '{{range .Mounts}}{{if eq .Destination "/data"}}{{.Name}}{{end}}{{end}}')
echo "$DATA_VOL"
Back up the full volume:
mkdir -p ~/licensetrack-upgrade-backups
docker run --rm \
-v "$DATA_VOL":/data:ro \
-v "$HOME/licensetrack-upgrade-backups":/backup \
alpine \
sh -c 'tar -czf /backup/licensetrack-data-pre-upgrade-$(date +%Y%m%d-%H%M%S).tar.gz -C /data .'
Also keep a copy of .env:
Normal same-directory upgrade¶
The cleanest upgrade path is to keep the same install directory and Compose project name.
Replace the source files with the new release while keeping the same folder name and .env. Then rebuild and start:
Check health and logs:
docker compose ps
docker compose logs --tail=100 license-lifecycle
curl http://localhost:8080/api/health
The health response should include the expected version:
Log in and smoke-test license listing, document downloads, settings, backup listing, and any configured SMTP/OIDC integrations.
If the install folder changes¶
Docker Compose names volumes from the Compose project name. By default, the project name comes from the folder name. For example:
~/LicenseTrack-1.0.4 -> licensetrack-104_license_lifecycle_data
~/LicenseTrack -> licensetrack_license_lifecycle_data
If you move to a different folder name, Compose may create a new empty volume. The symptom is a startup log that runs every migration from initial_schema, and the app opens with an empty database.
To reuse an existing volume after changing folder/project name, mark the volume as external in docker-compose.yml:
Use the volume name you found before upgrading, for example:
Then start again:
Podman upgrades¶
If you run LicenseTrack with plain podman run, upgrade by replacing the container while reusing the same /data volume.
Identify the current /data volume:
podman inspect licensetrack --format '{{range .Mounts}}{{if eq .Destination "/data"}}{{.Name}}{{end}}{{end}}'
Back up the volume:
mkdir -p ~/licensetrack-upgrade-backups
podman run --rm \
-v license_lifecycle_data:/data:ro \
-v "$HOME/licensetrack-upgrade-backups":/backup \
alpine \
sh -c 'tar -czf /backup/licensetrack-data-pre-upgrade-$(date +%Y%m%d-%H%M%S).tar.gz -C /data .'
Stop and remove only the old container, not the volume:
Build the new image from the release source:
Start the new container with the same volume mounted at /data:
podman run -d --name licensetrack -p 8080:8000 \
--env-file .env \
-v license_lifecycle_data:/data \
license-lifecycle-system:1.1.22
Check health:
If your Podman volume has a different name, substitute it in both -v arguments. Do not use podman volume rm during an upgrade unless you intentionally want to delete persistent data.
If you use podman compose, follow the Docker Compose guidance above. Compose project-name behavior can still change generated volume names when the install folder changes.
Stable project names¶
For new installs, you can avoid folder-name surprises by setting a stable Compose project name before first startup:
Do not add or change COMPOSE_PROJECT_NAME on an existing install unless you also confirm which data volume will be used. Changing it later changes the Compose-generated volume name.
Recovery if an empty database appears¶
If the upgraded container starts with an empty database:
- Stop the new container with
docker compose down. - Do not delete any Docker volumes.
- List available volumes with
docker volume ls. - Inspect old containers to find their
/datavolume:
- Update
docker-compose.ymlto use the correct existing volume as an external volume. - Start again and confirm that the startup logs no longer run the full migration chain from the initial schema.
After upgrading¶
- Confirm
/api/healthreports the expected version. - Confirm the container is healthy and not restarting.
- Review logs for migration errors.
- Log in with an admin account.
- Smoke-test license listing, document access, settings, backup listing, and configured integrations.
- Confirm scheduled database backup and notification settings remain as expected.
When upgrading from 1.1.0 or earlier, a browser may still hold the old SPA shell
under its previous cache policy. If /api/health reports the new version but
the interface still looks or behaves like the old release, perform one hard
refresh or clear that site's cached files. Releases from 1.1.1 onward require
the SPA shell to revalidate, so this should be a one-time transition.