Docs: https://rvenutolo.github.io/linPEAS-flake/
Note: Yes, this is an absurdly over-engineered way to skip running
curl -LO https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh. Also built just for fun. No, I will not be taking questions.
Personal Nix-flake wrapper around peass-ng/PEASS-ng linpeas.sh. All credit for LinPEAS itself belongs to the PEASS-ng authors.
The Renovate dependency dashboard tracks pending dependency bumps, rate-limited PRs, and config errors. Check there if a bump appears stalled.
Each install artifact serves a different scenario. Pick the one that matches your environment.
nix run — ad-hoc host audit on a Nix-enabled machine. No
install, no state.
nix run github:rvenutolo/linPEAS-flake -- -anix profile install — persistent install on a Nix-enabled
machine. linpeas ends up on $PATH.
nix profile install github:rvenutolo/linPEAS-flakeHost audit — use when Docker is the only install vehicle on the host. Joins host namespaces and bind-mounts rootfs read-only so linpeas sees the host instead of the container.
docker run --rm \
--pid=host --net=host --ipc=host --userns=host --privileged \
-v /:/host:ro \
rvenutolo/linpeas:latest -d /hostContainer / sidecar audit — audit a different running container. Real use cases: CI hardening, base-image review, forensics on a running workload. Joins the target container's PID and network namespaces.
docker run --rm \
--pid=container:<target> --net=container:<target> \
rvenutolo/linpeas:latest -aBoth registries (docker.io/rvenutolo/linpeas and
ghcr.io/rvenutolo/linpeas) serve the same image bytes — every
release pushes to both with identical content digests and matching
SLSA attestations. See docs/install/docker.md
for the full use-case matrix.
Pull linpeas as a dependency from another flake (e.g. a NixOS config or dev shell).
{
inputs.linpeas-flake = {
url = "github:rvenutolo/linPEAS-flake";
inputs.nixpkgs.follows = "nixpkgs";
};
# access via inputs.linpeas-flake.packages.${system}.default
}For a full guide (plain flake + flake-parts, pinning, no binary
cache), see docs/install/consume-from-flake.md.
Expose pkgs.linpeas inside your nixpkgs set so existing pkgs.*
consumers can reference it.
{
nixpkgs.overlays = [ inputs.linpeas-flake.overlays.default ];
# ...
# then pkgs.linpeas is available
}See docs/install/consume-from-flake.md
for pinning guidance that applies to overlay use as well.
Independent automations keep this flake current. Full pipeline,
trigger semantics, and credential split live in
docs/architecture/auto-update.md.
| Workflow | When | Purpose |
|---|---|---|
update-linpeas.yml |
daily 09:00 UTC + dispatch | Bumps linpeas-pin.json to the latest upstream tag. Opens PR; auto-merges on green. |
stale-pin-check.yml |
daily 10:30 UTC | Files a deduped issue if update-linpeas is stalled. |
verify-latest-release.yml |
daily 12:00 UTC | Re-verifies the latest release's attestations and re-fetches upstream linpeas.sh to confirm the pinned SRI hash. |
release-on-bump.yml |
push to main changing the pin |
Tags the release, builds + pushes per-arch OCI images (ghcr.io + docker.io), attests SLSA provenance + SBOMs. |
pages.yml |
push, PR, release, daily 14:00 UTC, dispatch | Rebuilds the MkDocs site; deploys via OIDC on non-PR events. Not in the required-check set. |
update-flake-lock.yml |
weekly Fri 06:00 UTC | Bumps nixpkgs via nix flake update; opens auto-merging PR. |
| Renovate | weekly Fri batch | Bumps action SHAs + tracked flake inputs after a 7-day cooldown. |
Bump-workflow commits are authored by the linpeas-flake-bumper GitHub
App and web-flow-signed by GitHub, satisfying required_signatures on
main without a personal access token. See
docs/security/repo-config.md.
Release tags match the upstream peass-ng/PEASS-ng tag verbatim
(e.g. 20260510-cd4bd619). No v prefix, no -flake suffix.
This keeps the mapping from a release here to the corresponding upstream
release one-to-one and obvious. Wrapper-only fixes (e.g. a flake.nix bug
fix unrelated to a pin bump) ride along with the next pin bump rather than
getting their own release tag — acceptable since the wrapper is intentionally
thin.
Every PR and push to main runs a gated set of required checks before
auto-merge. The authoritative check list lives in
docs/security/required-checks.md;
the full job inventory + cron schedule lives in
docs/architecture/ci.md.
- Build + smoke:
build-linpeas,build-linpeas-arm64,flake-check,image-smoke,image-smoke-arm64,smoke-test,smoke-test-arm64. - Conventional Commits:
commitlint,lint-pr-title. - Doc quality:
check-doc-anchors,check-orphan-invariants,editorconfig,markdownlint,typos. - Security/invariant lints:
check-jsonschema,checkout-persist-credentials,ci-job-in-summary,cliff-tag-pattern,cosign-identity-pinned,dashboard-data-tests,dependency-review,fork-guard-release,gh-attestation-repo,gitleaks,harden-runner-first,job-timeout-minutes,min-permissions,nix-run-pinned,pin-diff-isolated,pr-workflows-no-secrets,pre-commit-hooks-sha-parity,protect-main-drift-check,pull-request-target-absent,ratchet-pin-audit-harness,renovate-config-validator,renovate-invariants,required-checks-no-paths,run-block-strict,script-has-test,script-shebang-pipefail,setup-nix-required,tag-protection-drift-check,trufflehog,upload-artifact-strict,uses-sha-pinned,workflow-concurrency,workflow-on-branches.
Merge policy: merge-commit only, with required_signatures
enforced. Every branch commit must independently pass commitlint and be
signed; see
docs/development/git.md.
Defense-in-depth supply-chain layers (advisory or implicit, not in the required-check table; alphabetical):
actions.permissions.allowed_actions=selectedwith a vendor allowlist (docs/security/allowed-actions.md).image-cve-scan-trivyandimage-cve-scan-grype(Trivy + Grype → code-scanning SARIF, advisory only; prevention path isupdate-flake-lock).release-tag-protectionruleset blocks delete / non-FF / update on release tags; drift asserted bytag-protection-drift-check.step-security/harden-runnerruns as the first step in every job (egress-policy: audit).
Every release runs a verify job in release-on-bump.yml that downloads the
just-published image and runs gh attestation verify on each.
A separate daily cron workflow (verify-latest-release.yml) re-verifies the
latest release's image and pin file and re-fetches the pinned
linpeas.sh from upstream to confirm the SRI hash still matches — this
detects upstream tag-replacement that attestation alone cannot see. Any
failing check surfaces as a red workflow run.
Upstream PEASS-ng releases ship no signatures (GPG, cosign, SLSA). Integrity rests on:
- SRI hash pinning in
linpeas-pin.json— Nix refuses to build on mismatch. - Flake-eval-time assertions on
pin.version(YYYYMMDD-) andpin.url(peass-ng release prefix) — derivation eval fails on a malformed pin. - GitHub Releases API
digestfield cross-check inside the bump workflow (hard fail if absent — never a silent skip). - Asset-URL prefix validation inside the bump workflow.
- Daily upstream parity check (
verify-latest-release.yml).
This matches the trust model of curl ... | bash, but with reproducible,
hash-pinned downloads and SLSA build-provenance attestations. See
SECURITY.md for the full trust model, including the
distinction between build-provenance attestations and content trust.
The full nix flake show --all-systems tree lives in
docs/reference/flake-outputs.md and is
auto-regenerated by scripts/refresh-flake-show.sh.
Branches follow type/description (kebab-case); commits follow
Conventional Commits and must be signed. PRs land via merge-commit only;
rebase + squash are disabled to preserve branch-commit signatures.
Full runbook — branch naming, commit signing, pre-commit hook list,
local lint commands — lives in
docs/development/git.md.
Repository-side posture is locked down: main is ruleset-protected with
required checks + signed commits + merge-only; release tags are
ruleset-protected against delete / non-FF / update; only allow-listed
action vendors can run; bump workflows authenticate as a scoped GitHub
App rather than a PAT.
Full breakdown — allowed-actions allowlist, App-based bump auth, branch
and tag protection, required-check list — lives in
docs/security/repo-config.md.
All tooling below — shfmt, shellcheck, just, pre-commit,
nixfmt, deadnix, statix, actionlint, zizmor, yamllint,
prettier, lychee, check-jsonschema, and more (see devShells.default in
flake.nix for the full set) — is supplied by the flake's devShells.default.
You do not install any of it manually.
Enter the shell one of two ways:
nix develop— explicit entry.direnv allowonce, then direnv auto-enters oncd(.envrcrunsuse flake).
Either path runs the shellHook, which installs the pre-commit git hooks
automatically — the pre-commit install line below is shown only for
reference / non-flake setups. Prerequisite: Nix
with flakes enabled (nix-command flakes).
# Entry points.
nix develop # enter dev shell (or direnv allow)
pre-commit install # one-time, wires git hooks
# just recipes (alphabetical).
# BEGIN just-recipes
just # Default: list recipes
just build # Build the linpeas package
just bump # Manually refresh linpeas pin from upstream latest release
just check # Run all flake checks (eval, formatting, pre-commit)
just fmt # Format every file via treefmt
just image # Build the OCI image
just lint # Run pre-commit hooks against all files
just lint-links # Run lychee link checker against tracked markdown files
just show # Regenerate the <!-- BEGIN/END flake-show --> block in docs/reference/flake-outputs.md
just show-ci-dag # Regenerate docs/architecture/ci-dag.md from ci.yml needs graph
just show-ci-summary # Regenerate the Continuous integration summary in README.md
just show-enforcement-matrix # Regenerate docs/security/enforcement-matrix.md from invariant-index annotations
just show-hooks # Regenerate the pre-commit hook table in docs/development/git.md
just show-recipes # Regenerate the just-recipes list in README.md
just show-scripts # Regenerate docs/reference/scripts.md from in-script annotations
just show-treefmt # Regenerate docs/reference/treefmt-config.md from treefmt.nix
just site # Build the Pages site
just site-data # Regenerate docs/_data/dashboard.yml standalone
just site-dev # Live-preview site at http://127.0.0.1:8000 (regenerates data first)
just verify # Run every script-based check and test harness (excludes nix-build and link-check jobs)
# END just-recipesThis wrapper is MIT-licensed (see LICENSE). The wrapped
linpeas.sh is MIT-licensed by peass-ng/PEASS-ng;
this repo does not redistribute it (Nix fetches it at build time from upstream's
release URL).