Docs
← Home Sign In Get Started

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.

🛡️
This guide uses Docker Compose to orchestrate the app, PostgreSQL, Redis, and background workers. For Kubernetes or bare-metal Python deployments, contact us for dedicated deployment guides.

Requirements

  • Docker 24+ and Docker Compose v2+ (docker compose command)
  • 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:

bash
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

bash
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 password
  • DATABASE_URL - uncomment and update with your Postgres password
  • APP_BASE_URL - your public domain, e.g. https://scan.example.com
  • LICENSE_KEY - your on-premise license key
bash
# Generate a secure secret key
python -c "import secrets; print(secrets.token_hex(32))"

3. Start the stack

bash
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:

bash
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.

Caddyfile
scan.example.com {
    reverse_proxy localhost:5000
}
bash
# 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

nginx.conf
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;
    }
}
bash
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d scan.example.com
⚠️
The 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:

bash
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:

bash
# 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.

💡
Automate backups with a cron job or a tool like pg-backups. Store dumps offsite - S3, Backblaze B2, or a separate server.

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:

  1. 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)
  2. Set OOB_DNS_DOMAIN=oob.scan.example.com in your .env.
  3. Set INTERNAL_SECRET to a strong random value (used to authenticate callbacks).
  4. 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.