Skip to content

Install the agent

etminan-agent runs on every monitored host. This chapter installs it from the signed packages, enables its two systemd units, and confirms the host is wired up correctly — before it is ever enrolled.

Prerequisites

Confirm the host meets the monitored-host requirements first — a TPM 2.0 on /dev/tpmrm0, an IMA-capable kernel with the SHA-256 PCR bank, and a supported distribution.

Import the signing key

Every Etminan package is GPG-signed with the Etminan Team key. Import it once so the package manager (and you) can verify what you install.

# From the keyserver…
gpg --keyserver hkps://keys.openpgp.org \
    --recv-keys 0x73874214090F9137862D0AF1E1E541B7B42436DF
# …or import the local copy shipped alongside the downloads:
gpg --import gpg-etminan-team.asc

The fingerprint must read 7387 4214 090F 9137 862D 0AF1 E1E5 41B7 B424 36DF.

Install the package

The agent and verifier ship in one package; installing it lays down both binaries plus the systemd units and example configs, and creates the service users — but enables nothing. You choose the role(s) a host plays in the next step.

# verify the detached signature and checksum first
gpg --verify etminan_<version>_amd64.deb.asc etminan_<version>_amd64.deb
sha256sum -c etminan_<version>_amd64.deb.sha256

# install, letting apt pull any dependencies
sudo apt install ./etminan_<version>_amd64.deb
# verify the detached signature and checksum first
gpg --verify etminan-<version>.x86_64.rpm.asc etminan-<version>.x86_64.rpm
sha256sum -c etminan-<version>.x86_64.rpm.sha256

# install, letting dnf resolve dependencies
sudo dnf install ./etminan-<version>.x86_64.rpm

For a distribution without a package, unpack the signed release tarball by hand:

gpg --verify etminan-latest.tar.gz.asc etminan-latest.tar.gz
sha256sum -c etminan-latest.tar.gz.sha256
tar xzf etminan-latest.tar.gz

Copy the etminan-agent binary onto PATH, install the unit files from deploy/ into /etc/systemd/system/, and create the etminan-agent service user (in the tss group) and /var/lib/etminan-agent / /etc/etminan-agent directories the package's postinst would have created. The .deb/.rpm remain the recommended path — they wire all of that up automatically.

What the package creates

The post-install step creates the etminan-agent system user (group tss, so it can open /dev/tpmrm0), the state directory /var/lib/etminan-agent/, and the config directory /etc/etminan-agent/ with an agent.env.example to copy.

Configure watched paths

An agent with no watched-path setting watches nothing and prints a loud startup warning — deliberate, so a host never silently inherits another project's paths. Copy the example config and set at least one path source before enabling the daemon:

sudo cp /etc/etminan-agent/agent.env.example /etc/etminan-agent/agent.env
sudo $EDITOR /etc/etminan-agent/agent.env

At minimum, set watched paths (directly, or via a named profile) and — once you have the verifier's fingerprint — pin it. The full set of variables and the profile mechanism are covered in Agent configuration; mTLS pinning is in Mutual TLS.

Enable the systemd units

The agent role is two cooperating units:

sudo systemctl enable --now \
    etminan-agent-ima-policy.service \
    etminan-agent.service
Unit Type Role
etminan-agent-ima-policy.service one-shot, early boot Writes the IMA measurement policy once, before the daemon starts — this is what makes the "zero manual reboots" install real. Idempotent: a policy already active this boot counts as success.
etminan-agent.service long-running daemon Listens for quote requests, takes TPM quotes over PCR 10, and returns them with the IMA log delta. Runs as the non-root etminan-agent user (group tss), with AmbientCapabilities=CAP_DAC_READ_SEARCH.

Why the one-shot policy unit exists

IMA accepts exactly one successful policy write per boot, and once loaded the write node can disappear from securityfs entirely. Writing the complete policy in one shot, early, via its own unit is the only reliable pattern — hence a separate Before=etminan-agent.service unit rather than doing it inside the daemon.

Verify the host is ready

The agent has no separate self-check subcommand. Start the service and read its startup output — it refuses to start on a hard misconfiguration and emits a distinct warning for each softer problem (watched paths that don't resolve, a missing verifier fingerprint, a fanotify fallback, a TCTI override):

sudo systemctl restart etminan-agent.service
journalctl -u etminan-agent.service -b

Confirm the essentials by hand as well, before enrolling:

  • /dev/tpmrm0 is present and openable by the etminan-agent user (group tss);
  • the IMA SHA-256 measurement log is readable and actually measuring — wc -l /sys/kernel/security/ima/ascii_runtime_measurements_sha256 is non-zero;
  • CAP_DAC_READ_SEARCH is granted — systemctl show etminan-agent.service -p AmbientCapabilities;
  • the watched-path set resolves to at least one path (the agent warns at startup for any that don't);
  • ETMINAN_VERIFIER_CERT_FINGERPRINT is pinned (or permissive mode is explicitly opted into).

You will still need to generate the agent's TLS identity (etminan-agent keygen-tls) and pin the verifier — that is the first-attestation walkthrough, which ties the agent and verifier together end to end.

Next steps