📎 Unreleased docs. This is the next version (from main), features here may change or not be in a release yet.See the latest release →

Getting started

Install

Draugr is a single binary that orchestrates external scanners. Install Draugr first (below), then let it fetch the scanners its controls need. See Scanners. Once you're set up, head to the quickstart for your first scan.

One line, latest release, Linux and macOS:

curl -fsSL https://draugr.dev/install.sh | sh

It detects your OS and architecture, installs to ~/.local/bin, and tells you if that isn't on your PATH.

It verifies before it installs, and says which checks ran. The archive's SHA-256 is always checked against the release's checksums.txt. If cosign is on your PATH, it also verifies that checksums.txt was signed by Draugr's release workflow, which is the check that carries weight, because a host able to serve you a bad archive could serve a matching checksums file too. Nothing is installed if a check fails.

Piping a script into a shell means trusting the host that served it. If you'd rather not, the script is readable in the repo and the manual steps below do the same work.

Three knobs, all optional. They go on sh, not on curl, in a pipeline each side gets its own environment, so DRAUGR_INSTALL_DIR=~/bin curl … | sh sets the variable on the download and the script never sees it:

curl -fsSL https://draugr.dev/install.sh | DRAUGR_INSTALL_DIR=~/bin sh
VariableEffect
DRAUGR_VERSIONPin a release (vX.Y.Z) instead of tracking the latest
DRAUGR_INSTALL_DIRInstall somewhere other than ~/.local/bin
DRAUGR_REQUIRE_SIGNATURESet to 1 to refuse to install unless the signature verifies

Pick a version to pin from the releases page. In CI, pin the version and require the signature, a build runner shouldn't install anything it can't prove the origin of:

curl -fsSL https://draugr.dev/install.sh \
  | DRAUGR_VERSION=vX.Y.Z DRAUGR_REQUIRE_SIGNATURE=1 sh

Already have a draugr binary? Update it in place with draugr self-update.

From a release, by hand#

The same thing without the script. Grabs the latest release, no version to look up:

tag=$(curl -fsSLI -o /dev/null -w '%{url_effective}' \
  https://github.com/draugr-dev/draugr/releases/latest | sed 's#.*/tag/##')
curl -fsSL "https://github.com/draugr-dev/draugr/releases/download/${tag}/draugr_${tag#v}_linux_amd64.tar.gz" \
  | tar -xz draugr
sudo mv draugr /usr/local/bin/       # or anywhere on your PATH
draugr version

Swap linux_amd64 for darwin_arm64, darwin_amd64, linux_arm64, or windows_amd64.

To pin a release, set tag=vX.Y.Z yourself (pick one from the releases page) and drop the first command.

This path doesn't verify anything on its own. See verifying releases for the checksum and signature steps.

From a release, GitHub CLI#

If you already have gh, it handles the download and the platform suffix for you. Omit the tag to get the latest release, or pass a vX.Y.Z to pin:

gh release download --repo draugr-dev/draugr -p 'draugr_*_linux_amd64.tar.gz'
tar -xzf draugr_*_linux_amd64.tar.gz draugr
sudo mv draugr /usr/local/bin/
draugr version

Verify the download (recommended). Releases ship a cosign-signed checksums.txt and per-archive SBOMs:

gh release download --repo draugr-dev/draugr \
  -p 'checksums.txt' -p 'checksums.txt.sigstore.json'
# verify the signature came from Draugr's release workflow (needs cosign)
cosign verify-blob \
  --bundle checksums.txt.sigstore.json \
  --certificate-identity-regexp '^https://github\.com/draugr-dev/draugr/\.github/workflows/release\.yml@refs/tags/v.*$' \
  --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
  checksums.txt
# verify your archive matches
sha256sum --ignore-missing -c checksums.txt

For the full verification story (cosign, SLSA provenance, SBOMs) see verifying releases.

From source#

Requires Go 1.26+.

git clone https://github.com/draugr-dev/draugr.git
cd draugr
make build
./bin/draugr version

make build produces ./bin/draugr. To install a verified release into ~/.local/bin instead of building, from the same checkout:

make install-latest

With Go#

go install github.com/draugr-dev/draugr/cmd/draugr@latest

Scanners. The tools Draugr runs#

With Draugr installed, add the scanners for the controls you use. The fastest way is to let Draugr fetch pinned, verified copies into ~/.draugr/bin (added to your PATH automatically):

draugr tools install            # everything Draugr can provision, pinned + verified
draugr tools install --saga draugr.saga.yaml   # only what this descriptor's scan will run
draugr tools list               # what's pinned, which controls it backs, and what's installed

Prefer your own install (Homebrew, package manager, an existing copy)? That works too. Then run draugr doctor to confirm everything's found:

  • Trivy, images, sca, iac and licenses controls.
  • Gitleaks, secrets control.
  • Semgrep, sast control (default; opt-in gosec for Go).
  • Grype, opt-in second scanner for sca and images.
  • retire.js, opt-in for sca, and the one that finds JavaScript no lockfile describes.
  • Nuclei, dast control.
  • kube-bench, infrastructure control. Needs kubectl as well: its CIS checks are scripts that invoke it.
  • Syft, SBOM generation (config.sbom), which is not a control.
  • git, needed for any repository scan (sca, secrets, sast, licenses).

Two of these are language packages rather than release binaries, so Draugr installs them with the language's own package manager and needs it present: Semgrep needs Python 3.10 or newer with pip, and retire.js needs Node 18 or newer with npm. Every package is checked against a digest recorded in Draugr, and draugr tools list says pinned only when that check actually ran.

headers and tls are native and need nothing installed. draugr doctor reports which of these your Saga requires, so the list you have to care about is usually shorter than this one.