A free vulnerability scanner on your homelab. You click, you paste, you get a box that scans your LAN and gives you a report.
Full open-source OpenVAS on a Debian VM. No registration, no trial, current feeds, you control everything.
Start here โGreenbone's own prebuilt VM, imported as an OVA. Less setup, but needs an email request and 500 GB of disk.
See Path B โEverything happens in two places: the Proxmox web UI (port 8006) and a terminal inside the new VM. Each block has a copy button.
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.
Top-right Create VM. Only these tabs need touching โ leave everything else default:
| Tab | Set it to |
|---|---|
| General | Name openvas, tick Start at boot |
| OS | Storage local, ISO = the Debian one, Type = Linux |
| System | Defaults are fine (SeaBIOS, VirtIO SCSI, q35 off) |
| Disks | Bus VirtIO, size 80 GB, tick Discard |
| CPU | 4 cores, type host |
| Memory | 8192 MB |
| Network | Bridge vmbr0, model VirtIO |
Then start it and open Console.
You see the Debian installer boot menu.
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.
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.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.
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.
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.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.
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.)
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".
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.
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.192.168.50.38 โ your NPM host).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.
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
docker starts. Make sure the VM itself is set to Start at boot in Proxmox.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.
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.
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.
Select the OVA โ Import โ wizard:
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.
Log in at the console as admin / admin. The first-login wizard asks, in order:
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.
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.