Skip to main content

Installing the sensor on Linux

The GPG-signed deb and rpm packages, the exact install commands, the systemd unit and its paths, and what the sensor needs from the kernel to see anything useful.

Written for whoever runs IT8 min readUpdated

The Linux sensor is a single static binary run by systemd as an unprivileged service. It reports process activity and file activity to Qorionix, and it is the same code as the Windows and macOS builds with a different set of collectors underneath. This article covers what it runs on, the exact commands, where the files go, how to confirm it works, and — the part most vendors skip — what it needs from the kernel and what you actually lose where that is missing.

What it runs on

One packaging definition produces both a .deb and an .rpm, for amd64 and arm64. Our architecture decision record lists the family coverage as Ubuntu, Debian, RHEL, Rocky, Alma and AmazonLinux. We do not publish tested minimum releases for each of those, and we would rather tell you that than print a version table nobody verified.

  • systemd is required. The package ships a systemd unit and nothing else; there is no SysV or OpenRC init script.
  • Debian and Ubuntu package dependencies: libc6, adduser, libcap2-bin.
  • RHEL-family package dependencies: glibc, shadow-utils, libcap.
  • Outbound HTTPS to your API base URL — the console origin you were given at enrolment, e.g. https://app.qorionix.com. Nothing inbound; the sensor never listens on a port.
  • An enrolment token from the console, Settings -> Endpoints -> Enrolment tokens. See Enrolment tokens.

The install commands

The console generates these when you create an enrolment token, with the download URL, token and API URL already substituted. They begin with a fetch on purpose: a copy-pasteable command that names a file you were never told how to obtain is worse than no command at all. Every generated command downloads the package, its GPG signature and the public key, verifies the signature, and only then installs — all &&-chained, so a bad signature stops the command rather than being silently skipped.

Debian and Ubuntu (shape of the generated command)
curl -fsSL -o qorionix-sensor.deb <url> \
  && curl -fsSL -o qorionix-sensor.deb.asc <url>.asc \
  && curl -fsSL -o qorionix-linux-packages.asc https://stqorionixmvpqtjd4q.z16.web.core.windows.net/agents/qorionix-linux-packages.asc \
  && sha256sum -c <(echo '<published-sha256>  qorionix-sensor.deb') \
  && gpg --import qorionix-linux-packages.asc \
  && gpg --verify qorionix-sensor.deb.asc qorionix-sensor.deb \
  && sudo QX_ENROLL_TOKEN=<token> QX_API_URL=<api> apt-get install -y ./qorionix-sensor.deb
RHEL, Rocky, Alma, Amazon Linux (shape of the generated command)
curl -fsSL -o qorionix-sensor.rpm <url> \
  && curl -fsSL -o qorionix-sensor.rpm.asc <url>.asc \
  && curl -fsSL -o qorionix-linux-packages.asc https://stqorionixmvpqtjd4q.z16.web.core.windows.net/agents/qorionix-linux-packages.asc \
  && sha256sum -c <(echo '<published-sha256>  qorionix-sensor.rpm') \
  && gpg --import qorionix-linux-packages.asc \
  && gpg --verify qorionix-sensor.rpm.asc qorionix-sensor.rpm \
  && sudo QX_ENROLL_TOKEN=<token> QX_API_URL=<api> dnf install -y ./qorionix-sensor.rpm

The command the console generates for you has the exact URLs and checksum substituted — copy that one rather than retyping the shape above. The public key's fingerprint is 82B5493F28E56C9879AF345C69585537BBC6B9D9; if you are verifying by hand outside the generated command, confirm gpg --verify reports a good signature from that fingerprint before trusting the download.

Those two work from an interactive shell. They are not the form to use from configuration management, because apt and dnf do not reliably forward the invoking environment to package maintainer scripts. If Ansible, Puppet, Chef or an MDM is doing the install, drop the token into a file instead — a file arrives reliably where an environment variable may not.

Token-file form, for configuration management
curl -fsSL -o qorionix-sensor.deb <url> \
  && sudo mkdir -p /etc/qorionix && printf '%s' '<token>' | sudo tee /etc/qorionix/enrollment-token >/dev/null \
  && sudo chmod 600 /etc/qorionix/enrollment-token \
  && printf '%s' '<api>' | sudo tee /etc/qorionix/api-url >/dev/null \
  && sudo apt-get install -y ./qorionix-sensor.deb

The token file is read and whitespace-stripped, so a trailing newline or a CRLF from a file pushed by an MDM is handled rather than turned into a mystifying rejection. The installer deletes /etc/qorionix/enrollment-token once enrolment reaches a terminal outcome, and keeps it where a corrected re-run would still need it.

Where everything lives

Linux service identity and paths. The config file holds this machine's credential, which is why it is group-readable by the service account and nothing else.
ThingValue
Service nameqorionix-sensor.service
Runs asthe qorionix-sensor user and group, not root
Binary/usr/bin/qorionix-sensor
Config/etc/qorionix/qorionix-sensor.yaml, owned root:qorionix-sensor, mode 0640
Log file/var/log/qorionix-sensor.log, plus journald
Local state/var/lib/qorionix-sensor/cache.db
Quarantine vault/var/lib/zentryq/quarantine
Unit file/lib/systemd/system/qorionix-sensor.service

The config path is compiled into the binary rather than supplied by the unit, so the unit, the package scripts and the enroll subcommand cannot disagree about where it is. Only five keys in that file are read: api_url, enrollment_token, sensor_id, organization_id and tls_insecure_skip_verify. The channels, poll_interval_seconds, cache_path and log_path entries you will see in the shipped default are written but not parsed — they are not tuning knobs, and we would rather say so than let you spend an afternoon changing a value nothing reads.

The unit is deliberately hardened. It runs with NoNewPrivileges, ProtectSystem=strict, ProtectHome, PrivateTmp and MemoryDenyWriteExecute, and can only write to /var/lib/qorionix-sensor and its log file. Restart policy is Restart=always with RestartSec=5, and the start-limit budget is widened to ten restarts in five minutes — systemd's default of five in ten seconds is the wrong budget for a security agent, because it gives up permanently at exactly the moment you most want it trying again.

What the sensor needs from the kernel

The service does not run as root. Instead the unit pins exactly four capabilities, in both the ambient set and the bounding set, so the process holds these and nothing more:

The four Linux capabilities the sensor unit requests, and what each one is for. Anything not on this list is outside the bounding set and unavailable to the process.
CapabilityWhy it is needed
CAP_SYS_PTRACERead details of processes owned by other users from /proc.
CAP_DAC_READ_SEARCHRead files and directory entries the service account would otherwise be refused.
CAP_AUDIT_READRead the kernel audit stream.
CAP_NET_ADMINApply and remove the host firewall ruleset used by network isolation.

Beyond those, three collectors run concurrently and they are not equally important:

The procfs process differ — the source of record
It reads the process table from /proc every two seconds and diffs it. It always works, it carries the parent linkage and the full command line, and it depends on nothing being installed. This is what behavioural detection actually runs on.
The file watcher
A bounded scan of a few directory trees every five seconds, recording path, size and entropy. Its job is the burst shape that mass file encryption produces. Default roots are /home, /srv and /var/www; set QX_WATCH_PATHS (ZQ_WATCH_PATHS is still read as a fallback this release) to change them.
The auditd tail — useful, optional
It follows /var/log/audit/audit.log for syscall-level context that procfs cannot give. If that file is absent — a container, an unprivileged laptop, most non-RHEL default installs — this collector degrades to a 30-second heartbeat and the other two carry on regardless.

Two things are not available on Linux, and both bound what can ever be detected. There is no eBPF collector in the shipped package — the build tag exists, the compiled program lives outside the distribution build, and it is excluded from the artefacts you download, so treat eBPF as not shipped. And the sensor is a userland poller rather than a kernel callback: a process that starts and exits inside one two-second interval is missed. That trade buys an agent with no kernel module, no compiler, no headers and no dependency on your distribution's kernel version, which on a mixed fleet is worth a great deal. It is still a real gap and it is listed as one.

Confirming it is running

The checks the installer itself prints
sudo systemctl status qorionix-sensor
sudo journalctl -u qorionix-sensor -n 50

An active unit is necessary and not sufficient. The check that counts is the machine appearing under Endpoints in the console with a recent last-seen time, usually within a minute. A sensor that installed cleanly but never enrolled looks perfectly healthy from the host and does not exist as far as the platform is concerned.

In the journal, the messages worth recognising are these. Repeats of the same message are throttled to one line every five minutes, with a (<n> similar messages suppressed) suffix, so a machine that has been offline overnight does not fill your log.

Sensor messages in the journal
sensor: cannot reach <endpoint> (<err>) — <n> events dropped
sensor: telemetry rejected with HTTP <code> — <n> events dropped
sensor: telemetry delivery recovered
sensor: enrolled as <sensor-id> after <n> attempt(s)
sensor: no credential configured — this endpoint will not report. Re-run the installer with an enrolment token from Settings -> Endpoints -> Enrolment tokens.

To re-enrol a machine without reinstalling the package, run the enroll subcommand and restart the unit. --token, --config and --api are all required — pass the console origin you were given at enrolment as --api. --timeout defaults to 20s.

Manual re-enrolment
sudo qorionix-sensor enroll --token <TOKEN> --api <URL> --config /etc/qorionix/qorionix-sensor.yaml && sudo systemctl restart qorionix-sensor

Upgrading and removing

Upgrade by installing the newer package over the old one — sudo apt-get install -y ./qorionix-sensor.deb or sudo dnf install -y ./qorionix-sensor.rpm. The config file is marked as a configuration file that must not be replaced, so the machine's credential survives the upgrade and no re-enrolment is needed; the package's post-install step restarts the unit. There is no automatic update mechanism at all, which is a limitation rather than a preference — Keeping the sensor up to date explains how to run this across a fleet.

To remove it, remove the package: sudo apt-get remove qorionix-sensor or sudo dnf remove qorionix-sensor. As on every platform, removing the software does not remove the endpoint from your console — it reads as stale fifteen minutes after its last telemetry and stays there. Revoke the sensor in the console if the machine is gone for good; a revoked sensor is refused with sensor auth: sensor revoked even if someone restores the disk image later.

What to do next

  1. Enrolment tokens — token scoping, lifetimes and every failure message, verbatim.
  2. What the sensor collects — the per-platform list, including what is deliberately not gathered.
  3. The endpoint list and endpoint health — what stale means and the ordinary reasons for it.

Was this article wrong?

If a procedure here does not match what you see, or a limit we described has changed, tell us and we will fix the page. Email us about this article, or see how to get help if you need an answer rather than a correction.

Everything in endpoints and response