Self-hosting overview¶
Reference for operations tasks around Vesana. If you host Vesana for someone else or maintain a customer instance: the levers live here.
Directory layout¶
/opt/vesana/
├── docker-compose.prod.yml # Compose stack
├── .env # Secrets + configuration
├── secrets/ # File secrets (chmod 600)
│ ├── pg_password
│ ├── redis_password
│ ├── secret_key
│ └── field_encryption_key
├── ssl/ # TLS certs (optional, otherwise self-signed)
│ ├── cert.pem
│ └── key.pem
├── backups/ # Backups when profile "backup" is active
└── uploads/ # Wiki attachments etc.
Optional profiles¶
Compose profiles toggle optional services:
| Profile | Services | When |
|---|---|---|
| Default (no profile) | postgres, redis, api, receiver, worker, frontend, init | Always |
ai |
ollama | AI features with local Ollama |
backup |
backup sidecar | Daily backup |
pgbouncer |
pgbouncer | Connection pool with many API replicas |
Activate:
Profiles are cumulative — once active, services stay even on up -d without the flag. To remove: explicit down <service>.
Important env variables¶
.env is generated by the setup script. Important variables:
Required¶
| Variable | Meaning |
|---|---|
BASE_URL |
Public URL incl. https:// |
POSTGRES_PASSWORD |
Generated |
REDIS_PASSWORD |
Generated |
SECRET_KEY |
JWT signing key, generated |
FIELD_ENCRYPTION_KEY |
AES-256-GCM key for field encryption, generated |
Optional / tuning¶
| Variable | Default | Meaning |
|---|---|---|
WORKER_REPLICAS |
1 |
Number of consumer workers |
WORKER_CONCURRENCY |
4 |
Concurrency per worker |
WORKER_BATCH_SIZE |
100 |
Batch size per pass |
PG_SHARED_BUFFERS |
256MB |
~25 % of RAM |
PG_WORK_MEM |
16MB |
Sort/hash buffer |
PG_EFFECTIVE_CACHE |
512MB |
~50 % of RAM |
PG_MAX_CONNECTIONS |
200 |
Connection limit |
REDIS_MAXMEMORY |
512mb |
Redis memory limit (noeviction policy) |
HTTP_PORT / HTTPS_PORT |
80 / 443 |
When other services use the ports |
AI_ENABLED |
false |
Turn on AI features |
LICENSE_KEY |
empty | License key |
VESANA_TESTER_MODE |
false |
Tester mode (all features unlocked) |
Full list in .env.example. After changes: docker compose up -d to apply.
SSL / TLS¶
Default: Let's Encrypt from the wizard¶
If BASE_URL is a domain and port 80 is reachable from outside, the wizard auto-issues a Let's Encrypt cert. Renewal runs in the background.
Custom certificate¶
sudo cp your-cert.pem /opt/vesana/ssl/cert.pem
sudo cp your-key.pem /opt/vesana/ssl/key.pem
sudo chmod 600 /opt/vesana/ssl/key.pem
docker compose -f /opt/vesana/docker-compose.prod.yml exec nginx nginx -s reload
Behind your own reverse proxy¶
If a nginx / Traefik / HAProxy already fronts the server, terminate TLS there and proxy internally to http://vesana-frontend:80. Details: TLS / reverse proxy.
Tester mode¶
What is tester mode
With VESANA_TESTER_MODE=true in .env, license validation is bypassed — all features are unlocked, the setup wizard skips the license step. The instance registers with the licence portal as a „tester instance" and Lukas / vendor team can revoke updates server-side per instance.
Activate¶
echo "VESANA_TESTER_MODE=true" | sudo tee -a /opt/vesana/.env
docker compose -f /opt/vesana/docker-compose.prod.yml up -d
What happens¶
shared/license.py::is_tester_mode()returnsTrueload_license_from_env_or_db()returns a synthetic full-featuresLicenseInfo- API server phones home every 60 minutes to
license.vesana.org/api/v1/tester/registerwith{instance_id, hostname, version} - Instance shows up in the licence portal under „tester instances"
- Per instance, updates can be set to
blocked— the updater shows a banner
When to turn it off¶
Before handing the instance to a real customer: remove VESANA_TESTER_MODE from .env, set the license key, restart stack.
Updates & backups¶
- Updates — GUI updater, online + offline + emergency CLI
- Backup & restore — sidecar, manual, disaster drill
Next¶
- Scaling — tuning at growing host count
- System health — pipeline-health endpoint
- Security — hardening checklist