Skip to content

Installation

NetVuln Tool supports macOS (development) and Linux/Debian (deployment, including Raspberry Pi). All scan logic is pure Bash with no compiled binaries, and a Python orchestrator (netvuln) drives the same pipeline with typed data models. There are two supported install paths:

  • install.sh (this page, deployment path): sets up netvuln-tool for use on a scanning host or agent. It runs a preflight dependency check, installs the netvuln CLI, provisions a license key, scaffolds a per-engagement config, optionally installs the systemd daemon, and verifies portal connectivity.
  • setup.sh (developer path): sets up a development checkout (git hooks, lint dependencies, editable pip install). Use this when you intend to modify the tool, not just run it.

If you want a container instead of a host install, jump to the Docker guide. For always-on edge scanners, see Raspberry Pi deployment.

Platform Support

macOSLinux (Debian/Ubuntu/Raspberry Pi OS)
ScanningYesYes
systemd daemonNo (systemd is Linux-only; install.sh prints a notice)Yes
Recommended roleDevelopmentDeployment / agents

Requirements

install.sh installs everything in this table unprompted by default (apt on Linux, Homebrew on macOS); pass --minimal to skip that and fall back to warn-only checks with install hints instead. The table is still the reference for what each tool is for and how to install it by hand.

DependencyRequiredmacOSLinux (Debian/Ubuntu/Raspberry Pi)
Bash 4+Yesbrew install bashPre-installed (verify: bash --version)
nmapYesbrew install nmapsudo apt-get install -y nmap
jqRecommendedbrew install jqsudo apt-get install -y jq
python3 3.9+Recommendedbrew install pythonPre-installed on most distros
digOptionalPre-installedsudo apt-get install -y dnsutils
whoisOptionalPre-installedsudo apt-get install -y whois
opensslOptionalPre-installedPre-installed
curlOptionalPre-installedsudo apt-get install -y curl
sshOptionalPre-installedsudo apt-get install -y openssh-client
ncOptionalPre-installedsudo apt-get install -y netcat-openbsd
tracerouteOptionalPre-installedsudo apt-get install -y traceroute
smbclientOptionalbrew install sambasudo apt-get install -y smbclient
snmpwalk / snmpgetOptionalbrew install net-snmpsudo apt-get install -y snmp
wkhtmltopdfOptional (PDF export)brew install wkhtmltopdfsudo apt-get install -y wkhtmltopdf
msmtpOptional (email alerts)brew install msmtpsudo apt-get install -y msmtp
iwOptional (WiFi, Linux only)n/asudo apt-get install -y iw
rfkillOptional (WiFi, Linux only)n/asudo apt-get install -y rfkill
nmcliOptional (WiFi, Linux only)n/asudo apt-get install -y network-manager

Missing optional tools are gracefully skipped with a warning. iw, rfkill and nmcli are Linux-only and are never auto-installed on macOS.

Dependencies by purpose

ToolStatusPurpose
nmapRequiredCore scanning engine (host discovery, port/service detection, vuln scripts)
jqRecommendedJSON processing, required for HTML reports
python3RecommendedThe netvuln orchestrator CLI (recon/scan/upload/push/diff/status/daemon)
dig / host / nslookupOptionalDNS enumeration
whoisOptionalWHOIS / OSINT lookups
opensslOptionalSSL/TLS analysis
curlOptionalHTTP header checks, CVE CVSS lookups, session upload, license validation
sshOptionalSSH auth-method enumeration
nc / ncatOptionalSSH banner grabbing
tracerouteOptionalHop-distance / route discovery
smbclientOptionalSMB share enumeration
snmpwalk / snmpgetOptionalSNMP enumeration
wkhtmltopdfOptionalPDF export for executive summaries
msmtpOptionalEmail alerts and scan reminders (one of several accepted mail backends)
iwOptional (WiFi, Linux only)WiFi interface discovery
rfkillOptional (WiFi, Linux only)Unblocking a soft-blocked WiFi radio
nmcliOptional (WiFi, Linux only)WiFi network enumeration

Deployment install: install.sh

install.sh (repo root) prepares a host to run scans, either interactively (an analyst laptop) or as an unattended agent. It is idempotent and safe to re-run.

What it does

  1. Preflight: detects the platform (macOS or Linux) and installs the full scanner toolchain unprompted, skipping any binary already on PATH. On Linux it runs one batched apt-get update && apt-get install -y <packages>, falling back to installing each package individually (warning on any that fails) if the batch fails; on macOS it installs the Homebrew-formula subset per formula (WiFi tools iw, rfkill and nmcli are Linux-only and are only reported on macOS). Pass --minimal to skip all of this and fall back to the old warn-only nmap/jq check with install hints instead.
  2. Service account (Linux only): resolves who the daemon runs as and where the tree lives, either the current user (default) or a dedicated nvt account, always on Raspberry Pi and opt-in elsewhere with --service-user nvt. See Where things live below for the exact paths each choice produces.
  3. Python CLI: installs the netvuln console script (skip with --no-python). On an externally managed interpreter (see PEP 668 below) it builds a virtualenv and links the script into ~/.local/bin; elsewhere it runs pip install -e . directly. The venv path depends on step 2 (see Where things live).
  4. License key: installs the provided key (mode 600); the destination depends on step 2 (see Where things live). See License Provisioning for key formats and tiers.
  5. Config scaffold: creates a per-engagement config from templates/report_config.conf.example, filling in the API URL, client ID, and targets you passed; the destination depends on step 2 (see Where things live). The portal URL defaults to https://portal.netvulntool.com/api/upload (see Portal URL below).
  6. Systemd daemon (Linux only): installs and enables the netvuln-daemon service, but leaves scanning off until a config sets DAEMON_ENABLED=true with TARGETS. As of 4.9.0, install-service always renders the unit from explicit --user/--group/--home/--install-dir/--base-dir flags (install.sh supplies them) and refuses to render an implicit User=root unit; the daemon runs as the user step 2 resolved (see Where things live) and is granted CAP_NET_RAW (AmbientCapabilities=CAP_NET_RAW on the unit, plus a supplementary sudo setcap cap_net_raw+eip on the nmap binary), so nmap OS fingerprinting (-O) and SNMP/UDP scans (-sU) work without running as root. An nmap package upgrade resets that setcap capability, but this no longer needs a manual fix: the daemon's own scans keep working off the unit's AmbientCapabilities grant regardless, an apt post-invoke hook reapplies the file capability automatically after every apt/dpkg run, and the daemon self-checks the capability at startup and every heartbeat, logging a loud warning and reporting raw_scan_capable: false if it is ever actually lost. See Daemon Mode for the full picture. On macOS it prints a notice that systemd is Linux-only (use launchd or run the daemon in the foreground). Skip with --no-daemon.
  7. Portal verification: checks /api/health reachability and sends an authenticated heartbeat to confirm the license key and API URL are valid.
  8. Summary: prints a pi_validate.sh --json readiness summary and the next steps.

Where things live

Every path above depends on which account the daemon runs as (step 2), decided by --service-user, --pi/--no-pi, or the interactive prompt; see Raspberry Pi for the account itself.

PathDefault (current user)nvt path (Raspberry Pi by default, or --service-user nvt)
Install treethe checkout you ran install.sh from/opt/netvuln-tool (owned nvt:nvt)
Python venv~/.netvuln/venv/opt/netvuln-tool/venv
License key~/.netvuln/license.key/home/nvt/.netvuln/license.key
Configs~/netvuln-tool/configs/<name>.conf/opt/netvuln-tool/configs/<name>.conf
Daemon runs asthe invoking usernvt

PEP 668 and virtualenvs

Raspberry Pi OS (Bookworm and later), Debian 12+, Ubuntu 23.04+ and Homebrew Python mark their system interpreter as externally managed, which makes a system-wide pip install a hard error rather than a warning:

error: externally-managed-environment

install.sh detects this and installs into a virtualenv instead, so a stock Pi image needs no manual preparation:

PathPurpose
~/.netvuln/venvthe virtualenv holding the netvuln package
~/.local/bin/netvulnsymlink to the console script, no sudo required

If ~/.local/bin is not already on your PATH, the installer says so and prints the line to add:

bash
export PATH="$HOME/.local/bin:$PATH"

Debian packages the venv module separately. If the virtualenv cannot be created, install it and re-run:

bash
sudo apt-get install -y python3-venv

The netvuln CLI is optional. The Bash scan pipeline is self-contained, so a Python install that fails leaves scanning fully functional and only costs you the netvuln command.

Flags

FlagPurpose
--license-key <key>License key to install to ~/.netvuln/license.key (e.g. nvt_pro_<hex>)
--api-url <url>Portal upload endpoint. Defaults to https://portal.netvulntool.com/api/upload; pass none for no portal (see Portal URL)
--client-id <id>Client identifier injected into the config for portal multi-tenancy
--targets <spec>Comma-separated IPs, CIDRs, ranges, or domains for the scaffolded config
--config-name <name>Basename for the scaffolded config (see Where things live for the full path)
--service-user <name>Run the daemon as a dedicated account (nvt) instead of the current user. Prompted on non-Pi Linux when omitted; automatic (no prompt) on Raspberry Pi
--piForce Raspberry Pi behavior (auto-detected via /proc/device-tree/model otherwise)
--no-piForce non-Pi behavior on a host that looks like a Pi
--migrateDelegate to scripts/migrate_to_opt.sh (moves a hand-patched /home/nvt/netvuln-tool install onto the supported /opt/netvuln-tool layout) and exit
--minimalSkip the toolchain auto-install in preflight; only check for nmap/jq and print install hints (the pre-#208 behavior)
--no-daemonSkip installing/enabling the systemd service
--no-pythonSkip the pip install -e . step (bash-only install)
--verify-onlyRun the portal connectivity + readiness checks only, no install steps
--full-verifyRun the extended verification (health + authenticated heartbeat + pi_validate)
--offlineSkip the portal connectivity check (step 7/8). Preflight's toolchain install still runs; use --minimal to skip that too
--non-interactive, --yesAssume defaults and never prompt (agent/automation mode); the toolchain install already runs unprompted either way
-h, --helpShow usage

Portal URL

--api-url defaults to https://portal.netvulntool.com/api/upload, the hosted portal. The interactive prompt offers it, so Enter accepts it:

  Portal upload URL ('none' for no portal) [https://portal.netvulntool.com/api/upload]:

The same default applies to --non-interactive runs that pass no --api-url, so an unattended agent is portal-connected out of the box. Three ways to change that:

You wantDo this
A self-hosted portalType the URL at the prompt, or pass --api-url <your-portal-host>/api/upload
No portal at allType none at the prompt, or pass --api-url none. The config gets an empty CONSULTATION_API_URL and step 7 is skipped
A portal, but no network calls during installPass --offline. The URL is still written to the config; only the verification is skipped

Because a URL is now always configured by default, step 7 runs on every install rather than being skipped. Uploads still require an API key as well, so a config with a URL and no key does not send anything.

Example: unattended agent install

bash
bash install.sh --non-interactive \
  --license-key nvt_pro_<hex> \
  --api-url https://portal.netvulntool.com/api/upload \
  --client-id acme \
  --targets 192.168.1.0/24

This installs the CLI, writes the license key, scaffolds ~/netvuln-tool/configs/acme.conf with the URL/client/targets pre-filled, installs the systemd daemon (Linux), verifies portal connectivity, and prints a readiness summary. The daemon stays idle until you set DAEMON_ENABLED=true in that config.

Enable scheduled scanning after install

install.sh installs the daemon but does not start scanning. Edit the scaffolded config, set DAEMON_ENABLED="true" with a SCAN_SCHEDULE and TARGETS, then reload the daemon. See Daemon Mode and Scheduling.

Only scan authorized networks

Provisioning targets in a config does not grant authorization. Only scan hosts and networks you are explicitly authorized to assess.

Developer install: setup.sh

The public repository and the download addresses go live with the first public release of 4.10.0; if a link does not resolve yet, the release has not been published.

Use setup.sh when you are working on netvuln-tool itself. The source is public: clone it directly, or download a release tarball and verify it against its checksum. Clone the repository and run setup.sh once:

bash
git clone https://gitlab.com/netvulntool/netvuln-tool.git
cd netvuln-tool
bash setup.sh

Prefer a release tarball over a git clone? Download and verify it (replace vX.Y.Z with the release you want; /download/latest and /download/latest.sha256 on the same host always resolve to the current release):

bash
curl -Lfo netvuln-tool-vX.Y.Z.tar.gz https://netvulntool.com/download/vX.Y.Z
curl -Lfo netvuln-tool-vX.Y.Z.tar.gz.sha256 https://netvulntool.com/download/vX.Y.Z.sha256
sha256sum -c netvuln-tool-vX.Y.Z.tar.gz.sha256   # Linux
shasum -a 256 -c netvuln-tool-vX.Y.Z.tar.gz.sha256   # macOS

The /download/ addresses resolve to the assets on the GitLab release page at gitlab.com/netvulntool/netvuln-tool/-/releases, where the same files can be fetched directly if an alias is not yet in place.

The tarball extracts into a single top-level netvuln-tool-vX.Y.Z/ directory.

See the open source boundary for the full license and functional boundary.

setup.sh performs a five-step developer bootstrap:

  1. Configures git hooks (git config core.hooksPath .githooks) so the pre-commit ShellCheck lint and pre-push test suite run automatically.
  2. Checks linting dependencies (shellcheck, bats) and prints install hints for any that are missing.
  3. Checks runtime dependencies (nmap, jq).
  4. Installs the Python orchestrator in editable mode with dev extras (pip install -e ".[dev]"), putting the netvuln CLI on your PATH. Unlike install.sh, the developer path does not build a virtualenv for you: on an externally managed interpreter it prints pip's error and the venv command to run instead (python3 -m venv .venv && .venv/bin/pip install -e '.[dev]').
  5. Verifies the git hooks are executable.

It does not install a license, scaffold an engagement config, or install the systemd daemon; those belong to the deployment path (install.sh).

Dependency check

At any time, verify your environment with:

bash
bash scripts/dependency_check.sh

This detects your platform (macOS or Linux) and prints the correct install command for each missing tool: brew install on macOS, apt-get install on Linux. It reports and prompts; it does not batch-install the way install.sh's default preflight does. Useful for a standalone check outside of a full install.sh run, or after --minimal.

Platform validation

For deployment readiness (especially on Raspberry Pi or other edge devices), use the platform validation script:

bash
bash scripts/pi_validate.sh          # Run the deployment checks
bash scripts/pi_validate.sh --json   # JSON output (used by install.sh's summary)
bash scripts/pi_validate.sh --fix    # Attempt to install missing dependencies

It checks disk space, memory, required tools, permissions, and portal (/api/health) reachability, and can emit JSON for monitoring integration. Combine flags, for example pi_validate.sh --fix --json.

Next steps

Apache-2.0 licensed (appliance subtree proprietary)