Installing the agent
The agent is a single static binary that runs inside your network. It makes outbound HTTPS connections only — you open no inbound firewall rules, and it listens on nothing. It has no runtime dependencies: no JRE, no Python, no shared libraries to match.
Commands here are written to run as root. If you work through sudo, add the prefix
yourself. They are not written with sudo because it is not a dependency of the agent and is
not installed by default on a minimal Debian — a copied command would fail with
sudo: command not found on exactly the kind of host people install agents on. Where
something must run as the service account, these pages use runuser -u metricharbor -- …,
from util-linux, which is present everywhere.
You need an enrolment key from Settings → Agents, which looks like mhk_7f3a…. The key is
per organization, revocable, and can be limited to a number of installs or an expiry date. It
lets somebody register a new agent — visible in your fleet view immediately — and never
impersonate an existing one or read anything.
Debian and Ubuntu
Add the repository once, so that upgrades arrive through the same tooling as everything else on the machine:
curl -fsSL https://apt.metricharbor.io/metricharbor.asc \
| gpg --dearmor -o /usr/share/keyrings/metricharbor.gpg
echo "deb [signed-by=/usr/share/keyrings/metricharbor.gpg] https://apt.metricharbor.io stable main" \
> /etc/apt/sources.list.d/metricharbor.list
apt update
Then:
apt install metricharbor-agent
metricharbor-agent enrol --url https://api.metricharbor.io --key mhk_… --name centos-tst # whatever you will recognise in the fleet view
runuser -u metricharbor -- metricharbor-agent setup
systemctl enable --now metricharbor-agent
RHEL, Rocky, Alma, CentOS Stream, Fedora and openSUSE
cat > /etc/yum.repos.d/metricharbor.repo <<'EOF'
[metricharbor]
name=MetricHarbor
baseurl=https://rpm.metricharbor.io/stable/$basearch
enabled=1
repo_gpgcheck=1
gpgcheck=0
gpgkey=https://rpm.metricharbor.io/metricharbor.asc
EOF
repo_gpgcheck=1 with gpgcheck=0 is deliberate and is not a weaker setting. The
signature on the repository metadata covers the checksum of the package index, which covers
the checksum of every package, so a tampered .rpm fails the chain before dnf will install
it. What gpgcheck=1 adds is a second signature embedded in each package file, which these
packages do not carry. Setting it anyway produces a failed install, not better security.
Then:
dnf install metricharbor-agent
metricharbor-agent enrol --url https://api.metricharbor.io --key mhk_… --name centos-tst # whatever you will recognise in the fleet view
runuser -u metricharbor -- metricharbor-agent setup
systemctl enable --now metricharbor-agent
The name has to identify the machine
--name is how you will tell this host from every other one in the fleet view, so it has to
mean something. It used to default to the hostname, which is fine until you meet a
distribution that ships without one set — CentOS Stream 10 among them, where it came out as
localhost.
That is refused now, by the agent and by the platform, because the failure it caused was not a
visible one. Re-enrolling under a name that already exists is deliberately treated as the same
agent coming back, so its token is rotated rather than a duplicate created — which is what
makes a reinstall or a re-run of a playbook idempotent. Two different machines both calling
themselves localhost land in that path: the second takes over the first one's identity, the
first can no longer authenticate, and its readings stop without anything saying why.
--url is where the agent reports, https://api.metricharbor.io, and also the default; the
enrolment key's page shows the whole command with your key filled in.
Run setup as the agent's own user, as above, and not as root: it writes the credentials the
service will read.
arm64 / aarch64 packages are published alongside the x86_64 ones, so a Raspberry Pi or
an Ampere instance installs identically.
The service is not started by the package, on purpose
An agent that has not enrolled has nothing to collect. If the package started it, you would get a service restarting every ten seconds and a journal full of "this agent is not enrolled" on a machine where nothing is actually wrong. Enrolment is what makes the service meaningful, so enrolment is what starts it.
Tarball, for hosts with no package manager or an immutable /usr
Download the current release and its checksums. stable holds the version number, so these
lines do not change from one release to the next:
v=$(curl -fsSL https://dl.metricharbor.io/agent/stable)
arch=amd64 # arm64 on ARM
curl -fsSLO https://dl.metricharbor.io/agent/$v/metricharbor-agent-$v-linux-$arch.tar.gz
curl -fsSLO https://dl.metricharbor.io/agent/$v/SHA256SUMS
grep " metricharbor-agent-$v-linux-$arch.tar.gz\$" SHA256SUMS | sha256sum -c -
OK means the download is complete. It does not mean the file is genuine, because the
checksums came from the same server. Where gpg is installed, check the signature too:
curl -fsSLO https://dl.metricharbor.io/agent/$v/SHA256SUMS.asc
curl -fsSL https://dl.metricharbor.io/metricharbor.asc | gpg --dearmor > metricharbor.gpg
gpgv --keyring ./metricharbor.gpg SHA256SUMS.asc SHA256SUMS
Good signature from "MetricHarbor Package Signing" is the one that matters. It is the
same key that signs the apt and dnf repositories. Then install it:
tar xzf metricharbor-agent-$v-linux-$arch.tar.gz
cd metricharbor-agent-$v-linux-$arch
install -m 0755 metricharbor-agent /usr/local/bin/
install -m 0644 metricharbor-agent.service /etc/systemd/system/
install -m 0644 metricharbor-agent.options /etc/default/metricharbor-agent
groupadd --system metricharbor
useradd --system --gid metricharbor --no-create-home \
--home-dir /var/lib/metricharbor --shell /usr/sbin/nologin metricharbor
install -d -o metricharbor -g metricharbor -m 0750 /etc/metricharbor
install -d -o metricharbor -g metricharbor -m 0700 /etc/metricharbor/creds.d
install -d -o metricharbor -g metricharbor -m 0700 /var/lib/metricharbor
Change ExecStart= in the unit to /usr/local/bin/metricharbor-agent, run
systemctl daemon-reload, then enrol as above.
Container
No image is published yet. Until one is, install the package or the tarball. Once it is, this is how it runs:
podman run -d --name metricharbor-agent \
-v metricharbor-etc:/etc/metricharbor \
-v metricharbor-lib:/var/lib/metricharbor \
metricharbor/agent:2.3.3 run
Both volumes matter. /etc/metricharbor holds the enrolment identity and the credential
store; /var/lib/metricharbor holds samples collected while MetricHarbor was unreachable. A
container run without them re-enrols on every restart and discards whatever it had buffered,
turning a brief outage into a permanent gap in your history.
What the service is allowed to do
The agent runs as an unprivileged system user under a hardened systemd unit. If it were compromised, the attacker would get: outbound network, its own two directories, and whatever credentials you chose to give it. Not your filesystem, not other users' data, not root.
Check it yourself rather than taking our word for it:
ps -o user= -C metricharbor-agent # metricharbor, never root
ss -ltnp | grep metricharbor # no output: it listens on nothing
getpcaps "$(systemctl show -p MainPID --value metricharbor-agent)"
systemd-analyze security metricharbor-agent.service
It holds exactly one Linux capability, CAP_NET_RAW, and only so that ICMP ping works —
unprivileged ICMP is disabled by default on Linux (net.ipv4.ping_group_range is 1 0). If
you would rather it held none, delete the CapabilityBoundingSet= and AmbientCapabilities=
lines from the unit. The reachability check then falls back to a TCP connect, which is often
the better signal anyway: a host answering ping while its service is dead is not up in any
useful sense.
Options
Set in /etc/default/metricharbor-agent (Debian, Ubuntu) or
/etc/sysconfig/metricharbor-agent (Red Hat and derivatives), then restart the service.
MH_OPTS=--no-exec
| Option | What it does |
|---|---|
--no-exec |
Refuse script and agent_exec bindings outright, whatever MetricHarbor sends. See below. |
--buffer-mb=N |
How much collected-but-unshipped data to keep on disk. Default 64. |
--buffer-hours=N |
Discard buffered data older than this. Default 72. |
--auto-update |
Let the agent replace its own binary with a signed release. Off by default for packages. |
This file is deliberately not inside /etc/metricharbor. The agent can write to that
directory — it keeps its enrolment state and credentials there — and a process that can
rewrite its own hardening options is not constrained by them. Under ProtectSystem=strict the
rest of /etc is read-only to the agent, so only root can change the options above.
Turning off remote script execution
MetricHarbor can run check scripts you write on your own hosts. If you do not want that
capability to exist at all — including in the event that MetricHarbor itself were compromised
— set MH_OPTS=--no-exec.
The agent will then refuse every script binding regardless of what our platform sends, record the refusal so you can see it in the interface, and keep collecting everything else. This is a local, unconditional decision made by software on your machine; it does not depend on us behaving.
Why auto-update is off for packaged installs
An agent that overwrites /usr/bin/metricharbor-agent behind apt or dnf leaves the two
permanently disagreeing about what is installed, until the next upgrade silently reinstates an
older binary. For packages, MetricHarbor shows you which agents are out of date and the
upgrade comes from the repository above — through whatever already governs package changes on
that host, which on a machine under change control is the only acceptable answer. The tarball
and container builds, which no package manager owns, are where --auto-update belongs.
When it is on, a release is only installed if its signature verifies against a public key compiled into the binary. An update that fails verification is refused, left unapplied, and reported. There is no "download over HTTPS and trust the TLS".
Upgrading
apt update && apt install --only-upgrade metricharbor-agent # or: dnf upgrade metricharbor-agent
On a host with no route to the repository — an air-gapped network, or a site that mirrors
packages internally — download the .deb or .rpm and install the file directly:
apt install ./metricharbor-agent_2.4.0_amd64.deb
Your enrolment, credentials and buffered data survive. The service restarts only if it was already running — an upgrade is not permission to start something you had deliberately stopped.
Removing
apt purge metricharbor-agent # or: dnf remove metricharbor-agent
Buffered data is removed. Your credentials are not. apt purge would normally take
configuration with it, and this package deliberately does not: what is under
/etc/metricharbor/creds.d is database passwords, SNMP passphrases and private keys that
somebody typed in by hand, possibly on fifty hosts. Purge is also what people run to reinstall
cleanly. Removal tells you the path and the one command that deletes them for good.