Podman

Deploy the LinuxGuard agent under Podman — rootless vs rootful trade-offs, systemd quadlet integration, Docker-equivalent commands.

Podman is a daemonless container engine that runs containers as ordinary user processes. The LinuxGuard agent runs under Podman with two distinct trade-offs: rootful (full eBPF telemetry, ergonomically equivalent to Docker) or rootless (least-privilege execution, restricted telemetry surface). This page documents both shapes plus systemd quadlet integration for hosts where the agent should be a system service.

Important: Rootless Podman cannot grant CAP_BPF + CAP_PERFMON to the container because user namespaces do not propagate the host's eBPF capabilities to the container's PID-1. Rootless agents run in DEGRADED_PROBES_PARTIAL mode — the agent process starts and produces non-eBPF telemetry, but no behavioral, auth, or file-monitor events are produced. Use rootful Podman when full telemetry coverage is required.

When to use Podman

  • Hosts where Docker daemon access is restricted (locked-down workstations, hardened servers, multi-tenant build hosts). Podman's daemonless model fits the security posture.

  • systemd-native deployments where the agent should be a --user or system service managed by systemctl. The quadlet integration is canonical for this shape.

  • RHEL / Fedora / SUSE hosts where Podman is the supported container engine and Docker is not packaged.

If your host runs Docker, the docker-compose shape (docker-compose deployment) is simpler — Podman's podman-compose is API-compatible but has fewer eyes on it.

Rootless vs rootful trade-offs

Property
Rootful Podman
Rootless Podman

eBPF probes

Yes (full)

No — user namespaces drop the agent's caps; loader degrades to DEGRADED_PROBES_PARTIAL

Behavioral telemetry

Yes

No

Auth events

Yes

No

File monitor

Yes

No

Configuration management

Yes

Yes

Package inventory

Yes

Yes

Syslog forwarding

Yes

Yes

support-bundle collect

Yes

Yes

Privilege required to start

sudo podman or member of the podman group

Any user; no privilege elevation

Host filesystem visibility

Full

User-namespace remapped

pid=host

Available

Available but limited to the user's own processes

Image storage location

/var/lib/containers/

~/.local/share/containers/

Choose rootful when behavioral telemetry coverage is required (the standard case for a security agent).

Choose rootless when the host's security policy forbids daemonless privileged containers AND the agent's role is limited to configuration management, package inventory, or syslog forwarding (a narrow surface).

Rootful Podman

The rootful shape is ergonomically equivalent to a Docker run with the same flags. The only difference is the engine binary.

Minimal invocation

The flags match the Docker equivalent line-for-line; see docker-compose deployment for the rationale on each.

Differences from Docker

  • sudo prefix — rootful Podman requires either sudo or membership in the podman group. The podman group has no default member; add users explicitly via usermod -aG podman <user>.

  • No daemon to start — Podman is daemonless. There is no systemctl start podman for the rootful case (the podman.socket unit is used only for the Docker-compatibility API).

  • Image storage — rootful Podman stores images in /var/lib/containers/. Free space requirements match Docker's /var/lib/docker/.

  • SELinux labeling — on RHEL/CentOS/Fedora hosts with SELinux enforcing, Podman applies the container_t type to the container's processes. Host-path mounts may require :z or :Z suffix for SELinux relabeling — see § SELinux considerations.

Rootless Podman

Rootless Podman runs the container in a user namespace owned by the invoking user. Capabilities granted at --cap-add time are scoped to that namespace, not the host's. The agent's eBPF loader detects this at startup and degrades to DEGRADED_PROBES_PARTIAL mode.

Minimal invocation (rootless)

Notes on what is OMITTED from the rootless invocation:

  • No --cap-add flags — the capabilities are scoped to the user namespace and have no effect on the host eBPF subsystem. The agent will log a startup warning about degraded mode.

  • No --pid=host — rootless Podman cannot grant host PID visibility; the agent sees only the user's own processes.

  • No tracefs bind-mount — without CAP_BPF the agent does not attempt probe attach.

  • No host /proc mount.

Verifying degraded mode

After the agent starts, the log should contain a clear degradation marker:

If your security policy permits, switch to the rootful shape to recover the eBPF telemetry surface. Otherwise, document the rootless deployment as a known coverage gap.

systemd quadlet integration

A quadlet is a systemd unit file that describes a Podman container in a declarative, systemd-native way. Quadlets are preferred over podman generate systemd (which generates verbose units that mix Podman state into systemd state) because they are simpler, idempotent, and version-controlled like any other systemd unit.

Rootful quadlet

Place the following file at /etc/containers/systemd/linuxguard-agent.container:

Generate the systemd unit and enable it:

The EnvironmentFile=/etc/linuxguard/enroll.env references a file with the token + tenant ID:

Restrict permissions on the env file:

Only root and the linuxguard group can read the env file. systemd reads it as root when the service starts; the value is then injected into the container's environ block via Podman.

Rootless quadlet

Place the file at ~/.config/containers/systemd/linuxguard-agent.container (note the user-scoped path):

Enable as a user service:

The rootless quadlet inherits the same degradation properties as the rootless podman run invocation — see § Rootless Podman.

Docker-equivalent commands

For operators familiar with Docker, the table below maps common workflows to their Podman equivalents. The agent's behavior is identical under either engine.

Docker
Podman
Notes

docker run ...

podman run ...

Identical syntax. Rootful Podman requires sudo.

docker compose up -d

podman-compose up -d

podman-compose is a Python wrapper; install with pip install podman-compose or via distro package.

docker ps

podman ps

Identical.

docker logs -f linuxguard-agent

podman logs -f linuxguard-agent

Identical.

docker exec linuxguard-agent <cmd>

podman exec linuxguard-agent <cmd>

Identical. The distroless image has no shell; pass a specific command.

docker stop linuxguard-agent

podman stop linuxguard-agent

Identical. Sends SIGTERM; agent exits 143.

docker pull <image>

podman pull <image>

Identical.

docker login <registry>

podman login <registry>

Identical. Credentials stored in ~/.config/containers/auth.json.

docker inspect <ctr>

podman inspect <ctr>

Identical output structure.

docker system df

podman system df

Identical.

SELinux considerations

On RHEL / CentOS / Fedora / Rocky Linux hosts with SELinux enforcing, Podman applies the container_t type to processes inside the container. Host-path mounts must be relabeled or the agent's reads from /sys/kernel/tracing are denied with avc: denied.

Two options:

Option 1: :z / :Z mount suffix

Append :z (shared label) or :Z (private label) to the -v flag value. This is the simplest approach for single-host deployments:

:z relabels the host directory so the container can read it AND other containers can read it (shared). :Z relabels for exclusive access by this one container. For /sys/kernel/tracing (a kernel pseudo-filesystem, not real disk), :z is appropriate.

Option 2: Set the agent's SELinux profile at host level

Install the SELinux policy that ships with the agent's packaging tree, then label the agent's process with the policy's domain:

This is the production path. It avoids the :z / :Z relabel side effect on host directories.

Verifying SELinux is not blocking

If recent AVC denials appear, set SELinux to permissive temporarily to confirm the agent works in the absence of policy enforcement:

Then apply Option 1 or Option 2 to allow the agent under enforcing mode.

Security context

The rootful Podman security context is equivalent to the Kubernetes DaemonSet shape — see Kubernetes DaemonSet § Line-by-line rationale for the per-capability rationale. The rootless Podman security context inherits the user namespace's degradation as documented in § Rootless vs rootful trade-offs.

Common to both: read_only filesystem, tmpfs for the TLS cache, no privilege escalation needed (file caps baked into the binary), nonroot user (UID 65532 inside the container, remapped to a high UID range in the rootless case).

Host paths

Identical to the Kubernetes DaemonSet host-path requirements for the rootful case — see Kubernetes DaemonSet § Host paths. The rootless case omits the host-path mounts entirely because the user namespace cannot productively use them.

Security Note: For SELinux-enforcing hosts, mount each host path with :z (or apply the SELinux module per Option 2 above). For the rootless case, do not mount host paths — the user namespace cannot use them.

Pod Security Standard compatibility

PSS is a Kubernetes concept; it does not apply to Podman. The Podman equivalent is the combination of --cap-add / --cap-drop, --security-opt, --read-only, --tmpfs, --pid, and the rootful-vs-rootless distinction. The rootful Podman shape corresponds to PSS privileged (because of --pid=host and the added capabilities); the rootless shape has no Kubernetes analogue.

RBAC

RBAC is a Kubernetes concept; it does not apply to Podman. The Podman equivalent is filesystem access control on the Podman binary and the user namespace:

  • Rootful — access is controlled by sudo policy or podman group membership. Restrict membership to trusted users.

  • Rootless — access is per-user. The Podman binary itself is unprivileged; the user namespace determines what the container can see.

For the quadlet integration, systemd's unit-file permissions (/etc/containers/systemd/ for rootful, ~/.config/containers/systemd/ for rootless) control who can modify the agent's deployment manifest.

Verification

After starting the agent (via podman run, podman-compose, or the quadlet service):

A healthy rootful agent produces a heartbeat log line within 20 seconds. A degraded rootless agent produces the degradation warning, then a heartbeat with the reduced telemetry surface.


Next Step: OCI multi-arch manifest →

Related: Container deployment hub | docker-compose deployment | Kubernetes DaemonSet | Distroless image reference | probe CLI reference

Last updated

Was this helpful?