Skip to main content
CMDashCyber Maturity Dashboard
DocsAdministrationInstalling CMDash on your own servers

Installing CMDash on your own servers

Purpose: install CMDash on a Linux host you run, from a signed license file, and keep it updated and backed up.

A self-hosted install runs the same code as CMDash Cloud on your own hardware, inside your own boundary. It runs on the Enterprise plan, from a signed license file that the install checks offline: it never calls CMDash to verify the license. Enterprise costs the same wherever it runs. To compare this with CMDash Cloud and with running CMDash in your own AWS account, read Choose where CMDash runs.

To get a license, talk to us. Your license appears under Licenses in the customer portal.

System requirements

RequirementMinimumRecommended
Operating systemLinux, x86_64 or arm64A current LTS release
DockerDocker Engine 24 or later with the docker compose v2 pluginThe latest
CPU2 cores4 cores
RAM4 GB8 GB
Free disk (Docker root)10 GB20 GB or more
Ports80 and 443 free for the bundled Caddy edge, plus 3000 and 3001 on 127.0.0.1Set EDGE_HTTP_PORT and EDGE_HTTPS_PORT if the host already serves 80 or 443

You also need a DNS name that points at the host (APP_DOMAIN) and your signed license.json. The installer's preflight checks everything above and stops if something is missing.

What runs on the host

One Docker Compose stack: Postgres, Redis, MinIO and Vault, plus the api, web and worker services, the Caddy edge that terminates TLS, and an updater service that drives in-app updates. A single tenant is created by default.

Your license

The license is a signed license.json. The public key that verifies it is built into the release images, so there is nothing to download or configure. Place it on the host at ./secrets/license/license.json, or upload it later at Settings → License.

Setting in cmdash.envWhat the install does
LICENSE_SERVER unset and LICENSE_SERVER_URL emptyThe default. You supply the license file, and the install makes no call to CMDash.
LICENSE_SERVER=offThe same, even if a URL is set. Upload an offline license issued in the customer portal.
LICENSE_SERVER=onThe install registers with the license server and refreshes its license daily. It needs outbound HTTPS to that server.

If a license expires, the install moves through a grace period to read-only. Reading and exporting your data keep working.

Install

Run these on the host, from deploy/onprem/ in the release bundle.

  1. Copy cmdash.env.example to cmdash.env and fill in every CHANGE_ME. Preflight stops while any is left.
  2. Put your license at ./secrets/license/license.json.
  3. Run ./preflight.sh. It changes nothing, and reports the host, the settings and the license.
  4. Run ./install.sh. It runs preflight, obtains and verifies the images, starts the stack, applies the database schema, creates the storage bucket, waits for the health check and prints your access details.
  5. Open https://<APP_DOMAIN>/ and complete first-run setup. The first account becomes the workspace Owner, and the page asks for the one-time setup token that install.sh printed.

Each release image is verified against the CMDash release signature before it runs. A tag that was moved, a retagged archive or a downgrade is refused.

Sign-in

Single sign-on, SCIM and LDAP work as they do on Enterprise anywhere, against your own identity provider. See SSO, SCIM & LDAP. If the only Owner loses their password on an install with no mail, run ./reset-owner.sh --email <owner> on the host.

Update

Open Settings → Updates and select Apply update. The updater service rolls the api and then the web service and rolls back automatically if the new version fails its health check. A release that needs a database migration is not offered as a one-click update: back up, then set IMAGE_TAG to the new version in cmdash.env and run ./install.sh again. Full detail: Updating CMDash.

The updater service has access to the container runtime on the host. Treat it like root access to that host.

Back up and restore

Backup and recovery are your responsibility on a self-hosted install.

bash
./backup.sh --age-recipient age1...      # or --passphrase-file FILE
./restore.sh backups/<archive>.tar.gz.age --age-identity id.txt
  • backup.sh writes one encrypted archive: the Postgres dump, the MinIO contents, the license and the settings. It refuses to write an unencrypted archive, and it checks the dump can be restored before it finishes.
  • A systemd timer (systemd/cmdash-backup.timer) runs the backup daily. Copy the archives off the host yourself.
  • Back up before every upgrade, and keep the encryption key apart from the archives.
  • Keep CREDENTIAL_ENCRYPTION_KEY with your backups. A restored database cannot use its stored integration credentials without it.
  • Rehearse a restore at least once a quarter.

The backup and recovery policy for self-hosted installs is in Self-hosted backup and recovery.

This page is the product manual, published from the repository at docs/user/admin/install-on-your-servers.md. Customers read the same text inside CMDash under Help. Last updated October 25, 2026.

Installing CMDash on your own servers — CMDash Docs