0 / 0 steps

OpenVAS on the Debian VM you already have

A free vulnerability scanner deployed as a Portainer stack on your existing Proxmox VM. No new VM, no ISO, no Docker install — you already did that part.

Written for your setup: a Debian VM on Proxmox running Docker + Portainer. The stack is deployed from Portainer's web editor; the handful of steps Portainer can't do for you (setting the admin password, grepping logs, checking ports) are marked as VM-shell steps. The stack keeps its data in Docker named volumes, so a VM-level backup captures everything.
Naming trap, 10 seconds. "OpenVAS" is now Greenbone Community Edition — the free open-source stack, and what this page deploys. Greenbone also sells a separate free virtual appliance literally branded "OPENVAS FREE" (email-gated OVA, community feed, cut-down features) — that's Path B at the bottom. Path A is what you want.
Path A · recommended

Portainer stack on your VM

Seven steps, all inside the VM you already have. Rolling updates, full shell access, no extra hardware.

Start here →
Path B · optional

OPENVAS FREE appliance

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

See Path B →

Path A · on your existing VMDeploy as a Portainer stack

Two places: the VM's shell (SSH or Proxmox console) and the Portainer web UI. Blocks with a copy button are meant to be pasted.

1

Check the VM can take it

The scanner is the biggest thing most homelab VMs ever run. Three checks before you start:

free -h
df -h /var/lib/docker
ss -tlnp | grep -E ':(443|9392)\b' || echo "443 and 9392 are free"
CheckWhat you need
RAM8 GB minimum, 16 GB comfortable. 4 GB OOM-kills gvmd during the first sync.
Free disk40 GB+ on the Docker volume. Images ~8 GB, feed data ~32 GB measured.
Ports443 and 9392 free on the VM. Portainer's own 9000/9443 don't conflict.

You have ≥8 GB RAM, ≥40 GB free, and both ports show nothing listening.

Short on disk? Grow the VM disk in Proxmox (Hardware → Disk → Resize) and extend the filesystem inside the VM before deploying. Doing it later with the feed loaded is the annoying version.
2

Grab the compose file and open two ports

Greenbone ships one rolling compose file. It binds the web UI to 127.0.0.1 only, and the UI is HTTPS on 443 while 9392 just redirects to 443 — so both ports need publishing or the browser lands nowhere.

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 grep prints - 9392:9392 and - 443:443, neither with 127.0.0.1 in front.

You'll paste this file into Portainer in step 3, so leave it where it is — cat compose.yaml copies the whole thing for you.
3

Deploy it as a stack in Portainer

  1. Open Portainer → Stacks → Add stack.
  2. Name it greenbone.
  3. Build method: Web editor.
  4. Paste the whole file (from cat compose.yaml) into the editor.
  5. Deploy the stack.

Portainer pulls ~20 images on first deploy — several GB, 5–20 minutes. The stack page shows each container going from created to running; don't redeploy while it's pulling.

Stacks → greenbone lists ~20 containers, most running, none stuck restarting for more than a minute.

If Portainer refuses the YAML with an error mentioning name: delete the first line of the file (name: greenbone-community-edition) and deploy again. That key is standard docker compose, but older Portainer versions reject it — the stack name you typed does the same job.
Portainer in Swarm mode? Then deploy: keys behave differently and the self-signed cert setup may not come up cleanly. This guide assumes the normal Docker Standalone environment — check Environment details if unsure.
4

Set your admin password

Default is admin/admin. Portainer's console runs as root, but gvmd must run as the gvmd user — so this one is a VM shell command (SSH in, or Proxmox → Console):

docker exec -u gvmd "$(docker ps -qf name=gvmd | head -1)" \
  gvmd --user=admin --new-password='PickSomethingLong!42'

No output, no error. Replace the password inside the single quotes — a $ in it will otherwise be eaten by the shell.

5

Wait for the vulnerability feed

This is the slow part and where people give up. Greenbone loads ~100k vulnerability tests plus CVE/CPE data into Postgres. Watch it in Portainer: Stacks → greenbone → the ospd-openvas container → Logs, and wait for:

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

Then check the gvmd container's logs for the last gate:

Updating VTs in database ... done (XXXXX VTs).

Prefer the shell? Both at once:

docker logs -f "$(docker ps -qf name=ospd-openvas | head -1)" 2>&1 | grep --line-buffered -i "loading VTs"
docker logs -f "$(docker ps -qf name=gvmd | head -1)" 2>&1 | grep --line-buffered -i "Updating VTs in database"

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

Don't scan before both lines appear. Early scans don't fail loudly — they return wrong, incomplete reports. Expect 30–90 minutes; 8 GB of RAM makes it slower, not broken.
When it finishes, take a Proxmox snapshot of the VM. Rolling updates occasionally need a Postgres migration step; a snapshot turns a bad update into a 30-second rollback.
6

Open the web interface

From any machine on your LAN:

https://192.168.50.XXX/

Log in as admin with the password from step 4. The cert is generated by the stack's gvm-config container and self-signed, so expect a browser warning → Advanced → Proceed.

You get the Greenbone dashboard, not a connection error.

443 already taken on that VM? Map a different host port in the compose file (- 8443:443) and always browse https://<vm-ip>:8443/ directly — don't use :9392, because its redirect points at 443 and will fail.
Nothing loads? In the VM: curl -kI https://localhost. If that works but the LAN can't reach it, re-check step 2 — the usual cause is publishing 9392 but leaving 443 on 127.0.0.1.
7

Run your first scan

  1. Scans → Targets → new target: name it, host = one of your own boxes (e.g. the VM itself, or 192.168.50.38 — your NPM host).
  2. Scans → Tasks → new task: pick that target, scan config Full and fast, save.
  3. Hit ▶. Status Requested → Running → Done.
  4. Click the status bar to read the report; Report → Download for a PDF.

One host takes roughly 10–40 minutes depending on what's listening.

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

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

Keeping it alive

The stack is a rolling release — Greenbone ships one unversioned compose file with moving stable image tags, so "update" means: refresh the file, paste, redeploy. Do this every few weeks.

  1. Repeat step 2 in the VM (re-download + the two sed edits — the download overwrites them).
  2. Portainer → Stacks → greenbone → Editor → replace the contents with the new file → Update the stack.

If the version numbers in the UI haven't moved afterwards, the images weren't re-pulled. Force it from the VM shell, then update once more:

for i in gvmd gsa gsad openvas-scanner ospd-openvas pg-gvm; do
  docker pull registry.community.greenbone.net/community/$i:stable
done

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

Skip this unless you specifically want the vendor appliance or you're evaluating what a paid OPENVAS tier looks like. It is a different product from what Path A deploys.

B1

Request the download

Not a direct link: fill the form at greenbone.net/en/openvas-free/ (email + country + captcha) and they email the OVA. Minutes to a working day.

You have an .ova file, a few GB.

B2

Add a storage that accepts imports

Proxmox imports OVAs only from a file-based storage with the Import content type (wizard added in PVE 8.2).

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

Drop the OVA in that storage's import/ subfolder, or upload via 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 has an Import Working Storage field for that.
B3

Import with the wizard (three settings matter)

Select the OVA → Import → wizard:

  • Firmware: OVMF (UEFI) — Greenbone appliances require UEFI boot; an EFI disk gets added.
  • SCSI controller: VMware PVSCSI — not Virtio. The appliance's OS probes for VMware hardware; with Proxmox defaults the boot fails because "Greenbone thinks it's running on VMware". If the wizard doesn't offer it, 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. Swap any VirtIO disk to SCSI as well.
  • RAM 5 GB, 2 vCPU per Greenbone's spec; disk 500 GB, thin-provisioned.

After import: Options → Boot Order = imported disk, vmxnet3 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

Console login admin / admin, then the first-login wizard:

  • Start the wizard → Yes
  • Create the web administrator — the account for the browser UI
  • Subscription key → skip; with no key it uses the free Community Feed
  • Download the feed → Yes (background, ~30+ min), then let the self-check run

The console shows the appliance IP on login. Shut down via Maintenance → Power — not by yanking the VM, the feed updater dislikes it.

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

B5

Use the web UI

Browse to https://<appliance-ip>, accept the self-signed cert, log in with the web admin you created. Then Scans → Tasks → + New Task against your own LAN, same workflow as step 7.

Dashboard loads and a task runs to Done.

Path B, honestly