Skip to content

Native Linux installation

LicenseTrack can run directly on a Linux host as a systemd service. This path does not use Docker or Podman.

Supported baseline

  • Debian 13 or Ubuntu 22.04 LTS, x86_64
  • systemd
  • CPython 3.12, 3.13, or 3.14 with the venv, SSL, and SQLite modules
  • curl, tar, and standard GNU/Linux user-management tools
  • A TLS-terminating reverse proxy for network-reachable production use

The official native release archive contains the compiled frontend and offline wheelhouses for all supported Python ABIs. The installer selects the matching runtime and wheelhouse automatically, so Node.js is not required when using that archive.

Distribution Python

Debian 13 supplies supported CPython 3.13 packages; install its matching venv package before running the installer. Ubuntu 22.04 does not ship a supported LicenseTrack Python version in its standard repositories, so install and maintain CPython 3.12, 3.13, or 3.14 according to your organisation's package policy. Do not replace /usr/bin/python3; system tools should continue using the distribution Python.

Verify the interpreter you intend to use (this example uses Python 3.12):

python3.12 --version
python3.12 -c 'import sqlite3, ssl, venv; print("Python prerequisites OK")'

Install from the native release archive

Download both the native archive and SHA256SUMS from the GitHub release. Verify the archive before extracting it:

sha256sum --check SHA256SUMS
tar -xzf licensetrack-native-<version>-linux-x86_64.tar.gz
cd licensetrack-native-<version>-linux-x86_64
./install.sh --verify-only
sudo ./install.sh

The installer offers two modes:

Mode Intended use Configuration
Standard (recommended) Most production installations Prompts only for the browser-facing URL, reverse-proxy confirmation when needed, and initial local admin password. Uses safe runtime defaults and binds to 127.0.0.1:8000.
Advanced Custom ports, troubleshooting, larger limits, or isolated test environments Also prompts for bind address, port, log level, session lifetime, upload/extension limits, allowed extensions, API documentation exposure, session-cookie behavior, and test-only OIDC network allowances.

Press Enter at the mode prompt to choose Standard, or select a mode explicitly:

sudo ./install.sh --standard
sudo ./install.sh --advanced

Both modes generate the JWT signing secret automatically and protect the resulting environment file. SMTP credentials and OIDC provider/client details remain application-managed settings: configure them after first login under Settings. Advanced mode can enable plain-HTTP or private-network OIDC discovery for an isolated test environment, but those allowances should remain disabled in production.

After installation:

sudo licensetrack status
sudo licensetrack doctor
sudo licensetrack logs

Install from GitHub's source archive

The automatic tag ZIP is source-only. Its installer builds the production frontend on the server, so this path additionally requires Node.js 22 and npm:

unzip LicenseTrack-<version>.zip
cd LicenseTrack-<version>
sudo ./install.sh

Use the native release archive for production when possible. It is built and checksummed by the release workflow and does not install frontend build tooling on the server.

Unattended installation

Store the initial admin password in a root-readable file and supply the public URL explicitly:

sudo install -m 600 /dev/null /root/licensetrack-admin-password
sudo editor /root/licensetrack-admin-password

sudo ./install.sh \
  --yes \
  --network-mode reverse-proxy \
  --public-url https://licenses.example.com \
  --admin-password-file /root/licensetrack-admin-password

sudo rm /root/licensetrack-admin-password

The explicit network mode confirms that an existing reverse proxy will forward the public URL to LicenseTrack's loopback listener. An unattended install rejects a non-local public URL with a loopback bind unless --network-mode reverse-proxy is present.

The installer intentionally does not accept the password as a command-line argument, where it would be visible in process listings and shell history.

--yes selects Standard mode when no mode is supplied. An unattended Advanced install accepts the same settings as flags instead of prompting. For example, this isolated HTTP test configuration binds to the LAN and permits a private plain-HTTP identity provider:

sudo ./install.sh \
  --advanced \
  --yes \
  --network-mode direct-network \
  --bind-host 0.0.0.0 \
  --port 8000 \
  --public-url http://192.168.0.247:8000 \
  --allow-http-oidc-discovery \
  --allow-private-oidc-discovery \
  --no-session-cookie-secure \
  --admin-password-file /root/licensetrack-admin-password

direct-network defaults the bind address to 0.0.0.0 when --bind-host is omitted, but it never opens the host firewall. Restrict direct access to an isolated or otherwise trusted network.

Run ./install.sh --help for every Advanced automation flag. Command-line flags contain no secret values; application integration secrets are entered later through LicenseTrack's Settings UI.

Filesystem layout

Purpose Path
Versioned releases /opt/licensetrack/releases/<version>/
Active release link /opt/licensetrack/current
SQLite database /var/lib/licensetrack/licenses.db
Uploaded documents /var/lib/licensetrack/storage/
Official Extension packages /var/lib/licensetrack/plugins/
Database backups /var/lib/licensetrack/backups/
Upgrade snapshots /var/backups/licensetrack/upgrades/
Protected environment /etc/licensetrack/licensetrack.env
Install state /etc/licensetrack/install.json
systemd unit /etc/systemd/system/licensetrack.service

Application files are root-owned. The service runs as the unprivileged licensetrack account and can write only its persistent data paths. Journald captures application output.

Installation, upgrade, rollback, backup orchestration, and removal require root because they manage systemd, accounts, protected configuration, and root-owned application paths. The running web application does not run as root:

  • release code and its virtual environment are root-owned and not writable by the service account;
  • /etc/licensetrack/licensetrack.env is root-owned, readable by the service group, and not service-writable;
  • /var/lib/licensetrack is service-owned and contains the mutable database, documents, application backups, and Official Extension data;
  • native upgrade snapshots under /var/backups/licensetrack are root-only; and
  • the systemd service uses NoNewPrivileges, PrivateTmp, ProtectSystem, ProtectHome, and a restrictive UMask.

An application compromise can expose or alter LicenseTrack data and read the runtime secrets required by the service. These boundaries prevent that access from automatically granting permission to replace application code, configuration, the systemd unit, or the operator command; they are not a hostile-code sandbox.

Reverse proxy and HTTPS

The default loopback binding is deliberate. Put nginx, Caddy, or another TLS-terminating reverse proxy in front of 127.0.0.1:8000. The public URL entered during installation becomes CORS_ORIGINS; HTTPS URLs also enable secure session cookies.

When an interactive install combines a non-local public URL with the loopback bind, it explains that this is reverse-proxy mode and requires confirmation. For unattended installation, declare --network-mode reverse-proxy explicitly. licensetrack doctor reports the effective bind, public URL, and reachability mode; installations upgraded from an older state receive a warning until the operator confirms that the inferred reverse-proxy arrangement is intentional.

Do not expose port 8000 directly to an untrusted network. Route both the SPA and /api/* paths through the same public origin.

Service operations

sudo licensetrack start
sudo licensetrack stop
sudo licensetrack restart
sudo licensetrack status
sudo licensetrack logs
sudo licensetrack doctor
sudo licensetrack backup
sudo licensetrack version

The backup command creates the same WAL-safe SQLite backup format used by the application. It does not include uploaded documents. Upgrade snapshots are separate and include the managed data directory, configuration, and any configured external document-storage path. The doctor command reports document record, available-file, and missing-file counts so a database-only restore can be reconciled with managed storage without deleting metadata.

For data-retention choices and complete host cleanup, see Native Linux removal.

First login

Open the public URL, sign in as admin, and use the password supplied during installation. Continue with First launch & login.