This guide covers installing Heimdall for local development and production deployment using either local installation or Docker.
Prerequisites
Before installing Heimdall, ensure you have the required dependencies.
Required Dependencies
Dependency Version Purpose Rust 1.85+ (2024 edition) Compilation and runtime PostgreSQL 14+ Primary database Git 2.25+ Repository cloning AI API Key — At least one: Claude, OpenAI, or Ollama
Optional Dependencies
Dependency Version Purpose Docker 20+ Garmr sandbox for PoC validation
Docker is highly recommended for the Garmr sandbox, which executes proof-of-concept exploits in isolated containers. Without Docker, scans still work but sandbox validation is skipped gracefully.
Installing Prerequisites
Install Rust
Rust 1.85+ is required for the 2024 edition features:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup default stable
Verify installation:
rustc --version
# rustc 1.85.0 (or later)
Install PostgreSQL
macOS
Ubuntu/Debian
Docker (Recommended for Dev)
brew install postgresql@17
brew services start postgresql@17
Verify PostgreSQL is running:
psql --version
# psql (PostgreSQL) 17.x
Install Git
Verify installation:
git --version
# git version 2.25.0 (or later)
Install Docker (Optional)
Docker is required for the Garmr sandbox validation stage.
# Install Docker Desktop from:
# https://www.docker.com/products/docker-desktop/
Verify Docker is running:
On Linux, ensure your user is in the docker group to avoid permission issues. The Garmr sandbox needs access to the Docker socket.
Local Development Setup
Clone the repository
git clone https://github.com/modestnerd/heimdall.git
cd heimdall
Start PostgreSQL
Choose one method: Option A: Docker (Recommended)
Option B: Local PostgreSQL
docker compose -f docker-compose.dev.yml up -d
Configure environment
Copy the example environment file: Edit .env with your settings (see Configuration for details): # Required: Database connection
DATABASE_URL = postgres://heimdall:heimdall@localhost:5432/heimdall
# Required: At least one AI provider (BYOK)
ANTHROPIC_API_KEY = sk-ant-... # Claude (recommended)
# OPENAI_API_KEY=sk-... # GPT-4o
# OLLAMA_URL=http://localhost:11434 # Local models
# Security (generate these)
ENCRYPTION_KEY = $( openssl rand -hex 32 )
WEBHOOK_SECRET = $( openssl rand -hex 20 )
Generate security keys: # Add to .env
echo "ENCRYPTION_KEY=$( openssl rand -hex 32 )" >> .env
echo "WEBHOOK_SECRET=$( openssl rand -hex 20 )" >> .env
Build the project
This will download dependencies and compile Heimdall. First build takes 5-10 minutes.
Run Heimdall
The database schema is applied automatically on startup: For development with debug logging: RUST_LOG = debug cargo run --bin heimdall
Verify installation
Check the health endpoint: curl http://localhost:8080/health
# {"status":"ok"}
Open http://localhost:8080 in your browser to access the web UI.
Docker Compose Setup
For production or simplified deployment, use Docker Compose.
Clone the repository
git clone https://github.com/modestnerd/heimdall.git
cd heimdall
Configure environment
cp .env.example .env
# Edit .env with your AI provider key(s) and security settings
Ensure these are set: DATABASE_URL = postgres://heimdall:heimdall@postgres:5432/heimdall
ANTHROPIC_API_KEY = sk-ant-...
ENCRYPTION_KEY = $( openssl rand -hex 32 )
WEBHOOK_SECRET = $( openssl rand -hex 20 )
Start Heimdall + PostgreSQL
docker compose --profile postgres up -d
To build from source instead of using the pre-built image: docker compose --profile postgres up -d --build
View logs
docker compose logs -f heimdall
Press Ctrl+C to stop following logs.
Verify installation
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:
# PostgreSQL (default, recommended)
docker compose --profile postgres up -d
# MySQL 8.4
docker compose --profile mysql up -d
# MongoDB 7
docker compose --profile mongo up -d
Only use one database profile at a time. PostgreSQL is recommended for production.
Production Deployment
Building Release Binary
For production deployment on a single machine:
Build optimized binary
The binary will be at ./target/release/heimdall.
Configure environment
Create a production .env file: APP_HOST = 0.0.0.0
APP_PORT = 8080
TLS_ENABLED = false # Use reverse proxy for TLS
DATABASE_URL = postgres://heimdall:SECURE_PASSWORD@localhost:5432/heimdall
ANTHROPIC_API_KEY = sk-ant-...
ENCRYPTION_KEY =< generate-with-openssl-rand-hex-32 >
WEBHOOK_SECRET =< generate-with-openssl-rand-hex-20 >
WORKER_ENABLED = true
RUST_LOG = info, heimdall = info
Run with systemd (recommended)
Create a systemd service file /etc/systemd/system/heimdall.service: [Unit]
Description =Heimdall Security Scanner
After =network.target postgresql.service
[Service]
Type =simple
User =heimdall
WorkingDirectory =/opt/heimdall
EnvironmentFile =/opt/heimdall/.env
ExecStart =/opt/heimdall/target/release/heimdall
Restart =always
RestartSec =10
[Install]
WantedBy =multi-user.target
Enable and start the service: sudo systemctl daemon-reload
sudo systemctl enable heimdall
sudo systemctl start heimdall
sudo systemctl status heimdall
Reverse Proxy Setup (Nginx)
For production, use a reverse proxy to handle TLS:
/etc/nginx/sites-available/heimdall
server {
listen 443 ssl http2;
server_name heimdall.example.com;
ssl_certificate /etc/ssl/certs/heimdall.pem;
ssl_certificate_key /etc/ssl/private/heimdall.key;
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
location / {
proxy_pass http://127.0.0.1:8080;
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 requires no buffering
location /api/scans/ {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $ host ;
proxy_buffering off ;
proxy_cache off ;
proxy_read_timeout 3600s ;
}
}
# HTTP redirect to HTTPS
server {
listen 80 ;
server_name heimdall.example.com;
return 301 https://$ server_name $ request_uri ;
}
Enable the site:
sudo ln -s /etc/nginx/sites-available/heimdall /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Installation Verification
Check Service Health
curl http://localhost:8080/health
# Expected: {"status":"ok"}
Verify Database Connection
psql $DATABASE_URL -c "SELECT COUNT(*) FROM users;"
Verify Docker Access (for Garmr)
docker ps
# Should list running containers without errors
Test AI Provider
After registration, go to Settings → AI Providers → Test Connection to verify your AI provider is working.
Data Directory Structure
Heimdall stores persistent data in the configured data directory (default: ./data):
data/
├── repos/ # Cloned repository working copies
├── uploads/ # Uploaded ZIP files
└── logs/ # Application logs (if file logging enabled)
Ensure the Heimdall process has read/write permissions to this directory.
Upgrading Heimdall
Local Installation
cd heimdall
git pull origin main
cargo build --release
sudo systemctl restart heimdall # If using systemd
Docker Compose
cd heimdall
git pull origin main
docker compose --profile postgres down
docker compose --profile postgres up -d --build
The database schema is automatically applied on startup using idempotent DDL. No manual migrations needed.
Uninstalling Heimdall
Local Installation
# Stop the service
sudo systemctl stop heimdall
sudo systemctl disable heimdall
sudo rm /etc/systemd/system/heimdall.service
# Remove files
rm -rf /opt/heimdall
# Drop database
dropdb heimdall
Docker Compose
cd heimdall
docker compose --profile postgres down -v # -v removes volumes
cd ..
rm -rf heimdall
Next Steps
Configuration Configure AI providers, OAuth, security settings, and workers
Quickstart Run your first security scan
Troubleshooting
Compilation Errors
If you encounter compilation errors:
# Update Rust to latest stable
rustup update stable
# Clean build artifacts and rebuild
cargo clean
cargo build --release
Port Already in Use
If port 8080 is already in use:
APP_PORT = 8081 # Change to any available port
Docker Socket Permission Denied
If Garmr cannot access Docker:
# Add user to docker group
sudo usermod -aG docker $USER
# Log out and back in, then verify
docker info
Database Migration Issues
If schema application fails:
# Check database logs
docker compose logs postgres
# Manually connect and verify
psql $DATABASE_URL
The schema is idempotent and safe to re-run. Simply restart Heimdall: