Skip to content

Install

One command, run as root — that's all. A fresh Debian 13 in a dedicated VM is recommended (see Prerequisites), but it works just as well on Ubuntu or alongside other services:

curl -fsSL https://vesana.org/install | bash

If curl is missing (minimal Debian), wget works too:

wget -qO- https://vesana.org/install | bash

As root, without sudo

The installer needs root privileges (Docker, /opt, systemd). On Debian, sudo is often not even installed — so log in as root first: su - (Debian) or sudo -i (Ubuntu), then run the one-liner.

What the installer does

[1/6] Checking system            – architecture, RAM, ports 80/443
[2/6] Installing prerequisites   – openssl/curl, Docker (if needed)
[3/6] Downloading Vesana         – compose file + configuration template
[4/6] Configuration              – server address, license key (optional)
[5/6] Generating secrets         – passwords, encryption key
[6/6] Starting Vesana            – pull images, start stack, wait for health,
                                   schedule the active checker setup

Long steps (Docker install, image download) run quietly in the background — the full output goes to /var/log/vesana-install.log.

You are asked exactly two things:

  1. Address where Vesana should be reachable in the browser (suggested: the detected server IP — Enter accepts it)
  2. License key — Enter skips it (free Community Edition)

Then head to the browser: https://<your-address>/setup starts the setup wizard. The certificate warning on first visit is expected (self-signed certificate).

The installer ends by printing a setup link that carries a one-time code (…/setup?setup_token=…) and the code once more below it. If you open /setup by hand, the wizard asks for that code — you can paste the code or simply the whole link into the field. It is also in .env as VESANA_SETUP_TOKEN. Nobody else can set up the instance in the minutes between installation and completion. Once setup is complete the code no longer matters.

Finding the setup code again

If the installer output is gone, the code is in .env on the server:

grep VESANA_SETUP_TOKEN /opt/vesana/.env

Then open https://<your-address>/setup?setup_token=<code>, or open /setup and enter the code in the field. It stays valid until the setup wizard is complete.

Port 80 or 443 in use

If a web server is already running on the machine (Apache, nginx, a reverse proxy), the installer reports ports 80/443 are already in use in step 1 and offers to run Vesana on other ports — the other service keeps running:

? HTTPS port for Vesana [9443]:
? HTTP port (only redirects to HTTPS) [9080]:

Enter accepts the suggestion (always a port that is free right now; a free standard port stays the suggestion). The address in the next step already includes the port (https://<ip>:9443) — it belongs there, because agents and collectors connect to that address later, too. Leave it out only behind a reverse proxy that listens on 443 itself. If a firewall is active (e.g. ufw), allow the chosen HTTPS port there. At the end you get the setup link and the setup code as usual.

For an install without a terminal the same choice exists as the environment variables VESANA_HTTPS_PORT and VESANA_HTTP_PORT (see Unattended install).

If you answer the port question with n, you can still install Vesana (without starting it) and switch the ports yourself later:

  1. Set other ports in /opt/vesana/.env, for example:

    HTTP_PORT=9080
    HTTPS_PORT=9443
    BASE_URL=https://192.168.1.50:9443
    

    The port belongs in BASE_URL too — agents and collectors connect to that address later. Alternatively stop the other service (e.g. systemctl disable --now apache2) and keep 80/443.

  2. Run the installer again (the same one-liner). It finds the existing .env, leaves the configuration untouched, skips the port check, starts Vesana and ends by printing the setup link with the code and the new port.

If you start the stack by hand with docker compose -f /opt/vesana/docker-compose.prod.yml up -d instead, no link is printed — take the code from .env as described under Finding the setup code again.

Active checker & first network scan

The installation automatically sets up the active checker (Active Collector): active checks like ping/SNMP/HTTP directly from the Vesana server. It runs as a systemd service on the server, outside Docker. For this the installer creates a systemd timer (vesana-ac-autoinstall.timer) that looks every 3 minutes and sets up the service as soon as the setup wizard is finished — typically 1–3 minutes later, across reboots too. Afterwards the timer switches itself off.

On first contact it looks up the reachable networks once and scans up to three small private IPv4 networks (at most /22, e.g. 192.168.1.0/24) once for devices — the results are under Discovery. It never scans public networks on its own (such as the network of a rented server at a hosting provider). If the active checker does not come online within 14 days, this first scan is dropped.

Status and any errors: Admin → Agents & Collectors → Active checker (+ diagnostic log), log of the setup timer: journalctl -u vesana-ac-autoinstall.

Back up the FIELD_ENCRYPTION_KEY

Losing the key = losing data

At the end of step 5 the installer prints the FIELD_ENCRYPTION_KEY. It protects encrypted fields (e.g. SNMP communities) and is deliberately not part of backups. If it is lost, that data is permanently unrecoverable.

Right after installation:

  1. Copy the key from the output (also in /opt/vesana/secrets/)
  2. Store it in a password manager (Bitwarden, 1Password, KeePass)
  3. Additionally keep an offline or separately stored copy

IPv6 (optional)

By default Vesana publishes its ports on IPv4 only. To make it reachable over IPv6 as well, set VESANA_IPV6=true in /opt/vesana/.env (during installation: the environment variable VESANA_IPV6=true) and run the next update. This needs Docker 27 or newer with IPv6 NAT; if Docker cannot do that (too old, rootless, ip6tables disabled), Vesana stays on IPv4 and states the reason in the updater log or the installer. Ports with a fixed address (HTTP_PORT=127.0.0.1:8285) stay unchanged.

Unattended install (automation)

Every question has an environment variable — so the installer runs without a terminal (Ansible, cloud-init, CI):

VESANA_BASE_URL=https://monitoring.example.com \
  bash <(curl -fsSL https://vesana.org/install)
Variable Meaning
VESANA_BASE_URL server address (required for unattended)
VESANA_LICENSE_KEY license key (empty = Community)
VESANA_DIR install directory (default /opt/vesana)
VESANA_REGISTRY_USER / VESANA_REGISTRY_TOKEN private registry (Enterprise)
VESANA_HTTPS_PORT / VESANA_HTTP_PORT other ports than 443/80 (e.g. when a web server uses them)
VESANA_IPV6 true = also publish the ports over IPv6 (default: IPv4 only; needs Docker 27+ with IPv6 NAT)
VESANA_VERSION install a specific version (image tag, e.g. v1.903.0); unset = current released version
VESANA_PG_SIZING default = keep the template's Postgres memory values instead of deriving them from RAM (see Self-hosting)
VESANA_PULSE off = the instance sends no instance pulse (test/throwaway installs)
VESANA_NO_START any value (e.g. 1) = install but do not start
VESANA_NONINTERACTIVE any value = no questions, even when a terminal is present

Re-run

The installer is re-runnable: if /opt/vesana/.env already exists, the configuration is left untouched (no secret rotation; overly open file permissions on .env are tightened to root-only) — it makes sure the stack is running. In doing so it downloads the current compose file and images again; unless VESANA_VERSION is pinned in .env, the instance ends up on the current released version — without the pre-update backup of the GUI updater. So do not use it as an update substitute on a production instance. For a complete reinstall: docker compose -f /opt/vesana/docker-compose.prod.yml down -v (deletes all data!), then rm /opt/vesana/.env and run the one-liner again.

Next