Getting started
Installation
Section titled “Installation”The easiest path — one command, picks the right binary for your OS/arch:
curl -fsSL https://get.enodia.sh/unix | sh # Linux/macOS/Android (Termux)irm https://get.enodia.sh/windows | iex # Windowsenodia is runnable immediately afterward in that same PowerShell
window — the installer patches the current session’s PATH directly,
not just the persisted registry value a fresh terminal would pick up.
On Windows, winget and Chocolatey work too, if you’d rather your package manager track updates:
winget install EpicMorg.Enodia # wingetchoco install enodia # ChocolateyOr a package, if you’d rather your package manager track updates:
sudo dpkg -i enodia_linux_amd64.deb # Debian/Ubuntusudo rpm -i enodia_linux_amd64.rpm # Fedora/RHELapk add --allow-untrusted enodia_linux_amd64.apk # Alpinesudo pacman -U enodia_linux_amd64.pkg.tar.zst # ArchEvery package installs the binary at /usr/bin/enodia, man pages under
/usr/share/man/man1/, and creates a dedicated, unprivileged enodia
system user — nothing here needs root to run. Grab the right one from
the latest release.
Or a container:
docker run --rm \ -v /etc/enodia:/config:ro \ ghcr.io/epicmorg/enodia:latest check --config /config/config.yamlSince 1.1.0, this image is built and published by a companion repo,
EpicMorg/docker,
on its own schedule — not by this project’s own release pipeline
anymore, though the published address and tags stay the same. Also
published to docker.io/epicmorg/enodia and Quay, same tags — latest,
a bare major (2), and the exact version with no build suffix (e.g.
2.2.1 — confirmed live on all three registries; an earlier pipeline’s own tags looked like
1.0.0-1 instead, still pullable, just not how new releases tag from
here on). Two real changes worth knowing about: the image is
linux/amd64 only now (arm64 was dropped when publishing moved),
and it runs as root rather than a dedicated user, on the project’s
own debian:trixie-light house base instead of scratch. It declares
/var/lib/enodia/cve as a volume for the
CVE databases — mount your copies
there, or let enodia cve update fill it.
Build from source
Section titled “Build from source”Requires Go — check go.mod for the exact version enodia currently
targets.
git clone https://github.com/EpicMorg/enodia.gitcd enodiago build -o enodia ./cmd/enodia./enodia versionSupported platforms
Section titled “Supported platforms”| OS | Arch | Minimum version |
|---|---|---|
| Linux | amd64, arm64 | Kernel 3.2 or later — Debian 8+, Ubuntu 14.04+, RHEL/CentOS 7+ all comfortably qualify |
| Windows | amd64, arm64, 386 | Windows 10 / Windows Server 2016 or later |
| macOS | amd64, arm64 | macOS 12 Monterey or later |
| Android (Termux) | arm64 only | Android 7 or later — Termux’s own floor, stricter than the Android 5.0 Lollipop PIE-support minimum that actually drove the separate build (see the Termux note above). Rooted devices may need su — see the caution above |
These are the Go toolchain’s own floor, not something enodia adds on top. Building from source with a newer Go raises the macOS floor further — that’s a toolchain decision, not a project one.
Your first config
Section titled “Your first config”Create enodia.yaml next to the binary (or in any of the locations
listed in Configuration):
schemaVersion: 1targets: - id: gitlab-main product: gitlab address: https://gitlab.example.comThen run:
enodia checkID PRODUCT PATCH LIFECYCLE BRANCH SEVERITY REASON CVESgitlab-main gitlab ...check with no --from collects and evaluates in one process — enodia
reaches your target, then reaches the internet to check its lifecycle
data. If your target only has network access to your infrastructure (a
closed environment) and not the internet, split the two phases instead:
# inside the closed network - no internet neededenodia collect --config enodia.yaml -o inventory.jsonl
# anywhere else - no access to your services neededenodia check --from inventory.jsonlAdding credentials
Section titled “Adding credentials”A target with a private API needs a named credential, resolved from
enodia.yaml’s own credentials: map (or a separate
credentials.yaml — see Configuration):
schemaVersion: 1targets: - id: gitlab-main product: gitlab address: https://gitlab.example.com credentials: gitlab-token
credentials: gitlab-token: kind: token-header header: PRIVATE-TOKEN value: "${GITLAB_TOKEN}"${GITLAB_TOKEN} is interpolated from the environment at load time —
see Configuration.
Secrets never need to live in the same file as your service inventory.
- Concepts for the design decisions behind all of this.
- CLI reference for every command and flag.
- Views for
lifecycle,drift, andfleet— not just the default table.