Overview
Shieldome can be deployed on any Linux server you control - a VPS, a bare-metal machine, or a private cloud instance. The on-premise edition runs the same engine as the hosted service, but all data stays on your infrastructure. A license key is required for production use; contact [email protected] to obtain one.
Requirements
- Docker 24+ and Docker Compose v2+ (
docker composecommand) - A server with at least 2 GB RAM and 10 GB free disk space
- A domain name pointed at your server's IP (required for HTTPS and OOB detection)
- Ports 80 and 443 open in your firewall (for the reverse proxy)
- An on-premise license key - contact [email protected]
Quick start
1. Get the files
Clone the repository or download the release archive:
git clone https://github.com/shieldome/scanner.git
cd scanner
# Or pull the pre-built image without the source:
mkdir shieldome-onprem && cd shieldome-onprem
curl -O https://raw.githubusercontent.com/shieldome/scanner/main/docker-compose.yml
curl -O https://raw.githubusercontent.com/shieldome/scanner/main/.env.example
2. Configure environment
cp .env.example .env
# Open .env in your editor and fill in the required values
nano .env
At minimum, set these five values before starting:
SHIELDOME_SECRET_KEY- generate a strong random key (see below)POSTGRES_PASSWORD- set a strong database passwordDATABASE_URL- uncomment and update with your Postgres passwordAPP_BASE_URL- your public domain, e.g.https://scan.example.comLICENSE_KEY- your on-premise license key
# Generate a secure secret key python -c "import secrets; print(secrets.token_hex(32))"
3. Start the stack
docker compose up -d
This starts PostgreSQL, Redis, the Shieldome app, and the Celery background workers. First boot may take 30-60 seconds as images are pulled and the database is initialised. Check that all services are running:
docker compose ps docker compose logs -f shieldome
Once healthy, the app is reachable on port 5000. You should place it behind a reverse proxy (see SSL/HTTPS setup below) before exposing it to the internet.
Environment variables
| Variable | Required | Description |
|---|---|---|
SHIELDOME_SECRET_KEY |
Yes | Flask session secret. Generate with secrets.token_hex(32). Never use the default in production. |
DATABASE_URL |
Yes (prod) | PostgreSQL DSN, e.g. postgresql://shieldome:pass@postgres:5432/shieldome. Leave blank to use SQLite (single-container only). |
POSTGRES_DB |
Yes | PostgreSQL database name (used by the postgres Docker service). Default: shieldome. |
POSTGRES_USER |
Yes | PostgreSQL username. Default: shieldome. |
POSTGRES_PASSWORD |
Yes | PostgreSQL password. Must be set explicitly - Docker Compose will refuse to start without it. |
REDIS_URL |
Yes | Redis connection URL for Celery workers. Default: redis://redis:6379/0. |
APP_BASE_URL |
Yes | Public URL of your instance (no trailing slash). Used in emails, OAuth callbacks, and report links. |
RESEND_API_KEY |
Recommended | Resend API key for transactional email (alerts, account verification). Get a free key at resend.com. |
SHIELDOME_NOTIFY_EMAIL |
Recommended | Admin email for internal notifications (new tickets, abuse reports, etc.). |
INTERNAL_SECRET |
OOB only | Shared secret for authenticating OOB DNS callbacks. Generate with secrets.token_hex(32). |
OOB_DNS_DOMAIN |
OOB only | DNS subdomain for out-of-band detection probes, e.g. oob.scan.example.com. Omit to disable OOB detection. |
LICENSE_KEY |
Yes (prod) | On-premise license key. Contact [email protected] to obtain one. |
NVD_API_KEY |
Optional | NIST NVD API key - raises CVE lookup rate limit from 5/30s to 50/30s. Free at nvd.nist.gov. |
FLASK_ENV |
Optional | Set to production (default) or development. Never run development in production. |
See .env.example in the repository for the complete list including email, webhook, payment, and scanner tuning variables.
SSL/HTTPS setup
Run Shieldome behind a reverse proxy that handles TLS termination. Two common options:
Option A - Caddy (recommended, auto-HTTPS)
Caddy automatically obtains and renews Let's Encrypt certificates.
scan.example.com {
reverse_proxy localhost:5000
}
# Install Caddy (Debian/Ubuntu) sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list sudo apt update && sudo apt install caddy # Place your Caddyfile at /etc/caddy/Caddyfile, then: sudo systemctl reload caddy
Option B - nginx + Certbot
server {
listen 80;
server_name scan.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name scan.example.com;
ssl_certificate /etc/letsencrypt/live/scan.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/scan.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
location / {
proxy_pass http://127.0.0.1:5000;
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;
# Required for Server-Sent Events (live scan progress)
proxy_buffering off;
proxy_read_timeout 300s;
}
}
sudo apt install certbot python3-certbot-nginx sudo certbot --nginx -d scan.example.com
proxy_buffering off directive is required for Server-Sent Events (real-time scan progress) to work correctly through nginx.
Updating
To pull the latest Shieldome image and restart with zero downtime:
docker compose pull docker compose up -d
Docker Compose will restart only the services whose images have changed. Database migrations run automatically on startup.
Backups
Back up the PostgreSQL database regularly. A simple daily dump:
# Create a timestamped dump docker compose exec postgres pg_dump -U shieldome shieldome \ > backup-$(date +%Y%m%d-%H%M%S).sql # Restore from a dump docker compose exec -T postgres psql -U shieldome shieldome \ < backup-20260101-120000.sql
Also back up the shieldome-reports Docker volume (or the ./reports directory if you use a bind mount) to preserve generated PDF reports.
OOB detection setup
Out-of-band (OOB) detection finds vulnerabilities - like blind SSRF and blind SQLi - that produce no visible response. Shieldome sends probes with unique DNS hostnames; if the target resolves them, a callback hits your OOB listener and the finding is confirmed.
To enable OOB detection on your self-hosted instance:
- Create a DNS A record pointing a wildcard subdomain at your server IP:
DNS
*.oob.scan.example.com A 203.0.113.10 (your server IP)
- Set
OOB_DNS_DOMAIN=oob.scan.example.comin your.env. - Set
INTERNAL_SECRETto a strong random value (used to authenticate callbacks). - Restart the stack:
docker compose up -d
Shieldome's built-in DNS listener starts automatically when OOB_DNS_DOMAIN is configured. No additional software is required.
License key
On-premise deployments require a license key set as LICENSE_KEY in your .env. The app will start without a key in evaluation mode (limited scans per day); production use requires a valid license.
To obtain a license key, contact [email protected] with your company name and expected scan volume. Licenses are per-installation and tied to your APP_BASE_URL.