Observer ships as a single Docker image with the web interface embedded in the binary.

What you need

  • A server with Docker and Docker Compose installed
  • A domain name pointed at your server (for HTTPS)

Step 1: Generate signing keys

Observer uses RSA keys to sign login tokens. Run these commands on your server to create them:

mkdir -p keys
openssl genrsa -out keys/jwt_rsa 4096
openssl rsa -in keys/jwt_rsa -pubout -out keys/jwt_rsa.pub

If the keys are lost, all sessions become invalid.

Step 2: Configure your environment

Copy the example environment file and edit it for your setup:

cp .env.example .env

The most important variables:

VariableWhat it doesDefault
DATABASE_DSNHow Observer connects to PostgreSQL(must be set)
REDIS_URLHow Observer connects to Redisredis://localhost:6379/0
JWT_PRIVATE_KEY_PATHWhere you put the private key from Step 1keys/jwt_rsa
JWT_PUBLIC_KEY_PATHWhere you put the public key from Step 1keys/jwt_rsa.pub
CORS_ORIGINSYour domain (e.g. https://observer.yourorg.org)http://localhost:5173
COOKIE_SECURESet to true when using HTTPStrue
SERVER_HOSTWhich address to listen onlocalhost
SERVER_PORTWhich port to listen on9000

See Environment Variables for the full list.

Step 3: Start Observer

docker compose up -d

This starts PostgreSQL, Redis, and Observer. On first launch, Observer applies migrations automatically.

Step 4: Verify it’s running

curl http://localhost:9000/health

You should see:

{ "status": "healthy", "timestamp": "..." }

Open your domain in a browser to access the web interface.

Without Docker (VPS / bare metal)

If you prefer to run Observer directly, build the binary:

CGO_ENABLED=0 go build -tags production -ldflags="-s -w" -o observer ./cmd/observer

The -tags production flag embeds the web interface into the binary.

Run it:

./observer serve --host 0.0.0.0

You’ll need PostgreSQL and Redis running separately. Point DATABASE_DSN and REDIS_URL to them.

Setting up HTTPS

You should always run Observer behind a reverse proxy that handles HTTPS.

Caddy handles certificates automatically:

observer.yourorg.org {
    reverse_proxy localhost:9000
}

If you use Nginx or another proxy, make sure to set:

  • COOKIE_SECURE=true in your environment
  • CORS_ORIGINS to your actual domain (e.g. https://observer.yourorg.org)

DEV_MODE

DEV_MODE=true disables CORS enforcement, CSRF protection, and security headers. It exists only for local development and is set automatically by just dev. Never set this in a production environment — it removes all request origin and cross-site protections.