Skip to main content
Heimdall provides first-class Docker support with multi-stage builds and flexible database options.

Quick Start

1

Clone the repository

git clone https://github.com/modestnerd/heimdall.git
cd heimdall
2

Configure environment

cp .env.example .env
Edit .env and set at least one AI provider key:
ANTHROPIC_API_KEY=sk-ant-...
# or
OPENAI_API_KEY=sk-...
# or
OLLAMA_URL=http://localhost:11434
3

Start with Docker Compose

docker compose --profile postgres up -d
4

Verify it's running

curl http://localhost:8080/health
# {"status":"ok"}
Open http://localhost:8080 in your browser.

Docker Compose Profiles

Heimdall supports multiple database backends via Docker Compose profiles. Only activate one database at a time.
docker compose --profile postgres up -d
PostgreSQL is the recommended and most tested database backend.

Building from Source

The Dockerfile uses a multi-stage build process:

Build Arguments

ArgumentDefaultDescription
DB_DRIVERpostgresDatabase driver: postgres, mysql, mongo, or sqlite
INSTALL_SEMGREPtrueInstall Semgrep for enhanced static analysis

Custom Build

# Build with custom database driver
docker compose build --build-arg DB_DRIVER=mysql

# Build without Semgrep (smaller image)
docker compose build --build-arg INSTALL_SEMGREP=false

# Force rebuild
docker compose --profile postgres up -d --build

Environment Configuration

Required Variables

ANTHROPIC_API_KEY=sk-ant-api03-...

Database Connection

The database URL format depends on your chosen profile:
DATABASE_URL=postgres://heimdall:heimdall@postgres:5432/heimdall
When using Docker Compose, use the service name (e.g., postgres, mysql, mongo) as the hostname, not localhost.

Security Keys

Generate secure keys for encryption and webhook verification:
# Encryption key for stored API keys
ENCRYPTION_KEY=$(openssl rand -hex 32)

# Webhook signature verification
WEBHOOK_SECRET=$(openssl rand -hex 20)
Add these to your .env file.

Docker Volumes

Heimdall requires access to the Docker socket for the Garmr sandbox:
volumes:
  - /var/run/docker.sock:/var/run/docker.sock
Mounting the Docker socket grants the container access to create and manage other containers. Ensure proper network isolation in production environments.

Persistent Data

Database data is stored in named volumes:
volumes:
  postgres-data:    # PostgreSQL data
  mysql-data:       # MySQL data
  mongo-data:       # MongoDB data
To backup or migrate data:
# List volumes
docker volume ls

# Backup PostgreSQL data
docker run --rm -v heimdall_postgres-data:/data -v $(pwd):/backup \
  alpine tar czf /backup/postgres-backup.tar.gz -C /data .

# Restore PostgreSQL data
docker run --rm -v heimdall_postgres-data:/data -v $(pwd):/backup \
  alpine tar xzf /backup/postgres-backup.tar.gz -C /data

Health Checks

Heimdall includes built-in health checks:
healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
  interval: 30s
  timeout: 10s
  retries: 3
  start_period: 10s
Check container health:
docker compose ps
docker inspect heimdall | jq '.[0].State.Health'

Troubleshooting

Container won’t start

1

Check logs

docker compose logs -f heimdall
2

Verify database is ready

docker compose ps
# Ensure database service shows "healthy"
3

Check environment variables

docker compose config
# Verify .env values are loaded correctly

Database connection fails

Common mistake: Using localhost instead of the service name in DATABASE_URL.
# ❌ Wrong (when using Docker Compose)
DATABASE_URL=postgres://heimdall:heimdall@localhost:5432/heimdall

# ✅ Correct
DATABASE_URL=postgres://heimdall:heimdall@postgres:5432/heimdall

Permission denied on Docker socket

# Add your user to the docker group
sudo usermod -aG docker $USER

# Log out and back in, then verify
docker ps

Out of memory errors

Increase Docker daemon memory limits:
# Docker Desktop: Settings > Resources > Memory (recommend 4GB+)

# Linux: Edit /etc/docker/daemon.json
{
  "default-ulimits": {
    "memlock": {
      "Hard": -1,
      "Soft": -1
    }
  }
}

Semgrep not working

Rebuild with Semgrep enabled:
docker compose build --build-arg INSTALL_SEMGREP=true --no-cache
docker compose up -d

Clean slate restart

This will delete all data, including scans and findings.
# Stop and remove containers, volumes, and images
docker compose down -v --rmi all

# Rebuild and start fresh
docker compose --profile postgres up -d --build

Development Workflow

For local development, use docker-compose.dev.yml to run only the database:
# Start only PostgreSQL
docker compose -f docker-compose.dev.yml up -d

# Run Heimdall locally
cargo run --bin heimdall
This allows faster iteration with hot reloading while keeping the database containerized.

Next Steps

Production Deployment

Harden your deployment for production use

Reverse Proxy Setup

Configure Nginx with TLS and SSE support

Build docs developers (and LLMs) love