Security Azure

Dependency-Track on Ubuntu 24.04 on Azure User Guide

| Product: Dependency-Track on Ubuntu 24.04 LTS on Azure

Overview

Dependency-Track is the OWASP flagship platform for software supply chain component analysis. You upload a CycloneDX SBOM (Software Bill of Materials) for each project you ship, and Dependency-Track keeps an always-current inventory of every component in that software, continuously re-evaluating it against vulnerability intelligence as new advisories are published. Rather than telling you what was vulnerable the day you scanned, it tells you what is vulnerable now — which is why it is used to run software supply chain risk programmes across large portfolios.

The cloudimg image installs the official Dependency-Track 5.0.2 API server distribution and the official frontend single-page application, both verified against the upstream release SHA256 checksums at build time. The API server runs under a dedicated non-root dtrack service user on the OpenJDK 25 JRE, with nginx in front as the only public listener: it serves the frontend on port 80 and reverse-proxies /api to the API server. A local PostgreSQL is the backing store — Dependency-Track 5.x requires PostgreSQL and no longer supports an embedded database.

Dependency-Track seeds a well-known default admin / admin account. On the first boot of every deployed VM that password is rotated to a unique per-VM value, the rotation is verified, and the default credential is confirmed rejected before the VM is handed over. The result is written to /root/dependency-track-credentials.txt with mode 0600, so no two VMs ever share credentials and the shipped default is never usable. Backed by 24/7 cloudimg support.

What is included:

  • Dependency-Track 5.0.2 API server (/opt/dependency-track) on the OpenJDK 25 JRE, run as the non-root dtrack user
  • The official Dependency-Track frontend SPA served by nginx on :80, with /api reverse-proxied to the API server and an unauthenticated /health endpoint
  • PostgreSQL 16 as the backing database, bound to loopback only
  • A dedicated 40 GiB Azure data disk at /var/lib/dependency-track holding the API server data directory and the PostgreSQL datadir — separate from the OS disk and re-provisioned with every VM
  • An nftables ruleset keeping the API server port 8080 and the management port 9000 off the public interface, so nginx on :80 is the only way in
  • Telemetry submission disabled by default
  • JVM heap sized automatically at first boot from the VM's actual memory
  • Per-VM admin password, rotated at first boot, in a root-only file
  • dependency-track.service, postgresql.service, nginx.service and nftables.service as systemd units, enabled and active
  • 24/7 cloudimg support

Prerequisites

An active Azure subscription, an SSH key pair, and a VNet + subnet in the target region. Standard_B4ms (4 vCPU / 16 GiB RAM) is the recommended starting point — the API server JVM, its analysis workers and PostgreSQL share the VM, and vulnerability database mirroring is memory and IO hungry. NSG inbound: allow 22/tcp from your management network and 80/tcp from the networks your users and CI runners will reach Dependency-Track on (front port 80 with TLS for public exposure — see Enabling HTTPS).

Step 1 — Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Dependency-Track by cloudimg, and select Create. On Basics pick your subscription, resource group, region and size; under Administrator account choose SSH public key and paste your key; under Inbound port rules allow SSH (22) and HTTP (80). Review the dedicated data disk on the Disks tab, then Review + createCreate.

First boot initialisation takes approximately three to five minutes after the VM starts — Dependency-Track runs its database migrations, seeds its default objects and rotates the admin password on first boot.

Step 2 — Deploy from the Azure CLI

az vm create \
  --resource-group my-resource-group \
  --name my-dependency-track \
  --image cloudimg:dependency-track-ubuntu-24-04:default:latest \
  --size Standard_B4ms \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard

az vm open-port --resource-group my-resource-group --name my-dependency-track --port 80

Step 3 — Connect to your VM

ssh azureuser@<vm-ip>

Step 4 — Confirm the services are running

systemctl is-active dependency-track.service postgresql.service nginx.service nftables.service
curl -s -o /dev/null -w 'health: HTTP %{http_code}\n' http://127.0.0.1/health
curl -s http://127.0.0.1/api/version

All four units report active, the health endpoint returns 200, and the version endpoint reports Dependency-Track 5.0.2.

Dependency-Track services active, listeners, the open health endpoint and the reported API version

Step 5 — Retrieve your administrator login

Every VM generates its own administrator password at first boot. The shipped admin / admin default is rotated and then verified to be rejected, so it can never be used against your instance.

sudo cat /root/dependency-track-credentials.txt
sudo stat -c '%n mode=%a owner=%U:%G' /root/dependency-track-credentials.txt

The file is mode 600, owned by root, and holds DTRACK_USERNAME and DTRACK_ADMIN_PASSWORD for this VM only.

The per-VM administrator login generated at first boot, the authenticated round-trip, and the default admin credential being rejected

Step 6 — First sign-in

Browse to http://<vm-ip>/ and sign in as admin with the password from Step 5.

The Dependency-Track sign-in page

You can confirm the same credential over the API, and confirm the shipped default is dead:

PASS=$(sudo grep '^DTRACK_ADMIN_PASSWORD=' /root/dependency-track-credentials.txt | cut -d= -f2-)
TOKEN=$(curl -s -X POST http://127.0.0.1/api/v1/user/login \
  --data-urlencode "username=admin" --data-urlencode "password=$PASS")
curl -s -o /dev/null -w 'authenticated API call: HTTP %{http_code}\n' \
  -H "Authorization: Bearer $TOKEN" http://127.0.0.1/api/v1/team
curl -s -o /dev/null -w 'default admin/admin: HTTP %{http_code} (401 expected)\n' \
  -X POST http://127.0.0.1/api/v1/user/login \
  --data-urlencode "username=admin" --data-urlencode "password=admin"

Step 7 — Upload your first SBOM

Dependency-Track is driven by SBOMs. Generate a CycloneDX SBOM for your project with a tool such as cyclonedx-npm, cyclonedx-maven-plugin or syft, then upload it. The example below creates a small SBOM and uploads it so you can see the whole path working end to end.

cat > /tmp/example-bom.json <<'BOM'
{
  "bomFormat": "CycloneDX",
  "specVersion": "1.5",
  "version": 1,
  "components": [
    {"type":"library","group":"org.apache.logging.log4j","name":"log4j-core","version":"2.14.1","purl":"pkg:maven/org.apache.logging.log4j/log4j-core@2.14.1"},
    {"type":"library","name":"lodash","version":"4.17.15","purl":"pkg:npm/lodash@4.17.15"}
  ]
}
BOM

PASS=$(sudo grep '^DTRACK_ADMIN_PASSWORD=' /root/dependency-track-credentials.txt | cut -d= -f2-)
TOKEN=$(curl -s -X POST http://127.0.0.1/api/v1/user/login \
  --data-urlencode "username=admin" --data-urlencode "password=$PASS")

UPLOAD_TOKEN=$(jq -nc --arg b "$(base64 -w0 < /tmp/example-bom.json)" \
  '{projectName:"example-app", projectVersion:"1.0.0", autoCreate:true, bom:$b}' \
  | curl -s -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
    -X PUT http://127.0.0.1/api/v1/bom --data-binary @- | jq -r .token)
echo "upload token: $UPLOAD_TOKEN"

Processing is asynchronous. Poll until it completes, then confirm the components were analysed:

PASS=$(sudo grep '^DTRACK_ADMIN_PASSWORD=' /root/dependency-track-credentials.txt | cut -d= -f2-)
TOKEN=$(curl -s -X POST http://127.0.0.1/api/v1/user/login \
  --data-urlencode "username=admin" --data-urlencode "password=$PASS")
PROJECT_UUID=$(curl -s -H "Authorization: Bearer $TOKEN" \
  --get --data-urlencode "name=example-app" --data-urlencode "version=1.0.0" \
  http://127.0.0.1/api/v1/project/lookup | jq -r .uuid)
curl -s -H "Authorization: Bearer $TOKEN" \
  "http://127.0.0.1/api/v1/component/project/$PROJECT_UUID?limit=20" \
  | jq -r '.[] | "\(.name) \(.version)  \(.purl)"'

The projects tracked in this instance and the components Dependency-Track analysed from the uploaded SBOM

In the web interface the uploaded project appears under Projects, with its BOM format and last import time.

The Dependency-Track projects list showing an imported CycloneDX SBOM

Step 8 — Review the analysed components

Open a project and choose Components to see every component Dependency-Track extracted from the SBOM, each with its Package URL. This inventory is what every future advisory is evaluated against.

The Dependency-Track components view listing analysed components and their Package URLs

Step 9 — Review vulnerabilities

Vulnerabilities shows the vulnerability intelligence Dependency-Track has mirrored, and Vulnerability Audit is where findings against your own projects are triaged. Mirroring the full National Vulnerability Database on a new instance runs in the background and takes a while to complete on first boot; findings against your projects populate as it does.

The Dependency-Track vulnerabilities view showing mirrored advisories with CWE and severity

Step 10 — Confirm the data tiers

findmnt -no SOURCE,TARGET,FSTYPE /var/lib/dependency-track
sudo -u postgres psql -tAc 'SHOW data_directory'
grep '^DT_DATA_DIRECTORY=' /etc/dependency-track/dependency-track.env

Both the PostgreSQL datadir and the API server data directory sit on the dedicated Azure data disk, so they are independently resizable and separate from the OS disk.

sudo nft list table inet cloudimg_dtrack

The ruleset keeps ports 8080 and 9000 off the public interface — nginx on :80 is the only way in.

The persisted data tiers on the dedicated Azure data disk and the nftables ruleset protecting the internal ports

Enabling HTTPS

Dependency-Track handles SBOMs and vulnerability data for your software estate, so terminate TLS before exposing it beyond a trusted network. Point a DNS record at the VM, then use certbot to obtain a certificate and update the nginx site:

sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d dependency-track.your-domain.com --redirect --agree-tos -m you@your-domain.com

Certbot rewrites /etc/nginx/sites-available/cloudimg-dependency-track to listen on :443 with your certificate and redirects :80 to :443. Renewal is handled by the packaged systemd timer. Once TLS is in place, restrict 80/tcp and 443/tcp in the NSG to the networks that need access.

Backup and maintenance

The backing database is the thing to back up — it holds every project, SBOM inventory, finding and audit decision:

sudo -u postgres pg_dump -Fc dtrack > /var/tmp/dtrack-$(date +%F).dump
ls -lh /var/tmp/dtrack-*.dump

Copy the dump off the VM (Azure Blob Storage, or an Azure Backup policy on the data disk). Because both the database and the API server data directory live on /var/lib/dependency-track, a disk snapshot of that data disk captures the full application state.

Operating system security updates are delivered by Ubuntu's unattended-upgrades, which is enabled in the image. To upgrade Dependency-Track itself, follow the upstream release notes — the API server is a self-contained distribution in /opt, and the frontend is a static bundle served by nginx.

Support

This image is published and supported by cloudimg. For help with deployment or configuration, contact support@cloudimg.co.uk. Product documentation for Dependency-Track is at docs.dependencytrack.org.