0 / 0 steps

OpenVAS on Proxmox, step by step

A free vulnerability scanner on your homelab. You click, you paste, you get a box that scans your LAN and gives you a report.

Naming trap, read this first. "OpenVAS" is now called Greenbone Community Edition โ€” that's the free, open-source scanner, and it's Path A below. Greenbone also sells a separate free virtual appliance literally branded "OPENVAS FREE" (email-gated, community feed, cut-down features) โ€” that's Path B. Path A is what most people actually want.
Path A ยท recommended

Community Edition in Docker

Full open-source OpenVAS on a Debian VM. No registration, no trial, current feeds, you control everything.

Start here โ†’
Path B ยท optional

OPENVAS FREE appliance

Greenbone's own prebuilt VM, imported as an OVA. Less setup, but needs an email request and 500 GB of disk.

See Path B โ†’

Path A ยท recommendedOpenVAS Community Edition on a Debian VM

Everything happens in two places: the Proxmox web UI (port 8006) and a terminal inside the new VM. Each block has a copy button.

1

Grab the Debian 13 installer into Proxmox

In the Proxmox web UI: click your node โ†’ local (under Datacenter) โ†’ ISO Images โ†’ Download from URL โ†’ paste this:

https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-13.7.0-amd64-netinst.iso

Then Query URL โ†’ Download. It's ~700 MB. If the filename ever 404s (Debian bumps point releases), open this folder and copy the newest netinst.iso link.

The ISO shows up in the list on the left.

2

Create the VM (4 cores / 8 GB / 80 GB)

Top-right Create VM. Only these tabs need touching โ€” leave everything else default:

TabSet it to
GeneralName openvas, tick Start at boot
OSStorage local, ISO = the Debian one, Type = Linux
SystemDefaults are fine (SeaBIOS, VirtIO SCSI, q35 off)
DisksBus VirtIO, size 80 GB, tick Discard
CPU4 cores, type host
Memory8192 MB
NetworkBridge vmbr0, model VirtIO

Then start it and open Console.

You see the Debian installer boot menu.

3

Install Debian (plain, no desktop)

Choose Install (the non-graphical one). Then: language โ†’ Singapore/manual location โ†’ keyboard โ†’ hostname openvas โ†’ root password โ†’ create a normal user (e.g. gvm) โ†’ Guided, use entire disk โ†’ All files in one partition โ†’ mirror deb.debian.org โ†’ no proxy.

On the software screen untick Debian desktop environment and GNOME; tick only SSH server and standard system utilities.

Install GRUB to the disk, reboot, then detach the ISO (VM โ†’ Hardware โ†’ CD/DVD Drive โ†’ Edit โ†’ Do not use any media) so it boots from disk.

You land on a openvas login: prompt. Log in as your user.

Find the VM's IP any time with ip -4 addr show scope global โ€” you'll need it in step 9. You can also SSH in from your laptop and forget the console.
4

Install Docker

Paste this whole block into the VM (it's the official Docker apt-repo method for Debian 13):

sudo apt update
sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/debian
Suites: $(. /etc/os-release && echo "$VERSION_CODENAME")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

docker --version and docker compose version both print a version.

5

Download Greenbone's compose file + open the web port

By default both ports are bound to 127.0.0.1 inside the VM. Modern Greenbone runs HTTPS by default and redirects 9392 to 443, so you must publish both or the browser lands on a port nothing is listening on:

mkdir -p ~/greenbone && cd ~/greenbone
curl -fsSLO https://greenbone.github.io/docs/latest/_static/compose.yaml
sed -i 's|- 127.0.0.1:9392:9392|- 9392:9392|; s|- 127.0.0.1:443:443|- 443:443|' compose.yaml
grep -nE '443|9392' compose.yaml

The output shows - 9392:9392 and - 443:443, neither with 127.0.0.1 in front.

Re-run the sed every time you re-download the file. Updating the stack (see the end) overwrites compose.yaml and resets the port binding โ€” you'd wonder why the UI is suddenly unreachable.
6

Start the stack

cd ~/greenbone
docker compose -f compose.yaml up -d

First run pulls ~20 container images (several GB) โ€” 5 to 20 minutes on a decent line. It's not frozen, it's downloading.

docker compose -f compose.yaml ps lists containers, none stuck in Restarting for more than a minute.

7

Set your own admin password

The default is admin/admin. Change it now โ€” replace the password inside the single quotes:

cd ~/greenbone
docker compose -f compose.yaml exec -u gvmd gvmd \
  gvmd --user=admin --new-password='PickSomethingLong!42'

No error output. (Keep single quotes โ€” a $ in the password will otherwise get eaten by the shell.)

8

Wait for the vulnerability feed โ€” the slow part

This is where people give up too early. Greenbone has to load ~100k vulnerability tests plus CVE/CPE data into its database. Watch it:

cd ~/greenbone
docker compose -f compose.yaml logs -f ospd-openvas | grep --line-buffered -i "loading VTs"

Wait for this line, then Ctrl-C:

Finished loading VTs. The VT cache has been updated from version X to Y.

Then confirm gvmd pushed them into the database (this is the last gate):

docker compose -f compose.yaml logs -f gvmd | grep --line-buffered -i "Updating VTs in database"
Updating VTs in database ... done (XXXXX VTs).

You saw both "Finished loading VTs" and "Updating VTs in database ... done".

Don't scan before this finishes. Scans started early don't fail loudly โ€” they just come back with wrong, incomplete results.
First load is typically 30โ€“90 minutes. Take a Proxmox snapshot of the VM once it's done, so a future botched update costs you a rollback instead of another hour.
9

Open the web interface

From any machine on your LAN:

https://192.168.50.XXX/

Log in as admin with the password from step 7. The certificate is generated by the stack's gvm-config container and self-signed, so the browser will warn โ€” Advanced โ†’ Proceed. Typing :9392 also works; it 302-redirects to 443, which is why step 5 publishes both ports.

You get the Greenbone dashboard, not a connection error.

Page won't load? Check the VM is up (docker compose ps), check you used the VM's IP not Proxmox's, and confirm from inside the VM: curl -kI https://localhost. If that works but the LAN can't reach it, the sed in step 5 didn't apply โ€” most often because only 9392 was rebound and 443 was left on 127.0.0.1.
10

Run your first scan

  1. Scans โ†’ Targets โ†’ new target: name it, host = one of your own boxes (e.g. 192.168.50.38 โ€” your NPM host).
  2. Scans โ†’ Tasks โ†’ new task: pick that target, scan config Full and fast, save.
  3. Hit the โ–ถ play icon. Status Requested โ†’ Running โ†’ Done.
  4. Click the status bar to read the report; Report โ†’ Download gives you a PDF.

A single host takes roughly 10โ€“40 minutes depending on how much is listening on it.

A report with findings (or a clean bill of health) exists.

Only scan what you own. Scanning IPs you don't control is illegal in most places including Singapore (Computer Misuse Act). Stick to your own LAN.

Keeping it alive

The container setup is now a rolling release โ€” Greenbone ships one unversioned compose file and moving stable image tags, so "update" means pull and recreate. Every few weeks:

cd ~/greenbone
curl -fsSLO https://greenbone.github.io/docs/latest/_static/compose.yaml
sed -i 's|- 127.0.0.1:9392:9392|- 9392:9392|; s|- 127.0.0.1:443:443|- 443:443|' compose.yaml
docker compose -f compose.yaml pull
docker compose -f compose.yaml up -d

Path B ยท optionalGreenbone's "OPENVAS FREE" appliance (OVA)

Pick this only if you'd rather not touch a shell. It's a locked-down prebuilt appliance: you import a virtual disk, answer a text wizard, and use the web UI. Trade-offs listed honestly at the bottom.

B1

Request the download

The OVA is not a direct link โ€” you fill the form at greenbone.net/en/openvas-free/ (email + country + captcha) and they email you the file. Takes minutes to a working day.

You have an .ova file, a few GB.

B2

Add a storage that accepts imports

Proxmox can import OVAs (wizard added in PVE 8.2), but only from a file-based storage that has the Import content type enabled.

Datacenter โ†’ Storage โ†’ Add โ†’ Directory โ†’ path e.g. /var/lib/vz/import (create it first: mkdir -p /var/lib/vz/import on the node shell), content types: tick Import and Disk image.

Put the OVA in that folder's import/ subfolder, or upload it through Storage โ†’ Import โ†’ Upload.

The OVA appears in that storage's Import tab.

Proxmox needs roughly the OVA size again as scratch space while extracting โ€” the wizard lets you pick an Import Working Storage for that.
B3

Import with the wizard (three settings matter)

Select the OVA โ†’ Import โ†’ wizard:

  • Firmware: OVMF (UEFI) โ€” Greenbone appliances require UEFI boot, and an EFI disk gets added.
  • SCSI controller: VMware PVSCSI โ€” not Virtio. The appliance's OS probes for VMware hardware; with Proxmox defaults the install/boot fails because "Greenbone thinks it's running on VMware" but can't find what it expects. If the wizard doesn't offer PVSCSI, import first, then set Hardware โ†’ SCSI Controller.
  • NIC model: vmxnet3 โ€” the appliance doesn't understand the default E1000 and may come up with no network. Also swap any VirtIO disk to SCSI.
  • RAM 5 GB, 2 vCPU per Greenbone's spec; disk 500 GB, thin-provisioned so it doesn't eat the pool.

After import: Options โ†’ Boot Order = the imported disk, vmxnet3 NIC on vmbr0, then start it and open Console.

You reach the GOS administration menu (text-based) instead of a boot error.

B4

Run the setup wizard

Log in at the console as admin / admin. The first-login wizard asks, in order:

  • Start the wizard โ†’ Yes
  • Create a web administrator (username + password) โ€” this is the account for the browser UI
  • Subscription key โ†’ skip it. With no key it falls back to the free Community Feed, which is what you want
  • Download the feed โ†’ Yes (runs in the background, ~30+ minutes), then let the self-check finish

The console prints the appliance's IP when you log in. Later, change the default admin password from the GOS menu (Maintenance โ†’ Power is also where you shut it down โ€” don't just pull the plug, the feed updater hates it).

Self-check passes and the GOS menu shows the web interface URL.

B5

Use the web UI

Browse to https://<appliance-ip> and log in with the web admin you created. The cert is self-signed, so accept the browser warning.

Then Scans โ†’ Tasks โ†’ + New Task, create a target on your own LAN, and start it โ€” same workflow as Path A step 10.

Dashboard loads and a task runs to Done.

Path B, honestly