Skip to content
Security hardening, live updates and lease fixes
Verlocx

Setup guide

From an empty Ubuntu server to the first deployed VM. Paths below use /opt/verlocx — any folder works.

Requirements

WhatDetails
ServerUbuntu 24.04 LTS · 4 vCPU · 8 GB RAM · 40 GB disk (more for the database over time)
SoftwareDocker Engine with the compose plugin · PostgreSQL 16
Name & certificateA DNS name for the portal (e.g. verlocx.example.com) and a TLS certificate for it
HypervisorProxmox VE — an API token (recommended) or an admin account such as root@pam
Directory (optional)An Active Directory account allowed to join computers to the domain
NetworkOutbound internet during the build (npm and Rust packages); the rules on the firewall page
1

Install PostgreSQL and create the database

shell
apt update && apt install -y postgresql-16 postgresql-client-16sudo -u postgres psql -c "CREATE ROLE verlocx LOGIN PASSWORD 'choose-a-password';"sudo -u postgres psql -c "CREATE DATABASE verlocx OWNER verlocx;"
2

Let the containers reach PostgreSQL

The portal runs in a container and connects to the host through host.docker.internal. Postgres must listen beyond localhost and accept the Docker networks — and the firewall must let them in, but nobody else.

shell
sed -i "s/^#\?\s*listen_addresses\s*=.*/listen_addresses = '*'/" /etc/postgresql/16/main/postgresql.confecho "host    verlocx    verlocx    172.16.0.0/12    scram-sha-256" >> /etc/postgresql/16/main/pg_hba.confsystemctl restart postgresqlufw allow from 172.16.0.0/12 to any port 5432 proto tcp comment 'verlocx portal -> postgres'
3

Put the release in place

/opt/verlocxfiles
/opt/verlocx├── docker-compose.yml     # portal + backend├── portal/                # the portal (with .env.local)├── backend/               # the backend (with config.toml and its keys)├── agent-release/         # the signed agent build the portal serves for self-updates└── traefik/               # reverse proxy: docker-compose.yml, certs/, dynamic/tls.yml
4

Configure the portal

Create portal/.env.local. The minimum is below; every variable is explained in Configuration.

portal/.env.local.env
DATABASE_URL=postgres://verlocx:[email protected]:5432/verlocxVERLOCX_DB_ENCRYPTION_KEY=          # openssl rand -base64 32 — back it up!ROOT_PASSWORD=                    # local admin login until directory sign-in is set upVERLOCX_BACKEND_URL=wss://verlocx_backend:8788/ws/portalVERLOCX_PORTAL_SECRET=              # openssl rand -hex 32 — the same value as portal_secret in the backend configVERLOCX_PUBLIC_BASE_URL=https://verlocx.example.comVERLOCX_VNC_PUBLIC_BASE=wss://verlocx.example.comAGENT_RELEASE_DIR=/app/agent-release
Keep VERLOCX_DB_ENCRYPTION_KEY safe. It decrypts the stored domain-join password, cluster tokens and SMTP credentials. Lose it and those have to be entered again; change it and they can't be read.
5

Configure the backend

backend/config.tomlTOML
listen            = "0.0.0.0:8787"             # agents + browser console relaysportal_listen     = "0.0.0.0:8788"             # the portal only — not publishedportal_secret     = "…"                        # the same value as VERLOCX_PORTAL_SECRETallow_bootstrap_enrollment = false             # agents enroll with one-time tokens onlysecret_key_path   = "server.key"               # created on first startpublic_key_path   = "server.pub"               # copy this into every agent configtls_cert_path     = "cert.pem"                 # created (self-signed) if missingtls_key_path      = "tls.key"agents_store_path = "registered_agents.toml"   # enrolled agents

On first start the backend creates server.key / server.pub. The public key is what every agent pins — back up both files together with registered_agents.toml.

No shared secret in your templates. Each VM Verlocx clones gets a one-time enrollment token in its SMBIOS, so templates carry no secret. portal_secret is the portal's alone and opens the portal routes — on portal_listen, which guests can't reach. Publish only 8787 in docker-compose.yml, never 8788. Upgrading an installation whose templates still carry a bootstrap_secret? Keep allow_bootstrap_enrollment = true until they don't — see Configuration.
6

Certificate and routing

Put the certificate and key in traefik/certs/ and reference them in traefik/dynamic/tls.yml. In docker-compose.yml, the portal's router and the console router (PathPrefix("/vnc")) use your host name in their Host(...) rule.

traefik/dynamic/tls.ymlYAML
tls:  certificates:    - certFile: /certs/verlocx.example.com.crt      keyFile:  /certs/verlocx.example.com.key
7

Start

shell
docker network create web                       # shared by Traefik and Verlocx (once)cd /opt/verlocx/traefik && docker compose up -dcd /opt/verlocx && docker compose up -d --builddocker compose logs -f --tail=80

The portal applies its database migrations on start. The backend logs two lines — listening (wss) — agents + console relays and portal listener (wss) — and the portal connected to wss://verlocx_backend:8788/ws/portal.

The portal image includes .env.local. After changing it, rebuild: docker compose up -d --build verlocx_portal.
8

Open the firewall

shell
ufw allow 80/tcpufw allow 443/tcpufw allow 8787/tcp comment 'verlocx backend (agents)'

The full list — including what the server needs to reach — is on Firewall & ports.

9

First sign-in and your first cluster

  1. Open the portal and sign in as root with ROOT_PASSWORD.
  2. Clusters → Add cluster: enter a node's API address and choose API token or Admin account (root@pam + password). Both work — the admin account is only needed for snapshots on raw LVM storage. Details and commands in Connecting Proxmox.
  3. Identity: connect Active Directory and/or Microsoft sign-in; then grant teams access under Access.
  4. Templates: pick which templates each project may use, with sizes, VMID range and naming.
  5. Settings → Deployment (per project): domain, OU and the domain-join account.
10

Prepare a Windows template with the agent

Install the agent in the template, point its config.toml at your backend, add your release_pubkey (see Agent releases) and convert the VM to a template. In Templates, switch on One-time agent enrollment token for it. Details in Verlocx agent. Then create your first VM from the portal and watch the deployment live.

11

Back up and move

To restore — or move Verlocx to another server — you need exactly these:

shell
pg_dump -h 127.0.0.1 -U verlocx -d verlocx -Fc -f verlocx.dump      # the databaseportal/.env.local                                               # incl. VERLOCX_DB_ENCRYPTION_KEYbackend/server.key  backend/server.pub  backend/registered_agents.toml  backend/config.toml

With the same keys, agents reconnect to the new server as soon as their backend_url points to it — a DNS name you can move is the easiest way.

Updating Verlocx

shell
cd /opt/verlocx# replace portal/ and backend/ with the new release (keep .env.local, config.toml and the key files)docker compose up -d --builddocker compose logs -f --tail=80     # migrations are applied on start

Sign new agent builds into agent-release/ (below); agents with an update_url pick them up within a day, or use Fleet → Update agent.

Agent releases and the release key

Agents install only builds signed with your release key. You sign on a separate machine with Node.js — the key never goes onto the Verlocx server, so neither the server nor a compromised guest can push code to your agents. The signing script ships with the portal as portal/scripts/agent-release.mjs.

Once: create the key pair.

shell
node agent-release.mjs keygen --out ~/verlocx-release# writes release.key (private, mode 600 — back it up, keep it offline)# and release.pub, and prints the line for the agents' config.toml:# release_pubkey = "8a3c…91be"

Put that release_pubkey line into your templates' and running agents' config.toml. The script refuses to overwrite an existing key — a new key locks out every agent that pins the old one.

For every new agent build: sign it on the signing machine.

shell
node agent-release.mjs sign   --file <agent.exe> --version 0.0.36   --release-key ~/verlocx-release/release.key   --out ./agent-release

This copies the build and writes release.json with its version, SHA-256 and signature. Copy both files into /opt/verlocx/agent-release/ on the server. The portal checks that the build matches before offering it; agents check the signature.

Upgrading from agents older than 0.0.36? They don't know the release key yet and trust only the backend key. For the one update to 0.0.36, also pass --backend-key backend/server.key (copy it to the signing machine just for this, then delete it there). Move every agent to 0.0.36 quickly; afterwards sign without --backend-key.

Troubleshooting

You seeFix
network web declared as external, but could not be founddocker network create web, then start Traefik before Verlocx.
CONNECT_TIMEOUT host.docker.internal:5432Postgres listens only on localhost, or ufw blocks the Docker networks — steps 1–2.
no pg_hba.conf entryAdd the 172.16.0.0/12 line to pg_hba.conf and restart Postgres.
Browser warns about the certificateThe certificate in traefik/certs doesn't cover your host name — check its subjectAltName.
Port 80/443 already in useAnother web server (nginx, Apache) still runs on the host — stop it first.
Agents connected, but VMs show offlineYou're looking at a different portal than the backend they connect to — check VERLOCX_BACKEND_URL.
Portal log: ECONNREFUSED …:8788The backend runs without portal_listen, or wasn't restarted after editing config.toml — the backend log must show two listening lines.
Portal log: Unexpected server response: 401VERLOCX_PORTAL_SECRET in .env.local and portal_secret in config.toml differ (or the variable is misnamed) — same value, both names.
Backend won't start: portal_secret …It equals bootstrap_secret or is shorter than 24 characters — generate one with openssl rand -hex 32.
Update agent: no signed release publishedagent-release/ has no valid release.json, or the build was changed after signing — sign it again with agent-release.mjs sign.
Next up

See Verlocx in action

A 30-minute walkthrough on your use case — deployments, workflows, governance.

Hypervisor

We use your details only to handle this request — privacy policy.

Type to search the docs, the user guide, all features, the product pages and the changelog.

↑ ↓ to move↵ to openesc to close