Skip to content

Install on a VM (Debian/Ubuntu)

This guide installs the controller on a plain VM (or bare-metal host) from the Tessera apt repository. It runs as a systemd service, tessera-controller, backed by PostgreSQL.

For containers use the image registry.tessera.company/tessera/controller (Docker Compose / Kubernetes); this page is the VM path.

  • Debian 12 or Ubuntu 22.04+ (amd64), root / sudo.
  • PostgreSQL 16+ (local or managed).
  • Ports: 8443 for the web console + proxy (behind your firewall or a reverse proxy).

See System requirements for sizing.

Install PostgreSQL 16 or newer — the distro’s default package may be older, so follow the official PostgreSQL install guide for your OS. Then create the database and user (generate a password with openssl rand -hex 16):

Terminal window
sudo -u postgres psql -c "CREATE USER tessera WITH PASSWORD 'CHANGE_ME';"
sudo -u postgres psql -c "CREATE DATABASE tessera OWNER tessera;"

Migrations apply automatically on first start.

Terminal window
curl -fsSL https://packages.tessera.company/apt/tessera.gpg.asc \
| sudo gpg --dearmor -o /usr/share/keyrings/tessera.gpg
echo "deb [signed-by=/usr/share/keyrings/tessera.gpg] https://packages.tessera.company/apt stable main" \
| sudo tee /etc/apt/sources.list.d/tessera.list
Terminal window
sudo apt update
sudo apt install tessera-controller

apt asks for confirmation before installing — the controller is not installed silently.

On first install the encryption keys (TESSERA_ENC_KEY, TESSERA_JWT_SECRET) are generated automatically into /etc/tessera/tessera.secret (root-only). You never set them by hand.

Edit /etc/tessera/tessera.conf and set at least the database connection:

TESSERA_DATABASE_URL=postgres://tessera:CHANGE_ME@localhost/tessera?sslmode=disable
# External URL clients use (include the scheme) — needed for OIDC redirects and links:
TESSERA_PUBLIC_URL=https://tessera.example.com

The full list of options is in Configuration. Do not put the encryption keys here — they live in tessera.secret.

Terminal window
sudo systemctl enable --now tessera-controller
systemctl status tessera-controller --no-pager
journalctl -u tessera-controller -n 30 --no-pager

You should see database connected, migrations applied, and the server listening on :8443.

Open https://<your-server>:8443. On a fresh database the controller bootstraps a default admin — log in as admin / admin and change the password immediately.

The controller always serves HTTPS. In a dev/test setup it presents a self-signed certificate (your browser warns once). For production, front it with a reverse proxy that terminates TLS — see TLS behind nginx.

The controller listens on HTTPS at :8443 (self-signed if no cert is set), so nginx proxies to https://127.0.0.1:8443 with verification off, and WebSocket upgrade must be forwarded (the /connect tunnel). Put this in the http block once:

map $http_upgrade $connection_upgrade { default upgrade; '' close; }

Then the server block (Let’s Encrypt terminating TLS):

server { listen 80; server_name tessera.example.com; return 301 https://$host$request_uri; }
server {
listen 443 ssl;
server_name tessera.example.com;
ssl_certificate /etc/letsencrypt/live/tessera.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/tessera.example.com/privkey.pem;
proxy_ssl_verify off; # controller uses a self-signed cert internally
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 3600s; # long-lived SSH / DB sessions
location /metrics { deny all; } # keep metrics internal
location / { proxy_pass https://127.0.0.1:8443; }
}

Set TESSERA_PUBLIC_URL=https://tessera.example.com in tessera.conf so OIDC redirects and links use the public URL.

Upgrades are a planned action, never automatic — an upgrade restarts the controller and drops active sessions. Back up tessera.secret, PostgreSQL, and /var/lib/tessera. The what/why/how — including restore — is in Backups & upgrades.

Terminal window
sudo systemctl disable --now tessera-controller
sudo apt-get purge tessera-controller
# leftovers not owned by the package (only for a full wipe — irreversible):
sudo rm -f /etc/tessera/tessera.secret # encryption keys → creds become unrecoverable
sudo rm -rf /var/lib/tessera # recordings + SSH host key
sudo -u postgres psql -c "DROP DATABASE IF EXISTS tessera;"