Skip to main content

Docker Self-Hosting

Deploy Lagoon Cockpit on any Linux server with Docker installed.

Requirements

  • Docker Engine 20.10+
  • 256MB RAM, 0.25 CPU (resource limits)
  • Docker socket access (/var/run/docker.sock)

Quick Start

docker run -d \
--name cockpit \
-e API_KEY=your-secret-key \
-e JWT_SECRET=$(openssl rand -hex 32) \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /proc:/host/proc:ro \
-p 3000:3000 \
ghcr.io/lagoon-tech-systems/cockpit:latest

Verify it's running:

curl http://localhost:3000/health
# {"status":"ok"}

Create a docker-compose.yml:

services:
cockpit:
image: ghcr.io/lagoon-tech-systems/cockpit:latest
restart: unless-stopped
env_file: .env
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /proc:/host/proc:ro
- cockpit_data:/app/data
ports:
- "3000:3000"
deploy:
resources:
limits:
cpus: "0.25"
memory: 256M

volumes:
cockpit_data:

Create a .env file:

# Required
API_KEY=your-secret-key
JWT_SECRET=$(openssl rand -hex 32)

# Optional
AUTH_MODE=key
SERVER_NAME=Production VPS

Start the service:

docker compose up -d

Authentication Modes

API Key Mode (default)

Single-admin access using a shared API key. Best for personal use.

AUTH_MODE=key
API_KEY=your-secret-key

Multi-User Mode

Full user management with JWT auth, roles, and RBAC. Best for teams.

AUTH_MODE=users
JWT_SECRET=random-64-char-string
ADMIN_EMAIL=admin@example.com
ADMIN_PASSWORD=change-me

On first startup, the admin account is created automatically. Change the password immediately after first login.

Reverse Proxy (Nginx)

For production deployments behind a reverse proxy:

server {
listen 443 ssl http2;
server_name cockpit.example.com;

ssl_certificate /etc/letsencrypt/live/cockpit.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/cockpit.example.com/privkey.pem;

location / {
proxy_pass http://127.0.0.1:3000;
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;

# SSE support
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 86400s;
}
}

Set FORCE_HTTPS=true and CORS_ORIGINS=https://cockpit.example.com in your .env.

Extensions (Pro/Enterprise)

Pro and Enterprise modules are loaded from the extensions directory:

volumes:
- cockpit-extensions:/app/extensions

To install an extension, place the package directory inside the extensions volume and restart:

docker compose restart cockpit

Extensions are auto-detected on startup. Check the loaded extensions:

curl http://localhost:3000/api/edition \
-H "Authorization: Bearer $TOKEN"

Prometheus Metrics

Cockpit exports 37+ metrics at /metrics. To scrape with Prometheus:

scrape_configs:
- job_name: 'cockpit'
scrape_interval: 30s
static_configs:
- targets: ['cockpit:3000']
metrics_path: '/metrics'
authorization:
type: Bearer
credentials: your-metrics-token

Set METRICS_TOKEN in your .env to secure the endpoint.

Environment Variables

VariableDefaultDescription
API_KEY(required)Shared API key for AUTH_MODE=key
JWT_SECRET(required)Secret for signing JWT tokens
AUTH_MODEkeykey (single-admin) or users (multi-user)
PORT3000API port
SERVER_NAMEServerDisplay name in the mobile app
LICENSE_KEY(empty)Pro/Enterprise license JWT (CE if empty)
FORCE_HTTPSfalseRedirect HTTP to HTTPS
CORS_ORIGINS(empty)Comma-separated allowed origins
RATE_LIMIT_MAX100Max requests per minute per IP
METRICS_TOKEN(empty)Bearer token for /metrics
PROC_PATH/host/procMounted /proc path
DOCKER_SOCKET/var/run/docker.sockDocker Engine socket
DATA_DIR/app/dataSQLite DB + state files
EXTENSIONS_DIR/app/extensionsExtension modules directory
ENDPOINTS(empty)HTTP probe targets (format: Name|URL|ExpectedStatus)
SSL_DOMAINS(empty)Domains to monitor SSL expiry
EXPO_ACCESS_TOKEN(empty)Expo push notification token (Pro)

Data Persistence

All state is stored in SQLite at $DATA_DIR/cockpit.db (WAL mode). Back up this file regularly:

# Copy the database while the container is running (WAL mode is safe for this)
docker cp cockpit:/app/data/cockpit.db ./cockpit-backup.db

Upgrading

docker compose pull
docker compose up -d

The database schema auto-migrates on startup. No manual steps required.