Install DefectDojo with Docker and HAProxy on Ubuntu 24.04

DefectDojo is an open-source application vulnerability management system designed to help security teams track, triage, and report security findings at scale.

Originally created by the US Department of Defense, DefectDojo has grown into a mature platform trusted by many organizations. It supports:

  • Automated imports from tools like OWASP ZAP, Burp Suite, Nmap, and Nessus
  • Integration with CI/CD pipelines
  • Assigning and tracking remediation efforts
  • Metrics and dashboards to monitor security posture
  • Multi-user and team collaboration with role-based access control

In this guide, you’ll learn how to install DefectDojo using:

  • Docker Compose (release mode)
  • HAProxy to securely terminate SSL
  • Let’s Encrypt with Cloudflare DNS for free HTTPS
  • A systemd service to manage startup on Ubuntu 24.04

This production-ready setup ensures DefectDojo is secure, automated, and easy to maintain.


Prerequisites

  • Ubuntu 24.04 server
  • Docker & Docker Compose installed
  • Install Docker on Ubuntu 24.04
  • A domain name pointing to your server (e.g. defectdojo.maksonlee.com)
  • Cloudflare API Token with DNS edit access

  1. Install DefectDojo (Release Mode)

Clone and configure DefectDojo:

git clone https://github.com/DefectDojo/django-DefectDojo.git
sudo mv django-DefectDojo /opt/defectdojo
cd /opt/defectdojo

docker/setEnv.sh release

Restrict DefectDojo’s Nginx to localhost only:

# /opt/defectdojo/docker-compose.override.yml
services:
  nginx:
    ports: !override
      - "127.0.0.1:80:8080"

Do not start DefectDojo manually. We’ll configure it to start via systemd later.


  1. Issue HTTPS Certificate via Cloudflare DNS

Install Certbot and Cloudflare plugin:

sudo apt install -y certbot python3-certbot-dns-cloudflare

Create Cloudflare credentials:

mkdir -p ~/.secrets/certbot
vi ~/.secrets/certbot/cloudflare.ini

Add:

dns_cloudflare_api_token = YOUR_CLOUDFLARE_API_TOKEN

Secure the file:

chmod 600 ~/.secrets/certbot/cloudflare.ini

Request certificate:

sudo certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials ~/.secrets/certbot/cloudflare.ini \
  -d defectdojo.maksonlee.com

  1. Bundle Certificate for HAProxy
sudo mkdir -p /etc/haproxy/certs/
sudo bash -c "cat /etc/letsencrypt/live/defectdojo.maksonlee.com/fullchain.pem \
  /etc/letsencrypt/live/defectdojo.maksonlee.com/privkey.pem \
  > /etc/haproxy/certs/defectdojo.maksonlee.com.pem"
sudo chmod 600 /etc/haproxy/certs/defectdojo.maksonlee.com.pem

  1. Configure HAProxy for SSL Termination

Edit /etc/haproxy/haproxy.cfg:

frontend https_in
    bind *:443 ssl crt /etc/haproxy/certs/ alpn h2,http/1.1
    mode http
    default_backend defectdojo

backend defectdojo
    mode http
    option http-buffer-request
    option http-keep-alive
    option forwardfor
    http-request set-header X-Forwarded-Proto https

    server defectdojo1 127.0.0.1:8080

Restart HAProxy:

sudo systemctl restart haproxy

  1. Automate Certificate Renewal

Create deploy hook to reload HAProxy on renewal:

sudo tee /etc/letsencrypt/renewal-hooks/deploy/reload-haproxy.sh > /dev/null <<EOF
#!/bin/bash
cat /etc/letsencrypt/live/defectdojo.maksonlee.com/fullchain.pem \
    /etc/letsencrypt/live/defectdojo.maksonlee.com/privkey.pem \
    > /etc/haproxy/certs/defectdojo.maksonlee.com.pem
systemctl reload haproxy
EOF

sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-haproxy.sh

Test renewal:

sudo certbot renew --dry-run

  1. Create a systemd Service for DefectDojo

Create the /etc/systemd/system/defectdojo.service service file:

[Unit]
Description=DefectDojo
After=network-online.target docker.service
Requires=docker.service

[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/django-DefectDojo
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=0

[Install]
WantedBy=multi-user.target

Enable and start it:

sudo systemctl daemon-reexec
sudo systemctl daemon-reload
sudo systemctl enable --now defectdojo

  1. Retrieve Auto-Generated Admin Password

After the first run, retrieve the admin password:

docker compose logs initializer | grep "Admin password:"

Sample output:

initializer-1  | Admin password: hNBbmXkReXnDNMk2qm12gw

Default username:

admin

  1. Access DefectDojo

Open:

https://defectdojo.maksonlee.com

Login with the username admin and the password retrieved in Step 7. You’ll be prompted to change it on first login.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top