Skip to content

Direct install

PEART ships as two static, pure-Go binaries, peart (the internal surface the pentester uses) and peart-portal (the surface the client uses), plus a Python rendering sidecar that turns report HTML into PDF. This page installs the binaries directly on a Linux host. The container path is on its own page; the direct install is the right choice for a hardened or audited host, where fewer moving parts is itself a security property.

There is no default credential. On first access PEART requires you to create the administrator, including enrolling the second factor.

Every tagged release publishes cross-compiled binaries for linux/amd64 and linux/arm64, a checksums.txt manifest, a CycloneDX sbom.json, and Sigstore signatures for both. Download the binaries for your architecture along with checksums.txt, checksums.txt.sig and checksums.txt.pem from the releases page.

Verify the manifest signature before trusting it. The release is signed keyless with cosign, so there is no public key to fetch; the identity is the release workflow itself:

cosign verify-blob \
  --certificate-identity-regexp 'https://github.com/mentesan/peart/.*' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  --signature checksums.txt.sig --certificate checksums.txt.pem \
  checksums.txt

Then check the binaries against the verified manifest and install them:

sha256sum --check --ignore-missing checksums.txt
sudo install -m 0755 peart-linux-amd64        /usr/local/bin/peart
sudo install -m 0755 peart-portal-linux-amd64 /usr/local/bin/peart-portal
peart version

The Verifying the install page covers verifying the SBOM signature and the container image the same way.

Method 2 — go install

With a Go toolchain matching the version in the project's go.mod, install both commands from source without cloning:

go install github.com/mentesan/peart/cmd/peart@vX.Y.Z
go install github.com/mentesan/peart/cmd/peart-portal@vX.Y.Z

Pin the exact version tag rather than @latest so you know what you built. This path builds on your own machine and does not carry the release signatures, so prefer Method 1 when you want the signed, attested artifacts.

Method 3 — from source

For contributors, or to build inside an air-gapped environment from an audited checkout:

git clone https://github.com/mentesan/peart.git
cd peart
make build          # produces bin/peart and bin/peart-portal

The build is plain cross-compilation with no CGO (ADR 0004), so building for another Linux architecture needs only GOOS/GOARCH, not a second machine or emulation.

The users and groups (bare metal)

Nothing below this line works until these exist. Three service accounts run the three processes, and every install -d, chown and sudo -u in this page and the next one names them. Create them once, here, before anything uses them:

sudo groupadd --system peart
sudo groupadd --system peart-portal
sudo groupadd --system peart-render
sudo groupadd --system peart-work

sudo useradd --system --gid peart        --no-create-home --shell /usr/sbin/nologin peart
sudo useradd --system --gid peart-portal --no-create-home --shell /usr/sbin/nologin peart-portal
sudo useradd --system --gid peart-render --home-dir /opt/peart/render --shell /usr/sbin/nologin peart-render

Each account gets a group of its own name, and --gid says so rather than trusting the distribution to create one: whether useradd does that by itself depends on USERGROUPS_ENAB, and the permission block on the next page addresses peart and peart-portal as groups, not only as users. None of the three has a login shell or a home it does not need; peart-render's home is the virtualenv directory the sidecar runs from, created a few lines below.

peart-work is the fourth group and the odd one out: it belongs to no single account. It is the group peart and peart-render share over the job directory where one stages a report and the other renders it, and the shipped units put both processes in it with SupplementaryGroups=peart-work, so there is no usermod to remember here. First run and configuration owns the directory itself.

If you already have a PEART install, these accounts exist and this section is not for you. Leave them exactly as they are, whatever options they were created with.

Installing the rendering sidecar (bare metal)

The three methods above install the Go binaries and nothing else. PDF generation goes through a Python sidecar, and on a bare-metal install it is yours to put in place: peart-render.service expects it at /opt/peart/render, running from a virtualenv there. Without it the application starts and works, and every report generation fails.

The container path needs none of this: the image bundles the sidecar and its dependencies.

The job directory the sidecar works out of is not created here. It is shared with the peart process and belongs to the data tree, which First run and configuration owns in one place, group and modes included.

sudo install -d -o peart-render -g peart-render /opt/peart/render
sudo cp render/app.py render/requirements.txt /opt/peart/render/

sudo -u peart-render python3 -m venv /opt/peart/render/.venv
sudo -u peart-render /opt/peart/render/.venv/bin/pip install     --require-hashes -r /opt/peart/render/requirements.txt

--require-hashes is not decoration. Every distribution in requirements.txt is pinned by version and locked by hash, so a compromised index or a silently swapped wheel is refused instead of installed (docs/security.md, supply chain). WeasyPrint's own native dependency, Pango, comes from your distribution's packages, listed in Prerequisites.

The sidecar reads its token from /etc/peart/render.env as PEART_RENDER_TOKEN, and that value has to match render.token in config.yaml; the unit supplies the work directory, host and port (/var/lib/peart/work, 127.0.0.1:8090). ADR 0005 requires WeasyPrint 68.0 or newer because of CVE-2025-68616, and app.py verifies the version at runtime, so a downgrade of the requirements file alone is not enough to run an old one: the sidecar refuses to start instead.

When you upgrade PEART, refresh this directory from the same tag and reinstall the requirements, so the sidecar does not drift away from the binaries that call it.

Next steps

  1. First run and configuration — the config file, the paths PEART reads and writes, and the master encryption key generated on first boot.
  2. Running as a service (systemd) — the deploy/systemd/ units, including the rendering sidecar's mandatory network isolation.
  3. TLS and reverse proxy.

The rendering sidecar is required, and its network isolation is not optional. Do not run a real deployment from make run; that local path exists for development and omits the isolation the systemd units carry.