Enterprise Linux & SELinux support
The Praxis collector is built to meet enterprise Linux security and change-control expectations: it installs from signed native packages (rpm / deb), runs as a dedicated unprivileged service account with a single Linux capability, and runs cleanly on SELinux hosts in enforcing mode without weakening your policy.
This page documents the supported distributions, the security model, exactly what the installer does on each platform family, SELinux behavior, and the self-upgrade flow — so your platform and security teams can review and approve the collector with confidence.
Looking for the quickstart command? See Install the Praxis collector on Linux. This page is the deeper reference for enterprise and SELinux environments.
Supported distributions
The collector ships as x86_64/amd64 and aarch64/arm64 native packages.
| Distribution family | Versions | Package | Init system | SELinux |
|---|---|---|---|---|
| Red Hat Enterprise Linux (RHEL) | 8, 9, 10 | rpm | systemd | ✅ supported (enforcing) |
| Rocky Linux | 8, 9 | rpm | systemd | ✅ supported (enforcing) |
| AlmaLinux | 8, 9 | rpm | systemd | ✅ supported (enforcing) |
| CentOS Stream | 9, 10 | rpm | systemd | ✅ supported (enforcing) |
| Oracle Linux | 8, 9 | rpm | systemd | ✅ supported (enforcing) |
| Amazon Linux | 2, 2023 | rpm | systemd | ✅ supported (enforcing) |
| Fedora | current stable | rpm | systemd | ✅ supported (enforcing) |
| SUSE Linux Enterprise Server (SLES) | 15 | rpm (zypper) | systemd | n/a (AppArmor by default) |
| openSUSE Leap | 15 | rpm (zypper) | systemd | n/a (AppArmor by default) |
| Ubuntu LTS | 20.04, 22.04, 24.04 | deb | systemd | n/a (AppArmor by default) |
| Debian | 11, 12 | deb | systemd | n/a (AppArmor by default) |
SELinux is an RPM-family concern. RHEL-family distributions ship SELinux and use the SELinux-aware rpm installer. Debian and Ubuntu ship AppArmor (not SELinux) and use dpkg. So in practice, "SELinux support" applies to the RPM install path, and the collector is validated on RHEL-family hosts in enforcing mode.
:::tip Validated on both security layers
The collector's unprivileged runtime and self-upgrade are validated end-to-end on both Linux mandatory-access-control layers: SELinux in enforcing mode (RHEL-family, rpm) and AppArmor (Ubuntu/Debian, deb). On both, the collector installs, runs as the unprivileged service account, connects to Praxis, and self-upgrades with no security-policy denials.
:::
The security model
The collector follows a least-privilege model so it can be deployed broadly without granting it root:
- Runs as a dedicated, unprivileged system account —
praxiscollector(/usr/sbin/nologin, a low system UID, home set to the install directory). It is not root and cannot log in. - One Linux capability by default —
CAP_NET_BIND_SERVICE. This is the single privilege the collector genuinely needs out of the box: binding privileged ports below 1024 (for example a syslog receiver on514). It is granted as an ambient capability bysystemdat process start — not withsetcapon the binary — so it survives package upgrades. By default the collector holds noCAP_NET_RAW,CAP_DAC_READ_SEARCH,CAP_SYS_PTRACE, orCAP_NET_ADMIN. Specific sources (packet capture, root-only logs, host process metrics) can be enabled per host with explicit, install-time capability opt-ins — each adds exactly one capability and nothing else, so you never have to choose between "lean" and "full root." See Host capability opt-ins. NoNewPrivileges=true. The process and its children can never acquire new privileges (nosetuid, nosudo, no capability escalation).- Log access is by group membership, not a privilege bypass. Where the host has them, the service is added to the
admandsystemd-journalgroups so it can read group-readable logs under/var/logand thesystemdjournal. It cannot read arbitrary root-only0600files such as/var/log/audit. - Credentials are stored with restricted permissions. The OAuth2 key/secret and encrypted pipeline config under
/opt/praxis-collector/cfgare group-private (0750directory,0640files), owned by the service account. - Signed packages and verified downloads. Packages are signed; self-upgrade downloads are pulled only from your organization's allowlisted artifact host and verified by checksum before install.
- The privileged upgrade step is decoupled from the collector. The collector itself never holds
sudoand never transitions into the package-manager domain. See Self-upgrade below.
If a use case genuinely requires reading root-only logs (for example /var/log/audit) or ptrace-based process discovery, prefer the granular capability opt-ins (--enable-dac-read-search, --enable-sys-ptrace) — they grant exactly the one capability that source needs and keep the rest of the lean model intact. Running fully as root (PRAXIS_RUN_AS_ROOT=true, see Run-as options) remains available as the broad fallback. The default and recommended posture is the unprivileged account above.
What the installer does
The installer is the native package (rpm or deb). Whether you run a Praxis-provided install script, your configuration-management tooling, or the package command directly, the same package maintainer steps run. Below is exactly what happens, end to end.
RPM-based hosts (RHEL, Rocky, AlmaLinux, CentOS Stream, Oracle, Amazon Linux, Fedora, SLES)
- Pre-install — create the service account. A dedicated
praxiscollectorsystem group and user are created (idempotently; a re-install or upgrade reuses the existing account). On an upgrade, the step records that the running service should be restarted afterward, and deliberately does not stop it mid-transaction. - Unpack files.
rpminstalls the binaries and assets under/opt/praxis-collectorand thesystemdunits under/lib/systemd/system. On SELinux hosts,rpmapplies the correct file labels during this transaction. - Post-install — set ownership and least privilege.
- Hands the install tree to the
praxiscollectoraccount so the collector can write its runtime state, rotate its own log, and stage upgrades — except the root-owned upgrade helper and SELinux assets, whose root ownership is re-asserted so the unprivileged account can never modify code that root executes. - Locks down
cfg/(credentials) to group-private permissions. - Creates and owns
/var/log/praxis-collector(the service account must own the directory so log rotation by rename succeeds). - Adds the
admandsystemd-journalsupplementary groups — but only those that exist on the host, so a minimal image still starts. - Removes any legacy
sudogrant from older installs (the upgrade path no longer usessudo).
- Hands the install tree to the
- SELinux. On an
enforcinghost the collector runs in the default domain with no extra module required (see SELinux behavior). No custom policy is loaded unless you explicitly opt in. - Enable services.
- Enables and starts the root-owned self-upgrade watcher (
praxis-collector-update.path). - Enables
praxis-collector.service. - On a fresh install, the service is enabled but not started — the install wrapper applies your enrollment configuration first.
- On an upgrade, a deferred restart is scheduled that waits for the package manager to finish before restarting, so an in-flight transaction is never killed.
- Enables and starts the root-owned self-upgrade watcher (
DEB-based hosts (Ubuntu, Debian)
The deb package runs the same maintainer steps as the RPM above — create the praxiscollector account, install to /opt/praxis-collector, apply unprivileged ownership and the single capability, add log groups, enable the units, and (on upgrade) schedule a deferred restart. The differences are mechanical:
dpkgdrives the transaction instead ofrpm.- These distributions use AppArmor, not SELinux, so no SELinux relabeling or module handling applies.
SELinux behavior
The collector is designed to run on SELinux hosts without disabling or weakening enforcement.
- Works in
enforcingmode, out of the box. With the standardtargetedpolicy, the collector binary is labeledbin_tunder/optand runs in the default domain. The service starts normally — there is nostatus=203/EXECfailure — and the upgrade flow completes with zero AVC denials. - Relabel-on-upgrade. Because the install path is
rpm(which is SELinux-aware), file labels are applied and corrected during every package transaction, so upgrades survive cleanly. - Validated. The unprivileged install, the service runtime, and a full backend-driven (OpAMP) self-upgrade were validated on Rocky Linux 9 in
enforcingmode with no AVC denials in the default domain. - No policy changes required. You do not need to set the host
permissive, add booleans, or ship a custom module for the supported configuration.
Verify under SELinux
# Confirm SELinux is enforcing
getenforce
# Confirm the service is running and see its SELinux context
systemctl status praxis-collector
ps -eZ | grep praxis-collector
# Confirm there are no denials attributable to the collector
sudo ausearch -m avc -ts recent 2>/dev/null | grep -i praxis || echo "no recent praxis AVC denials"
Optional: confined custom domain (advanced)
For teams that want the collector to run in its own confined SELinux domain (rather than the default bin_t domain), the package can ship a custom policy module. This is opt-in and not required — the default domain is the supported, validated configuration. When you and Red Hat (or your policy owner) have reviewed and pre-compiled the module for your fleet, enable it before install:
# /etc/default/praxis-collector (or /etc/sysconfig/praxis-collector)
PRAXIS_LOAD_SELINUX_MODULE=true
The installer then loads the prebuilt module and relabels the install tree. If loading fails for any reason, the collector falls back to the working default domain.
Self-upgrade (signed and decoupled)
When Praxis instructs a collector to upgrade, the privileged step is kept out of the collector's process:
- The unprivileged collector downloads the new signed package from your allowlisted artifact host, verifies it, and stages it under
/opt/praxis-collector/runwith an upgrade request marker. - A root-owned
systemdwatcher (praxis-collector-update.path) notices the request and runs a small root installer unit that installs the staged package withrpm/dpkg. The collector itself never holdssudoand never transitions into the package-manager domain — which is exactly what keeps the SELinux story small. - The upgrade is single-flight (one request is processed at a time) and version-gated — it proceeds only to a strictly higher version, never a downgrade or re-install.
- A deferred restart brings the new version online after the package transaction completes, so a running collector is never killed mid-upgrade.
This is the same model on every supported distribution; on enforcing SELinux hosts the entire flow runs with no AVC denials.
File & directory layout
| Path | Purpose | Owner | Notes |
|---|---|---|---|
/opt/praxis-collector/bin | Collector + updater binaries | root (helper) / praxiscollector | Replaced by the package manager on upgrade |
/opt/praxis-collector/cfg | Config + encrypted credentials | praxiscollector | Group-private (0750 / 0640) |
/opt/praxis-collector/metadata | Runtime state (offsets, file storage) | praxiscollector | 0750 |
/opt/praxis-collector/run | Upgrade staging + lock/markers | praxiscollector | 0750 |
/opt/praxis-collector/selinux | SELinux policy assets (if shipped) | root | Not writable by the service account |
/var/log/praxis-collector | Collector's own log | praxiscollector | Directory owned by service account for rotation |
/etc/default/praxis-collector or /etc/sysconfig/praxis-collector | Optional site overrides | root | Read before install (see below) |
/lib/systemd/system/praxis-collector.service | Main service unit | root | |
/lib/systemd/system/praxis-collector-update.path | Root self-upgrade watcher | root |
Run-as options
Set these in /etc/default/praxis-collector (Debian/Ubuntu) or /etc/sysconfig/praxis-collector (RHEL-family) before installing:
| Variable | Default | Effect |
|---|---|---|
PRAXIS_RUN_AS_ROOT | false | true runs the service as root (use only when you need root-only log access or ptrace process discovery). |
PRAXIS_USER / PRAXIS_GROUP | praxiscollector | Run as a different unprivileged account. |
PRAXIS_SKIP_RUNTIME_USER_CREATION | false | true when the account is pre-provisioned by your configuration management; the installer will not create it. |
PRAXIS_LOAD_SELINUX_MODULE | false | true loads the opt-in confined SELinux module (advanced; requires a prebuilt module). |
PRAXIS_ENABLE_PCAP | false | true grants CAP_NET_RAW so this host can run a PCAP (packet capture) source. The install script's --enable-pcap flag sets this for you. |
PRAXIS_ENABLE_DAC_READ_SEARCH | false | true grants CAP_DAC_READ_SEARCH so the collector can read root-only logs such as /var/log/audit/audit.log. The install script's --enable-dac-read-search flag sets this. Bypasses all DAC read checks — review before enabling. |
PRAXIS_ENABLE_SYS_PTRACE | false | true grants CAP_SYS_PTRACE so the host-metrics process scraper can read /proc/<pid>/ of other users' processes. The install script's --enable-sys-ptrace flag sets this. Also allows reading any process's memory. |
Host capability opt-ins
The lean default holds only CAP_NET_BIND_SERVICE. Three sources need an additional Linux capability, and each is a deliberate, host-level, install-time opt-in — so a remote pipeline change can never silently widen a host's privileges. Each opt-in adds exactly one ambient capability via its own systemd drop-in (layered on top of the lean set) and is recorded in the package env file so it persists across auto-updates.
| Install flag | Env variable | Capability granted | Enables | systemd drop-in |
|---|---|---|---|---|
--enable-pcap | PRAXIS_ENABLE_PCAP | CAP_NET_RAW | PCAP packet-capture source | 20-pcap.conf |
--enable-dac-read-search | PRAXIS_ENABLE_DAC_READ_SEARCH | CAP_DAC_READ_SEARCH | reading root-only logs (e.g. /var/log/audit/audit.log) | 25-dac-read-search.conf |
--enable-sys-ptrace | PRAXIS_ENABLE_SYS_PTRACE | CAP_SYS_PTRACE | host-metrics process scraper (other users' /proc/<pid>/) | 30-sys-ptrace.conf |
Set the flag on the install command, or set the env variable in /etc/default/praxis-collector (Debian/Ubuntu) or /etc/sysconfig/praxis-collector (RHEL-family) before installing. These flags exist on the Linux/RHEL install scripts only — packet capture, audit-log read, and process metrics are not available on macOS or Windows. None has any effect when PRAXIS_RUN_AS_ROOT=true (root already holds every capability).
CAP_NET_RAW — packet capture
The PCAP source needs CAP_NET_RAW to open an AF_PACKET socket. Enable it with --enable-pcap. Once a host is enabled, pipelines can add or remove a pcap source over OpAMP with no reinstall; a pcap source on a host that was not enabled fails closed with a clear permission error. Promiscuous-mode capture (SPAN/mirror ports) additionally requires CAP_NET_ADMIN and must be enabled on the interface out-of-band.
CAP_DAC_READ_SEARCH — root-only logs
Reading files that only root can open — chiefly the audit log at /var/log/audit/audit.log (root:root 0600, no group to join) — needs CAP_DAC_READ_SEARCH. Enable it with --enable-dac-read-search.
This capability bypasses all DAC read/search checks: a process that holds it can read any file on the host (/etc/shadow, private keys, anything), not just logs. Enable it only when ingesting root-only logs is required and that read scope is acceptable. For general root access, use PRAXIS_RUN_AS_ROOT=true instead.
CAP_SYS_PTRACE — host process metrics
The host-metrics process scraper reads /proc/<pid>/ for processes owned by other users, which the kernel allows only with CAP_SYS_PTRACE (this also bypasses the yama ptrace_scope restriction). Enable it with --enable-sys-ptrace.
CAP_SYS_PTRACE also allows attaching to and reading the memory of any process on the host, which can expose in-memory secrets. Enable it only where host-wide process metrics are required.
Under SELinux enforcing
All three capabilities work in the default domain with no extra policy. If you run the optional confined SELinux module, it must include the matching type-enforcement rules — the dac_read_search / sys_ptrace capability allows plus the audit-log-type read and cross-domain /proc read. The shipped policy contains these blocks (kept inert until the ambient capability is actually granted), but they are broad and host-specific, so validate them on a real enforcing host with audit2allow and confirm with ausearch -m avc after enabling.
Verify the install
# Service is enabled and active
systemctl is-enabled praxis-collector
systemctl status praxis-collector
# It runs as the unprivileged account with the single capability
ps -o user,comm -C praxis-collector
systemctl show praxis-collector -p User -p AmbientCapabilities -p NoNewPrivileges
# Healthy OpAMP session to Praxis
sudo journalctl -u praxis-collector -f | grep -iE "opamp|connect"
In Praxis, confirm the collector instance shows online and your pipeline is attached.
Uninstall
Removing the package (rpm -e / apt-get remove, or your runbook's uninstall script) stops and disables the collector service and the root self-upgrade watcher, unloads the SELinux module if one was loaded, and removes the run-as systemd drop-ins. On a true uninstall (not an upgrade) it also removes the install tree and logs, the dedicated praxiscollector service account, and the site-override env file (/etc/default or /etc/sysconfig/praxis-collector) — so no capability opt-in silently carries over to a future fresh install. An upgrade preserves all of these. The account is left untouched if you pre-provisioned it (PRAXIS_SKIP_RUNTIME_USER_CREATION=true) or ran the collector as root.
Related
- Install the Praxis collector on Linux — quickstart, proxy configuration, and uninstall.
- macOS and Windows — other single-host options.
- Installation overview — how the host collector fits with Kubernetes and the Praxis Gateway.