For the complete documentation index, see llms.txt. This page is also available as Markdown.

Single-node deployment

Run the full Observal stack on a single VM with Docker Compose. Best for teams of up to ~50 users, internal tools, evaluations, and any deployment where simplicity matters more than multi-AZ redundancy.

End state: Observal running behind TLS on one server, with automated backups to S3-compatible storage, surviving reboots, and upgradable in under a minute.

When to use this vs. the Terraform module

Single-node (this guide)

Production Terraform

Best for

Small/mid teams, internal use, POCs

Enterprise, SLA-bound, high-traffic

Infra

1 VM, any cloud or on-prem

~100 managed AWS resources

Cost

$20–150/mo

~$255/mo

HA

No — single point of failure

Yes — Multi-AZ Postgres, autoscaling ECS

Time to deploy

10 minutes

20–30 minutes

Operational complexity

Low — SSH, docker compose, cron

Medium — Terraform, AWS console, CloudWatch

Scaling

Vertical (bigger VM)

Horizontal (more Fargate tasks)

Architecture

Everything runs as Docker containers on a single host. The nginx LB routes traffic and terminates TLS. Docker's restart policy and systemd keep the stack running across reboots.

Prerequisites

Requirement
Minimum
Recommended

VM

2 vCPU, 4 GB RAM, 40 GB SSD

4 vCPU, 8 GB RAM, 100 GB SSD

OS

Ubuntu 22.04+ / Amazon Linux 2023 / Debian 12

Ubuntu 24.04 LTS

Docker

Engine ≥ 24.0 with Compose v2

Latest stable

Domain (for TLS)

A DNS record pointing to the VM's public IP

Firewall

Ports 80, 443 open inbound

Sizing guide

Team size
VM spec
Estimated cost (AWS)

1–10 users

t3.medium (2 vCPU / 4 GB)

~$30/mo

10–30 users

t3.large (2 vCPU / 8 GB)

~$60/mo

30–50 users

t3.xlarge (4 vCPU / 16 GB)

~$120/mo

50+ users

Consider the Terraform module

~$255/mo

ClickHouse is the memory consumer. If you run out, increase CLICKHOUSE_MEMORY_LIMIT before resizing the VM.

Step 1: Provision the VM

Use any cloud provider or on-prem hypervisor. Example for AWS:

For other clouds:

  • GCP: e2-standard-2 with 100 GB balanced persistent disk

  • Azure: Standard_B2ms with 100 GB Premium SSD

  • Hetzner: CPX31 (4 vCPU / 8 GB, ~€15/mo)

  • On-prem: any Linux box meeting the specs above

Step 2: Install Docker

SSH into the VM and install Docker:

Step 3: Clone and configure

Edit .env for production. At minimum, change these:

Write them into .env:

SAML SSO, audit logs, and executive dashboards are included in the open-source distribution. See Configuration. For mounted credentials and private keys, use the documented NAME_FILE inputs instead of placing secret contents in .env.

Step 4: Set up TLS

This guide uses the source Compose stack. Every localhost:80 example below refers to that stack's nginx load balancer. Do not expose its HTTP listener directly to remote clients. For downloadable server-package bindings, see Requirements.

Option A: Caddy (simplest — automatic HTTPS)

Create /etc/caddy/Caddyfile:

Caddy handles Let's Encrypt certificates automatically. No renewal cron needed.

Option B: Certbot + nginx production config

Then use the production compose overlay which configures nginx for TLS:

Set up auto-renewal:

Option C: Behind a cloud load balancer

If your VM sits behind an AWS ALB, GCP HTTPS LB, or Cloudflare, terminate TLS there and proxy to port 80 on the VM. No TLS config on the VM itself.

Step 5: Start the stack

First build takes 3–5 minutes (pulling images, building the API and web containers). Watch the logs:

Wait for:

Verify:

Step 6: Survive reboots

Docker's restart: unless-stopped policy (already set in docker-compose.yml) handles container restarts. To ensure Docker itself starts on boot:

Test it:

Step 7: Set up automated backups

Create a backup script:

Schedule it:

For ClickHouse (weekly, since it's larger):

See Backup and restore for detailed restore procedures.

Step 8: First login

Install the CLI on your local machine:

Log in:

Verify:

Upgrades

The Compose init service applies migrations before API startup. See Upgrades for rollback procedures.

Or use the CLI:

Monitoring

Prometheus and Grafana are optional. Start the core stack with Prometheus only:

Start Prometheus and Grafana:

Access Grafana at http://your-server:3001 when the Grafana profile is enabled.

For basic alerting without Grafana, add a health check cron:

Security hardening

The security assurance case describes the deployment trust boundaries and residual risks.

Before exposing to the internet:

Scaling up

When you outgrow a single node:

Symptom
Fix

API response times increasing

Increase API_WORKERS in .env (default 2), or bump to a bigger VM

ClickHouse queries slow

Increase CLICKHOUSE_MEMORY_LIMIT, move to a bigger VM, or externalize to ClickHouse Cloud

Disk filling up

Reduce DATA_RETENTION_DAYS, add a bigger disk, or move ClickHouse data to a separate volume

Need HA / zero downtime deploys

Migrate to the Terraform module

Next

Last updated

Was this helpful?