Skip to main content

Self-host Observra with Docker

Run Observra locally or on a Docker-capable server with one Compose file. You do not need Node.js, pnpm, PostgreSQL, Redis, NATS, or Python installed on the host.

Requirements​

  • Docker Desktop or Docker Engine with Docker Compose support
  • Access to the public container registry during the initial image pull
  • An available host port for the dashboard (3000 by default)

Pull the Observra image​

Pull the public Observra image before starting the services:

docker pull hardik1802/selfhosted-observra:latest

Create docker-compose.yml​

Use the following Compose configuration:

services:
observra:
image: hardik1802/selfhosted-observra:latest
ports:
- "3000:3000"
- "8787:8787"
- "8788:8788"
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_started
nats:
condition: service_started
volumes:
- observra-journal:/app/journal-data
- observra-config:/app/config
restart: unless-stopped

postgres:
image: postgres:16-alpine
environment:
POSTGRES_DB: observra
POSTGRES_USER: observra
POSTGRES_PASSWORD: observra
volumes:
- observra-postgres:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U observra -d observra"]
interval: 5s
timeout: 5s
retries: 10
restart: unless-stopped

redis:
image: redis:7-alpine
volumes:
- observra-redis:/data
restart: unless-stopped

nats:
image: nats:2-alpine
restart: unless-stopped

volumes:
observra-config:
observra-journal:
observra-postgres:
observra-redis:

Start Observra​

From the folder containing docker-compose.yml, run:

docker compose up -d
docker compose ps

Open the dashboard at http://localhost:3000.

Default first-login credentials:

Email: admin@observra.local
Password: ChangeMe-123!

Change the password immediately after signing in.

On first setup, choose Use bundled local services. Observra runs database migrations, verifies the schema, seeds the initial account, and starts the gateway and worker.

Use the gateway​

Create a Gateway API key in the dashboard. Requests use the gateway at http://localhost:8787. The gateway key authenticates Observra; the provider key is forwarded to the selected AI provider.

Example Gemini request:

import requests

response = requests.post(
"http://localhost:8787/gemini/v1beta/models/gemini-3.6-flash:generateContent",
headers={
"Authorization": "Bearer <GATEWAY_KEY>",
"x-provider-key": "<GEMINI_API_KEY>",
"Content-Type": "application/json",
},
json={
"contents": [
{"role": "user", "parts": [{"text": "Hello from Observra"}]}
]
},
timeout=60,
)

print(response.status_code)
print(response.text)

After a successful request, open Request Explorer to view status, model, tokens, cost, latency, and request timing.

Run on another machine or server​

Copy the same docker-compose.yml to the host and run:

docker compose pull
docker compose up -d

On a remote server, allow TCP port 3000 in its firewall and open:

http://SERVER_IP:3000

For production hosting, put the dashboard behind HTTPS and restrict ports 8787 and 8788 to trusted networks. Keep the Docker volumes so database, configuration, and journal data survive container restarts.

Logs and shutdown​

docker compose logs -f observra
docker compose down

docker compose down preserves named volumes. To permanently remove all bundled data:

docker compose down -v

This deletes the local PostgreSQL, Redis, configuration, and journal volumes.

Troubleshooting​

Check service status:

docker compose ps

If Observra reports getaddrinfo EAI_AGAIN postgres, Redis, or NATS, make sure all four Compose services are defined in the same file and started together. If the dashboard is unavailable, check that port 3000 is free and inspect:

docker compose logs -f observra postgres redis nats