Skip to main content

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 familyVersionsPackageInit systemSELinux
Red Hat Enterprise Linux (RHEL)8, 9, 10rpmsystemd✅ supported (enforcing)
Rocky Linux8, 9rpmsystemd✅ supported (enforcing)
AlmaLinux8, 9rpmsystemd✅ supported (enforcing)
CentOS Stream9, 10rpmsystemd✅ supported (enforcing)
Oracle Linux8, 9rpmsystemd✅ supported (enforcing)
Amazon Linux2, 2023rpmsystemd✅ supported (enforcing)
Fedoracurrent stablerpmsystemd✅ supported (enforcing)
SUSE Linux Enterprise Server (SLES)15rpm (zypper)systemdn/a (AppArmor by default)
openSUSE Leap15rpm (zypper)systemdn/a (AppArmor by default)
Ubuntu LTS20.04, 22.04, 24.04debsystemdn/a (AppArmor by default)
Debian11, 12debsystemdn/a (AppArmor by default)
note

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 accountpraxiscollector (/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 on 514). It is granted as an ambient capability by systemd at process start — not with setcap on the binary — so it survives package upgrades. By default the collector holds no CAP_NET_RAW, CAP_DAC_READ_SEARCH, CAP_SYS_PTRACE, or CAP_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 (no setuid, no sudo, no capability escalation).
  • Log access is by group membership, not a privilege bypass. Where the host has them, the service is added to the adm and systemd-journal groups so it can read group-readable logs under /var/log and the systemd journal. It cannot read arbitrary root-only 0600 files such as /var/log/audit.
  • Credentials are stored with restricted permissions. The OAuth2 key/secret and encrypted pipeline config under /opt/praxis-collector/cfg are group-private (0750 directory, 0640 files), 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 sudo and never transitions into the package-manager domain. See Self-upgrade below.
tip

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)

  1. Pre-install — create the service account. A dedicated praxiscollector system 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.
  2. Unpack files. rpm installs the binaries and assets under /opt/praxis-collector and the systemd units under /lib/systemd/system. On SELinux hosts, rpm applies the correct file labels during this transaction.
  3. Post-install — set ownership and least privilege.
    • Hands the install tree to the praxiscollector account 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 adm and systemd-journal supplementary groups — but only those that exist on the host, so a minimal image still starts.
    • Removes any legacy sudo grant from older installs (the upgrade path no longer uses sudo).
  4. SELinux. On an enforcing host 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.
  5. 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.

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:

  • dpkg drives the transaction instead of rpm.
  • 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 enforcing mode, out of the box. With the standard targeted policy, the collector binary is labeled bin_t under /opt and runs in the default domain. The service starts normally — there is no status=203/EXEC failure — 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 enforcing mode 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:

  1. The unprivileged collector downloads the new signed package from your allowlisted artifact host, verifies it, and stages it under /opt/praxis-collector/run with an upgrade request marker.
  2. A root-owned systemd watcher (praxis-collector-update.path) notices the request and runs a small root installer unit that installs the staged package with rpm/dpkg. The collector itself never holds sudo and never transitions into the package-manager domain — which is exactly what keeps the SELinux story small.
  3. 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.
  4. 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

PathPurposeOwnerNotes
/opt/praxis-collector/binCollector + updater binariesroot (helper) / praxiscollectorReplaced by the package manager on upgrade
/opt/praxis-collector/cfgConfig + encrypted credentialspraxiscollectorGroup-private (0750 / 0640)
/opt/praxis-collector/metadataRuntime state (offsets, file storage)praxiscollector0750
/opt/praxis-collector/runUpgrade staging + lock/markerspraxiscollector0750
/opt/praxis-collector/selinuxSELinux policy assets (if shipped)rootNot writable by the service account
/var/log/praxis-collectorCollector's own logpraxiscollectorDirectory owned by service account for rotation
/etc/default/praxis-collector or /etc/sysconfig/praxis-collectorOptional site overridesrootRead before install (see below)
/lib/systemd/system/praxis-collector.serviceMain service unitroot
/lib/systemd/system/praxis-collector-update.pathRoot self-upgrade watcherroot

Run-as options

Set these in /etc/default/praxis-collector (Debian/Ubuntu) or /etc/sysconfig/praxis-collector (RHEL-family) before installing:

VariableDefaultEffect
PRAXIS_RUN_AS_ROOTfalsetrue runs the service as root (use only when you need root-only log access or ptrace process discovery).
PRAXIS_USER / PRAXIS_GROUPpraxiscollectorRun as a different unprivileged account.
PRAXIS_SKIP_RUNTIME_USER_CREATIONfalsetrue when the account is pre-provisioned by your configuration management; the installer will not create it.
PRAXIS_LOAD_SELINUX_MODULEfalsetrue loads the opt-in confined SELinux module (advanced; requires a prebuilt module).
PRAXIS_ENABLE_PCAPfalsetrue 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_SEARCHfalsetrue 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_PTRACEfalsetrue 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 flagEnv variableCapability grantedEnablessystemd drop-in
--enable-pcapPRAXIS_ENABLE_PCAPCAP_NET_RAWPCAP packet-capture source20-pcap.conf
--enable-dac-read-searchPRAXIS_ENABLE_DAC_READ_SEARCHCAP_DAC_READ_SEARCHreading root-only logs (e.g. /var/log/audit/audit.log)25-dac-read-search.conf
--enable-sys-ptracePRAXIS_ENABLE_SYS_PTRACECAP_SYS_PTRACEhost-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.

warning

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.

warning

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.