Hostveil / Docs / Installation

Installation

One command installs a single binary. There is no config file to write and no account to create — after installing, you can scan immediately.

Quick install

The installer detects your OS and architecture, downloads the release binary, verifies its checksum, and installs it to /usr/bin/hostveil:

curl -fsSL https://hostveil.seolcu.com/install.sh | bash

Run the same command any time to update to the latest release. Then verify:

hostveil version
Supported platforms

Hostveil audits Linux hosts. Prebuilt binaries are published for Linux and macOS on amd64 and arm64, and the macOS build runs — but every detection rule in it is about Linux, so on a Mac most domains report N/A and the score is drawn from the two that do not. See Running it on macOS before you read a number it gives you there.

What the installer does

  • Detects your OS (linux/darwin) and architecture (amd64/arm64).
  • Downloads the release tarball and hostveil-checksums.txt, then verifies the SHA-256 checksum. On a mismatch it aborts.
  • Installs the binary to /usr/bin/hostveil with sudo (mode 0755) and runs hostveil --version as a sanity check.
  • Offers to install Trivy for optional image CVE scanning. Declining never blocks the Hostveil install.

Installer options

OptionEffect
--version vX.Y.ZInstall a specific release instead of the latest.
--no-trivySkip the optional Trivy prompt entirely.
--yes / -yRun non-interactively (accept prompts).

Pass options through the pipe with bash -s --, for example:

curl -fsSL https://hostveil.seolcu.com/install.sh | bash -s -- --no-trivy

Elevation is automatic

Heads up

The SSH and firewall checks read root-owned files (such as sshd_config), and applying fixes writes to protected paths. So hostveil re-runs itself under sudo automatically — you'll see the same sudo password prompt as sudo hostveil, and after authenticating it continues in the same terminal. version and help never prompt. To run unprivileged (scripts/CI), set HOSTVEIL_NO_SUDO=1; the root-owned domains are then skipped with a clear message and the score is renormalized so you are not handed a misleadingly perfect result.

Optional tools

Every domain is skipped cleanly if its tooling is absent. Add these when you want the extra coverage:

ToolUnlocksNotes
DockerThe Docker / Compose auditHostveil reads your Compose files to audit services.
TrivyImage CVE scanningUsed if present; the installer can set it up for you.
OllamaAI explanations (explain --ai)Local by default — nothing leaves your host. Not required: set HOSTVEIL_AI_PROVIDER=anthropic or openai to use an external API instead, useful on a host too small to run a local model. See AI explanations.

Debian and RPM packages

Every release also ships .deb and .rpm packages, for people who would rather not pipe a script into a shell — a reasonable preference, especially for a security tool. Download the one matching your architecture from the latest release and install it with your package manager:

sudo apt install ./hostveil_<version>_linux_amd64.deb
# or
sudo dnf install ./hostveil-<version>.x86_64.rpm

The package installs the same single binary to the same path the installer uses, /usr/bin/hostveil, so the two are interchangeable — you can move from one to the other without ending up with two copies on your PATH. Docker and iproute2 are listed as recommended, never required: without them the container, CVE, and exposed-service domains report N/A rather than Hostveil failing to run.

There is no service to enable and no config file to edit. Removing the package leaves /var/lib/hostveil in place, for the same reason --uninstall does: those checkpoints are the backups of every file Hostveil has edited.

Packages are Linux-only.

Verifying what you downloaded

You are being asked to pipe a script into a shell and then run a tool as root. Here is what you can check before you do.

The installer already verifies the checksum of the archive it fetches against the release’s own hostveil-checksums.txt, and discards anything that does not match. That proves the bytes arrived intact. It does not prove who produced them — a checksum file published beside a tampered archive matches it perfectly.

Every release archive carries a signed build provenance attestation, which does prove that: the archive was built by this repository’s release workflow, from a named commit, at a named tag. Nothing running on a maintainer’s laptop can produce one.

gh attestation verify hostveil-linux-amd64.tar.gz --repo seolcu/hostveil

hostveil update runs that check for you where the GitHub CLI is present. A provenance check that fails stops the update; one that cannot run because gh is not installed is a note rather than an error, because a checksum still proves the bytes are intact and it would be dishonest to imply otherwise.

Each archive also ships an SBOM (.sbom.json) listing everything that went into the binary, so you can answer “does this contain the library in today’s advisory” without building it yourself.

Running it on macOS

The macOS build is a real build — the installer takes it, it runs, and it produces a report. It is published because Hostveil is often driven from a laptop and because a build that is not published is a build nobody notices breaking. What it is not is a macOS auditor: there is no Darwin-specific rule anywhere in the tool.

On a Mac with no Docker, ten of the twelve domains report N/A. Seven find nothing to look at on their own — no /proc/sys, no systemd, no apt or dnf, no ss — and three more are excluded deliberately, because on macOS they would have answered a question they had not asked:

DomainOn macOS
Host firewallExcluded. Hostveil probes ufw, firewalld, nftables and iptables. macOS has none of them and uses pf instead, so “none of my probes found anything” would have been reported as firewall.inactive — a top-severity finding about a firewall Hostveil never looked for.
Account hygieneExcluded. macOS ships an /etc/passwd, but the account database is Open Directory and that file does not describe the host. The /etc/shadow half cannot run at all, and the advice it would print — re-run with sudo — could never help, because the file is absent rather than unreadable.
AI agent runtimesExcluded. It finds home directories through the same /etc/passwd, keeping the Linux UID range. macOS accounts start at 501, so it would have found only /var/root and reported “no agent runtime” about a host whose /Users it never opened.

Two domains do run. SSH reads /etc/ssh/sshd_config, which macOS ships whether or not Remote Login is on, and its findings are about OpenSSH rather than about Linux — PasswordAuthentication means the same thing on Darwin. File permissions stats the files it recognises and skips the rest. On stock macOS both are usually clean.

A fix on macOS edits a real file

The SSH domain is not read-only theatre. hostveil fix ssh.passwordauth on a Mac backs up and rewrites /etc/ssh/sshd_config, exactly as it would on a server, and it is reversible from hostveil history the same way. That is correct behaviour and worth knowing before you run it on a laptop.

And the score is a number, not N/A: two domains ran, so there is something to average. It is an average over 19 of the 100 points of weight, and it says nothing about the ten domains that did not run. Read the axis breakdown, not the headline. Nothing about pf, the application firewall, Homebrew’s update state, launchd services, or System Integrity Protection is examined by any part of hostveil.

Upgrading and uninstalling

Hostveil does both itself, and the reason it does rather than telling you to re-run the installer is that it knows how this binary got here.

hostveil update      # --check to ask without changing anything
hostveil uninstall

update works out the origin — the install script, a .deb, an .rpm, or go install — and updates it the same way. Re-running the install script over a packaged install replaces a file dpkg or rpm still believes it owns, which is the state this command exists to avoid. The download is checked against the release’s checksums and, where the GitHub CLI is present, against the signed build provenance. If Hostveil cannot tell how the binary was installed it does nothing and says so. See the CLI reference for the full origin table.

Uninstalling removes /usr/bin/hostveil and prints where the state directory is — without deleting it. Those checkpoints are the backups of every file Hostveil has edited on this host, and removing the tool is not a decision to give up the ability to undo its fixes. The command to delete them is printed if you want it. Trivy is left alone too: it is a general-purpose scanner that may predate Hostveil or be used by something else.

Build from source

With a recent Go toolchain installed:

git clone https://github.com/seolcu/hostveil
cd hostveil
go build ./cmd/hostveil
go test ./...

See Contributing for the full development setup, including the reproducible demo VM.