> For the complete documentation index, see [llms.txt](https://adatrack.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://adatrack.gitbook.io/docs/documentation/getting-started/adatrack-ctl.md).

# adatrack-ctl CLI

`adatrack-ctl` is the command-line management tool for self-hosted AdaTrack installations. It handles database setup, schema migrations, backups, health monitoring, and configuration — everything you need to install, maintain, and upgrade your instance.

The tool ships as a standalone binary alongside the main AdaTrack server. It is also included in the Docker image.

***

## Installation

### Download

Pre-built binaries are available on every [GitHub Release](https://github.com/AdaTrack/adatrack/releases) for Linux, macOS, and Windows:

```bash
# Example: download for Linux amd64
curl -LO https://github.com/AdaTrack/adatrack/releases/latest/download/adatrack-ctl-linux-amd64
chmod +x adatrack-ctl-linux-amd64
sudo mv adatrack-ctl-linux-amd64 /usr/local/bin/adatrack-ctl
```

### Docker

If you are running the AdaTrack Docker image, `adatrack-ctl` is already included:

```bash
docker exec adatrack ./adatrack-ctl status
```

***

## Connecting to the Database

Every command that interacts with the database accepts connection flags. You can provide a full connection URL or individual components:

```bash
# Full URL
adatrack-ctl --db-url="postgres://user:pass@localhost:5432/iot_platform?sslmode=disable" status

# Individual flags
adatrack-ctl --db-host=localhost --db-port=5432 --db-name=iot_platform \
  --db-user=postgres --db-password=secret --db-sslmode=prefer status
```

Connection parameters can also be set via environment variables: `DATABASE_URL`, `DB_HOST`, `DB_PORT`, `DB_NAME`, `DB_USER`, `DB_PASSWORD`, `DB_SSLMODE`.

### Global Flags

| Flag              | Env Var        | Description                             |
| ----------------- | -------------- | --------------------------------------- |
| `--db-url`        | `DATABASE_URL` | Full PostgreSQL connection string       |
| `--db-host`       | `DB_HOST`      | Database host (default: `localhost`)    |
| `--db-port`       | `DB_PORT`      | Database port (default: `5432`)         |
| `--db-name`       | `DB_NAME`      | Database name (default: `iot_platform`) |
| `--db-user`       | `DB_USER`      | Database user (default: `postgres`)     |
| `--db-password`   | `DB_PASSWORD`  | Database password                       |
| `--db-sslmode`    | `DB_SSLMODE`   | SSL mode (default: `prefer`)            |
| `--yes`, `-y`     |                | Skip confirmation prompts               |
| `--verbose`, `-v` |                | Show detailed output                    |
| `--dry-run`       |                | Preview changes without executing them  |

***

## Commands

### install

Performs a complete fresh installation of the AdaTrack database schema. Use this the first time you set up your instance.

```bash
adatrack-ctl install --create-extensions
```

What it does:

1. Connects to your PostgreSQL instance and runs pre-flight validation checks.
2. Optionally creates required extensions (TimescaleDB, PostGIS, uuid-ossp) with `--create-extensions`.
3. Applies all schema migrations in order.
4. Verifies key tables, hypertable configuration, and extension status.

| Flag                  | Description                                                                                   |
| --------------------- | --------------------------------------------------------------------------------------------- |
| `--create-extensions` | Create TimescaleDB, PostGIS, and uuid-ossp if not already installed                           |
| `--create-db`         | Create the database itself if it does not exist                                               |
| `--create-admin`      | Create an admin user after schema installation (solves the first-login bootstrapping problem) |
| `--admin-username`    | Admin username (prompted interactively if `--create-admin` is set and this is omitted)        |
| `--admin-email`       | Admin email address (prompted if omitted)                                                     |
| `--admin-password`    | Admin password (prompted if omitted)                                                          |

**One-command bootstrap** — set up the database and create your first admin in a single step:

```bash
adatrack-ctl install --create-extensions --create-admin \
  --admin-username myadmin \
  --admin-email admin@mycompany.com \
  --admin-password 'Str0ng!AdminPass'
```

> If you have already run `install` and want to apply newer migrations after an upgrade, use `adatrack-ctl upgrade` instead.

***

### upgrade

Detects the current schema version and applies any pending migrations.

```bash
adatrack-ctl upgrade
```

If a previous migration failed and left the schema in a "dirty" state, use `--force` to clear the dirty flag before retrying:

```bash
adatrack-ctl upgrade --force
```

***

### rollback

Reverts schema migrations. You must specify either a step count or a target version.

```bash
# Roll back the last 2 migrations
adatrack-ctl rollback --steps=2

# Roll back to a specific version
adatrack-ctl rollback --target=20260301000000
```

> Rolling back migrations may permanently delete data. Always back up your database first with `adatrack-ctl backup`.

***

### status

Displays the current state of your database: schema version, pending migrations, installed extensions, and table count.

```bash
adatrack-ctl status
```

Example output:

```
adatrack-ctl v1.0.0

─ Connecting
  ✓ Connected to postgres@localhost:5432/iot_platform

─ Schema Status
  Current version      20260331100000 (create_system_properties)
  Latest available     20260331100000 (create_system_properties)
  Pending migrations   ✓ 0 — up to date

─ Database Info
  PostgreSQL           16.2
  TimescaleDB          2.14.0
  PostGIS              3.4.1
  Hypertable           readings ✓
  Tables               24
```

***

### validate

Runs all pre-flight checks against your database and host system without making any changes. Use this to verify that your environment meets AdaTrack's requirements before installing.

```bash
adatrack-ctl validate
```

**Database checks** (required — block install on failure):

* PostgreSQL version (15+)
* TimescaleDB, PostGIS, and uuid-ossp extension availability
* Table creation privileges
* Max connections and shared buffers

**Host checks** (advisory — warnings only, Linux only):

* UDP receive/send buffer sizes
* Network backlog setting
* Open file limit

***

### uninstall

Removes all AdaTrack database objects by reverting all migrations. This permanently deletes all data.

```bash
adatrack-ctl uninstall --force
```

For safety, you must type the database name to confirm unless you pass both `--force` and `--yes`.

| Flag                | Description                                                |
| ------------------- | ---------------------------------------------------------- |
| `--drop-extensions` | Also remove TimescaleDB, PostGIS, and uuid-ossp extensions |
| `--force`           | Skip typed confirmation (requires `--yes` as well)         |

***

### backup

Creates a database backup using `pg_dump` with TimescaleDB-aware defaults.

```bash
adatrack-ctl backup --output=adatrack-backup.dump
```

The backup is created in PostgreSQL's custom format (compressed, supports selective restore).

| Flag                 | Description                                                           |
| -------------------- | --------------------------------------------------------------------- |
| `--output`, `-o`     | Output file path (default: auto-generated with version and timestamp) |
| `--format`           | `custom` (default), `plain`, or `directory`                           |
| `--exclude-readings` | Skip the `readings` hypertable (can be very large)                    |
| `--data-only`        | Back up data without schema definitions                               |
| `--compress`         | Compression level 0-9 (default: 6)                                    |

> Requires `pg_dump` to be installed on your system.

***

### restore

Restores a database from a backup file created by `adatrack-ctl backup`.

```bash
adatrack-ctl restore --input=adatrack-backup.dump
```

| Flag            | Description                                                            |
| --------------- | ---------------------------------------------------------------------- |
| `--input`, `-i` | Path to backup file (required)                                         |
| `--clean`       | Drop existing objects before restore (default: true)                   |
| `--data-only`   | Restore data only (schema must already exist)                          |
| `--no-owner`    | Skip ownership restoration (useful when restoring to a different user) |
| `--tables`      | Comma-separated list of specific tables to restore                     |

After a restore, run `adatrack-ctl upgrade` to apply any migrations that are newer than the backup.

> Requires `pg_restore` to be installed on your system.

***

### init-config

Generates a starter `.env` configuration file with all supported environment variables, grouped by feature area with documentation comments.

```bash
adatrack-ctl init-config --output=.env
```

In interactive mode (the default), the tool prompts you for essential values like the database connection, JWT secret, and server ports. Non-interactive mode (`--yes`) writes all defaults without prompting.

| Flag             | Description                                                              |
| ---------------- | ------------------------------------------------------------------------ |
| `--output`, `-o` | Output file path (default: `.env`)                                       |
| `--merge`        | Add missing keys to an existing file without overwriting existing values |
| `--minimal`      | Only include required variables                                          |

***

### doctor

Runs a comprehensive health check across your database and host system. Use this to diagnose issues with a running instance.

```bash
adatrack-ctl doctor
```

The doctor checks the following categories:

* **Schema:** Migration version, dirty state, table integrity
* **TimescaleDB:** Hypertable status, chunk count, compression
* **Storage:** Database size, table bloat (dead tuples)
* **Connections:** Active vs. max connections, long-running queries, idle transactions
* **Performance:** Cache hit ratio, index usage
* **Host:** UDP buffer sizes, open file limits (Linux only)

| Flag         | Description                                                                |
| ------------ | -------------------------------------------------------------------------- |
| `--category` | Run only specific categories (comma-separated, e.g., `schema,timescaledb`) |
| `--json`     | Output results in JSON format (for monitoring integration)                 |

***

### version

Prints the tool version and information about embedded migrations.

```bash
adatrack-ctl version
```

***

### license

Manages self-hosted license keys. License commands **do not require a database connection** — they operate on license files and environment variables only.

#### license status

Displays the current license tier, resource limits, expiry, and validation status.

```bash
adatrack-ctl license status
```

Example output (no license installed):

```
─ License Status

  Tier                   Community
  Status                 community
  Message                No license key provided. Community Edition limits are active.

─ Resource Limits

  RESOURCE                LIMIT
  ──────────────────────  ───────
  Devices                 5
  Device Profiles         3
  ...
```

| Flag     | Description           |
| -------- | --------------------- |
| `--json` | Output in JSON format |

#### license install

Installs a license key. The argument is auto-detected: if a file exists at the given path, it reads the JWT from the file; otherwise it treats the argument as an inline JWT string.

```bash
# Install from a file
adatrack-ctl license install /path/to/license.lic

# Install an inline JWT
adatrack-ctl license install "eyJhbGci..."

# Store directly in .env instead of a separate file
adatrack-ctl license install "eyJhbGci..." --inline
```

The command verifies the Ed25519 signature, displays a summary, and writes the license to disk with 0600 permissions.

| Flag             | Description                                                                                              |
| ---------------- | -------------------------------------------------------------------------------------------------------- |
| `--license-path` | Destination file path (default: `/opt/adatrack/config/.adatrack.lic`)                                    |
| `--inline`       | Write the JWT directly as `ADATRACK_LICENSE_KEY` in the `.env` file instead of saving to a separate file |

#### license inspect

Decodes a license JWT **without verifying the signature** and displays all claims. Useful for examining a license before installing it.

```bash
adatrack-ctl license inspect /path/to/license.lic
```

#### license remove

Removes the installed license, reverting the instance to Community Edition.

```bash
adatrack-ctl license remove
```

This deletes the `.adatrack.lic` file (if present) and comments out `ADATRACK_LICENSE_KEY` and `ADATRACK_LICENSE_FILE` in the `.env` file.

***

### user

Manages user accounts. User commands **require a database connection** (same `--db-*` flags as other commands). The server does not need to be running.

#### user list

Lists all users in a formatted table.

```bash
adatrack-ctl user list

# Filter by role
adatrack-ctl user list --role ADMIN
```

| Flag     | Description                                   |
| -------- | --------------------------------------------- |
| `--role` | Filter by role: `USER`, `SUPPORT`, or `ADMIN` |
| `--json` | Output in JSON format                         |

#### user create

Creates a new user account. The account is created as pre-activated (`is_active = true`), bypassing the OTP/recaptcha registration flow.

```bash
# Interactive mode (prompts for missing fields)
adatrack-ctl user create

# Non-interactive mode
adatrack-ctl user create \
  --username jsmith \
  --email john@example.com \
  --password 'MyStr0ng!Pass' \
  --role USER \
  --yes
```

Password validation enforces the same rules as the web registration flow: minimum 10 characters, must include uppercase, lowercase, number, and special character.

| Flag         | Description                                                     |
| ------------ | --------------------------------------------------------------- |
| `--username` | Username (3-30 chars, letters/numbers/underscores/hyphens only) |
| `--email`    | Email address                                                   |
| `--password` | Password (prompted securely if omitted)                         |
| `--role`     | Role: `USER` (default), `SUPPORT`, or `ADMIN`                   |
| `--json`     | Output created user as JSON                                     |

#### user get

Displays detailed information about a user. The argument is resolved flexibly: if it parses as a UUID, lookup by ID; otherwise, lookup by username.

```bash
adatrack-ctl user get jsmith
adatrack-ctl user get e5f6g7h8-1234-5678-9abc-def012345678
```

| Flag     | Description           |
| -------- | --------------------- |
| `--json` | Output in JSON format |

#### user disable / user enable

Toggles the `is_active` flag on a user account. Disabled users cannot log in.

```bash
adatrack-ctl user disable jsmith
adatrack-ctl user enable jsmith
```

#### user reset-password

Force-sets a new password for a user. Directly updates the password hash in the database — does not send an email.

```bash
adatrack-ctl user reset-password jsmith --password 'NewStr0ng!Pass'
```

| Flag         | Description                                 |
| ------------ | ------------------------------------------- |
| `--password` | New password (prompted securely if omitted) |

#### user delete

Permanently deletes a user account. Requires typed confirmation (you must type the username to confirm).

```bash
adatrack-ctl user delete jsmith
```

Resources owned by the deleted user (devices, profiles, geofences, alert rules, dashboards, workflows, etc.) become unowned. User preferences and subscription records are deleted.

***

### user role

Manages user roles and the RBAC permission matrix.

#### user role list

Displays all available roles and their assigned permissions.

```bash
adatrack-ctl user role list
```

#### user role set

Changes a user's role. Valid roles: `USER`, `SUPPORT`, `ADMIN`.

```bash
adatrack-ctl user role set jsmith ADMIN
```

***

### tiles

Manages self-hosted OpenStreetMap tile data for air-gapped map rendering. Tiles are stored as [PMTiles](https://github.com/protomaps/PMTiles) archives — a single-file format containing vector tiles for a geographic region.

#### tiles download

Extracts tiles for a region from the [Protomaps](https://protomaps.com/) daily planet build using HTTP range requests. Only the tiles within the region's bounding box are transferred — you never download the full 120 GB planet file.

```bash
# Download US region (~8.5 GB)
adatrack-ctl tiles download --region=united-states

# Download low-zoom world base (~100 MB) for global coverage
adatrack-ctl tiles download --region=world-base

# List all available regions
adatrack-ctl tiles download --region=list

# Import a pre-downloaded file (for air-gapped environments)
adatrack-ctl tiles download --file=/path/to/region.pmtiles
```

| Flag          | Description                                                        |
| ------------- | ------------------------------------------------------------------ |
| `--region`    | Region name to download (use `list` to see all options)            |
| `--file`      | Import a local `.pmtiles` file instead of downloading              |
| `--data-path` | Tile data directory (default: `./data/tiles` or `TILES_DATA_PATH`) |
| `--maxzoom`   | Maximum zoom level, lower = smaller file (default: `14`)           |
| `--threads`   | Parallel download threads (default: `4`)                           |

20 regions are available, from continents (Europe, Asia, Africa) to individual countries (United States, United Kingdom, Germany, Japan, etc.).

#### tiles list

Shows installed tilesets with name, size, and file path.

```bash
adatrack-ctl tiles list

# Show all downloadable regions instead
adatrack-ctl tiles list --available
```

#### tiles status

Displays a summary of the tile data directory: total size, tileset count, and whether font/sprite assets are installed.

```bash
adatrack-ctl tiles status
```

Example output:

```
─ Tile Server Status
  Data path              /data/tiles
  Total size             8274 MB
  Tilesets               2
    - world-base (42 MB)
    - united-states (8172 MB)
  Fonts                  ✓ (12 entries)
  Sprites                ✗ (not installed)
```

#### tiles remove

Removes a tileset file from disk.

```bash
adatrack-ctl tiles remove --region=united-states
```

#### tiles download-assets

Downloads universal font glyphs and sprite sheets for map styling. These are region-independent and only need to be downloaded once.

```bash
adatrack-ctl tiles download-assets
```

> **Note:** Font glyphs are automatically fetched and cached on first map load if the server has internet access. This command is primarily for pre-populating the cache in air-gapped environments.

***

### plugin

Manages compiled and scripted plugins from the command line. Plugin commands **require a database connection** (same `--db-*` flags as other commands). The server does not need to be running for most operations.

#### plugin list

Lists all registered plugins with their current state, type, and license requirements.

```bash
adatrack-ctl plugin list
```

Example output:

```
  ID              TYPE       STATE     LICENSE           VERSION
  ──────────────  ─────────  ────────  ────────────────  ───────
  chatbot         compiled   enabled   plugin:chatbot    1.0.0
  fleet-health    scripted   disabled  —                 0.2.1
```

| Flag     | Description           |
| -------- | --------------------- |
| `--json` | Output in JSON format |

#### plugin status

Shows detailed information about a specific plugin: manifest, capabilities, current state, health, and configuration summary.

```bash
adatrack-ctl plugin status chatbot
```

| Flag     | Description           |
| -------- | --------------------- |
| `--json` | Output in JSON format |

#### plugin enable

Enables a plugin. If the plugin declares a license requirement, the license is validated before enabling.

```bash
adatrack-ctl plugin enable chatbot
```

What happens on enable:

1. License check (if the plugin requires one).
2. Database migrations are applied (if any).
3. Plugin is initialized and started.
4. Extension points are registered.

> **Note:** The plugin starts immediately if the server is running. If the server is stopped, the plugin will start on next server launch.

#### plugin disable

Disables a running plugin. All registered extension points (routes, cron jobs, event hooks, etc.) are removed. Plugin data is preserved in the database.

```bash
adatrack-ctl plugin disable chatbot
```

#### plugin config

View or update plugin configuration values.

```bash
# View current configuration
adatrack-ctl plugin config chatbot

# Set a single value
adatrack-ctl plugin config chatbot --set enable_telegram=true

# Set multiple values
adatrack-ctl plugin config chatbot \
  --set enable_telegram=true \
  --set external_base_url=https://track.example.com
```

Sensitive fields (marked `writeOnly` in the plugin's schema) are displayed as masked values (`••••••••`) when viewing.

| Flag     | Description                                                              |
| -------- | ------------------------------------------------------------------------ |
| `--set`  | Set a configuration key=value pair. Can be repeated for multiple values. |
| `--json` | Output current configuration in JSON format                              |

#### plugin health

Runs a plugin's self-diagnostic. Reports healthy or unhealthy with diagnostic details.

```bash
adatrack-ctl plugin health chatbot
```

Example output:

```
Plugin: chatbot (v1.0.0)
State:  enabled
Health: ✓ healthy
  Database connectivity:  ✓
  Telegram webhook:       ✓ registered
  Slack connection:       ✗ not configured
```

***

## Typical Workflows

### First-time Setup

```bash
# 1. Generate a configuration file
adatrack-ctl init-config --output=.env

# 2. Edit .env — set DB_PASSWORD, JWT_SECRET, etc.

# 3. Validate your database environment
adatrack-ctl validate

# 4. Install the schema and create the first admin user
adatrack-ctl install --create-extensions --create-admin

# 5. Start AdaTrack
./adatrack
```

Or in a single non-interactive command for scripted deployments:

```bash
adatrack-ctl install --create-extensions --create-admin \
  --admin-username myadmin \
  --admin-email admin@mycompany.com \
  --admin-password 'Str0ng!AdminPass' \
  --yes
```

### Upgrading to a New Version

```bash
# 1. Download the new adatrack and adatrack-ctl binaries

# 2. Back up your database
adatrack-ctl backup --output=pre-upgrade-backup.dump

# 3. Check what migrations are pending
adatrack-ctl status

# 4. Apply the migrations
adatrack-ctl upgrade

# 5. Start the new version
./adatrack
```

### Setting Up Self-Hosted Maps

```bash
# 1. Download the low-zoom world base (~100 MB)
adatrack-ctl tiles download --region=world-base

# 2. Download your regional tiles
adatrack-ctl tiles download --region=united-states

# 3. Verify
adatrack-ctl tiles status
```

The map renders immediately — no server restart required.

### Managing Users & Licenses

```bash
# Check current license status
adatrack-ctl license status

# Install a new license
adatrack-ctl license install /path/to/license.lic

# Create a new user
adatrack-ctl user create --username jsmith --email john@example.com --role USER

# Promote a user to admin
adatrack-ctl user role set jsmith ADMIN

# List all admin users
adatrack-ctl user list --role ADMIN

# Disable a user account
adatrack-ctl user disable jsmith
```

### Managing Plugins

```bash
# List all plugins
adatrack-ctl plugin list

# Enable the chatbot plugin (requires Standard license with plugin:chatbot feature)
adatrack-ctl plugin enable chatbot

# Configure Telegram integration
adatrack-ctl plugin config chatbot --set enable_telegram=true
adatrack-ctl plugin config chatbot --set external_base_url=https://track.example.com

# Check plugin health
adatrack-ctl plugin health chatbot

# Disable a plugin (data is preserved)
adatrack-ctl plugin disable chatbot
```

### Diagnosing Issues

```bash
# Quick health check
adatrack-ctl doctor

# Export diagnostics as JSON for support
adatrack-ctl doctor --json > diagnostics.json
```

***

### Still Need Help?

Check out our [Troubleshooting Guide](https://github.com/AdaTrack/adatrack_platform/tree/main/docs/gitbook/help/troubleshooting.md) or join our [Discord community](https://github.com/AdaTrack/adatrack_platform/tree/main/docs/gitbook/help/support.md).
