Ephemeral mode
Configure the LinuxGuard agent in ephemeral container mode — TOTP enrol, in-memory cert chain, PID 1 auto-detection, TLS cache restart semantics.
Ephemeral mode is the container-friendly operating shape of the LinuxGuard agent. The agent enrols once via a short-lived TOTP token, holds the resulting mTLS cert chain in memory, skips PID-file machinery (the orchestrator owns lifecycle), and never writes to /var/lib/linuxguard/. This page documents the trigger conditions, the runtime behavior, and the restart semantics — including the optional TLS cache that survives container restarts without re-enrolling.
Important: Ephemeral mode is selected by any of the following triggers: the
--ephemeralflag, a non-empty--enroll-token(or itsLINUXGUARD_ENROLL_TOKENenv-var binding),os.Getpid() == 1(the agent is the container's init process), or theLINUXGUARD_PID1_CHILDre-exec sentinel. Explicit--ephemeralis NOT required when any of the implicit triggers fires.
When ephemeral mode is the right choice
Ephemeral mode is designed for containers whose lifecycle is owned by the orchestrator and whose workload identity is derived from the container's runtime context, not from a persisted enrollment on disk:
Kubernetes DaemonSet pods — node-level coverage, workload identity from the Downward API.
Kubernetes sidecars — pod-level coverage, workload identity from
metadata.uid.Docker / Podman containers running as PID 1 — single-tenant edge appliance, CI runner, build container.
One-shot CI / build jobs — a fresh enrol per invocation, no persistent state.
It is NOT the right choice for:
A long-lived host installation managed by systemd. Use the per-distro install guides for that shape.
A container that runs the agent as a non-PID-1 worker alongside an application. The PID-file machinery the agent skips in ephemeral mode is the same machinery that prevents two
startinvocations from competing for the same host identity. Use the host install path inside the container instead.
Flags consumed by ephemeral mode
The flags below are the surface ephemeral mode actually consumes. The full start flag reference (defaults, env-var bindings, source line numbers) lives at start CLI reference.
--ephemeral
Explicit trigger. Optional when any implicit trigger fires (PID 1, non-empty --enroll-token, LINUXGUARD_PID1_CHILD).
--enroll-token
TOTP enrolment token. Prefer the LINUXGUARD_ENROLL_TOKEN env var so the token does not appear on the command line (see Enrollment tokens).
--tenant-id
Tenant the agent enrols into. Required on the TOTP path — the backend's /agent/enroll handler rejects with 400 "tenantId required for TOTP enrollment" when missing. Bound to LINUXGUARD_TENANT_ID.
--workload-id
Explicit workload identifier (sha256 hex). Required only when the Downward API env vars are absent. Hard-error if neither --workload-id nor LINUXGUARD_NODE_NAME + LINUXGUARD_POD_UID are set.
--node-id
Kubernetes node name from the Downward API. Bound to LINUXGUARD_NODE_NAME. Feeds the workload-id derivation when --workload-id is not provided.
--tls-cache
Opt-in: mirror the cert chain + token-hash tag to /run/linuxguard/tls/ (mode 0700/0600) so a container restart can reuse the cache without re-enrolling. Off by default. Requires a tmpfs mount at /run/linuxguard.
--loader-embedded
Force the in-process embedded eBPF loader. Auto-on under PID 1 or --ephemeral when the binary was built with the loader_embedded build tag (the published image is built with this tag set). Bound to LINUXGUARD_LOADER_EMBEDDED.
--api-url
Override the LinuxGuard API base URL. Bound to LINUXGUARD_API_URL. Whitespace-only values treated as empty. Channel default applies when absent.
LINUXGUARD_POD_UID is read directly via os.Getenv — it has no flag binding. It pairs with LINUXGUARD_NODE_NAME for the workload-id derivation.
PID 1 auto-detection
The agent inspects its own PID at startup. When os.Getpid() == 1 (or when the LINUXGUARD_PID1_CHILD sentinel is set by the agent's own init re-exec wrapper), ephemeral semantics activate even if the --ephemeral flag was not passed. This matches the common container pattern of running the agent as the container's main process (Dockerfile CMD ["start"], distroless image default).
When PID 1 is detected, the agent additionally:
Skips
agent.EnsureNotRunningandagent.WritePIDso there is no PID-file collision with itself across re-execs.Installs the PID-1 init shim (build tag
pid1) that reaps zombie children — required for any container that may spawn subprocesses, even transiently.Re-execs itself with
LINUXGUARD_PID1_CHILD=1set; this sentinel marks the second invocation as the actual agent process, not the init shim.
LINUXGUARD_PID1_CHILD is internal-only. Operators must NOT set it manually. Documented in Environment variables only so process-introspection tooling (e.g., reading /proc/<pid>/environ during incident triage) can identify the value as agent-internal rather than user-supplied.
Workload identity derivation
The workload identifier is the value the backend uses to distinguish one ephemeral agent from another. It is also used as the Idempotency-Key header on the enrolment POST so a retried request does not produce two server identities.
The derivation order is:
Explicit
--workload-id <hex>→sha256(explicit). The flag value is hashed (not used verbatim) so misuse — passing a non-hex value, passing whitespace — produces a deterministic identifier rather than a backend rejection.Downward API env vars →
sha256(LINUXGUARD_NODE_NAME + ":" + LINUXGUARD_POD_UID). Both env vars must be set; either one missing falls through to error.Neither set → hard error:
--ephemeral requires either Downward API env vars (LINUXGUARD_NODE_NAME and LINUXGUARD_POD_UID, set via valueFrom.fieldRef) OR --workload-id CLI flag; none of the three were present.
There is no silent UUID fallback. An ephemeral agent that cannot derive a workload identity refuses to start, by design — otherwise a misconfigured Pod would silently enrol with a random identity on every restart and produce a sprawl of orphan enrollments in the tenant.
For the Kubernetes pattern using valueFrom.fieldRef, see Downward API integration.
TLS cache restart semantics
By default, an ephemeral agent that restarts performs a fresh enrolment with the supplied TOTP token. This is the safest default: no cert material survives container exit; a stolen image filesystem yields no live mTLS keys.
For deployments where restart is frequent and re-enrolment is undesirable (e.g., a sidecar that restarts on application crashes), the optional --tls-cache flag mirrors the cert chain + a token-hash tag to a tmpfs at /run/linuxguard/tls/:
/run/linuxguard/tls/agent.crt
0600
mTLS client certificate
/run/linuxguard/tls/agent.key
0600
mTLS client private key
/run/linuxguard/tls/ca.crt
0600
Backend CA chain
/run/linuxguard/tls/.tag
0600
hex(sha256(token + ":" + workloadID)) — token-hash tag used to invalidate stale caches across token rotations
On restart with --tls-cache, the agent computes the current .tag value from the env-var token + workload-id and compares it against the file. If they match, the cached cert chain is reused without re-enrolling. If they diverge — because the TOTP token has been rotated, or because the workload-id changed (a new pod UID under Kubernetes) — the cache directory is deleted and a fresh enrolment runs.
Important:
--tls-cacherequiresLINUXGUARD_ENROLL_TOKEN(or a pre-computedEnrollTokenTagvalue) to be set. The agent refuses to seed a cache that cannot be cryptographically invalidated — otherwise a token rotation would silently leave the agent using cert material attached to the prior identity. Without the token + tag pair, the agent returns the error--tls-cache requires LINUXGUARD_ENROLL_TOKEN (or pre-computed EnrollTokenTag) to be set; refusing to seed a cache that cannot be cryptographically invalidated.
The tmpfs mount is mandatory when --tls-cache is active. Without it, the cert chain ends up on the container's writable layer — discoverable via docker diff, persisted in image-export workflows, and survivable to disk. The Docker run incantation is:
The Kubernetes equivalent (in the Pod spec) is an emptyDir with medium: Memory:
Restart semantics summary
Scenario
Without --tls-cache
With --tls-cache
Container restart, same TOTP token, same workload-id
Fresh enrol with the token
Cert chain reused from tmpfs; no enrol call
Container restart, rotated TOTP token, same workload-id
Fresh enrol with the new token
.tag mismatch → cache deleted → fresh enrol with the new token
Container restart, same TOTP token, new workload-id (e.g., new pod UID)
Fresh enrol under the new identity
.tag mismatch → cache deleted → fresh enrol under the new identity
Container exit (SIGTERM / SIGINT)
Cert chain is GC'd from memory; exits with os.Exit(143) / os.Exit(130) respectively
Cert chain is GC'd from memory; the tmpfs cache survives until the next start (tmpfs is the orchestrator's lifecycle, not the container's)
Security context
Ephemeral mode runs the agent under the same security context as any other container deployment of the distroless image — see Distroless image § Security context for the canonical reference. Specifically:
Runs as
nonrootUID 65532.Uses Linux file capabilities (
CAP_BPF,CAP_PERFMON,CAP_DAC_READ_SEARCH,CAP_SYS_PTRACE,CAP_SETPCAP) baked into the binary.Requires the runtime to add the same capabilities to the bounding set (
--cap-addorsecurityContext.capabilities.add).Requires a custom seccomp profile (or
--security-opt seccomp=unconfinedfor UAT/dev) soperf_event_open(2)is permitted.Sets
runAsNonRoot: true,allowPrivilegeEscalation: false,readOnlyRootFilesystem: trueat the Pod level.
Host paths
Ephemeral mode requires fewer host paths than the DaemonSet shape because it does not need to observe other workloads on the node:
/run/linuxguard
tmpfs, mode 0700, size 10m, read-write
TLS cert cache when --tls-cache is set. Mandatory when the flag is active; optional otherwise.
/sys/kernel/tracing
hostPath, read-only
Required for probe attach. Omit when running on a kernel without eBPF or in DegradedNoEBPFArch mode.
/sys/fs/bpf
hostPath, read-write
Required when the loader pins maps.
/proc
hostPath, read-only
Required when ephemeral mode is observing other host processes (rare; typical ephemeral is per-pod or per-container scope only).
The DaemonSet shape, by contrast, mounts host PID + the full host-path set. See Kubernetes DaemonSet § Host paths.
Pod Security Standard compatibility
privileged
Yes
Default profile that admits all capabilities and host namespaces required by the agent.
baseline
Yes — with caveat
The agent's CAP_BPF + CAP_PERFMON are within the baseline allowlist; tmpfs mount and runAsNonRoot satisfy baseline constraints. Caveat: ephemeral mode without hostPID works under baseline; ephemeral mode with hostPID: true requires privileged.
restricted
Not currently supported
The agent's required CAP_BPF and CAP_PERFMON are NOT in the restricted allowlist (which drops all capabilities by default). Requires an explicit AdmissionPolicy waiver. Consult support.
RBAC
Ephemeral mode makes no Kubernetes API calls. Workload identity comes from Downward API env vars injected at Pod admission time (no apiserver lookups), and telemetry ships via outbound mTLS to the LinuxGuard API (no in-cluster service mesh).
The Pod runs under any ServiceAccount (the namespace default SA is acceptable). No Role, ClusterRole, RoleBinding, or ClusterRoleBinding needs to be created for the agent itself. RBAC is required only for sibling components (e.g., the profile-installer DaemonSet that writes seccomp/AppArmor profiles to host paths — that DaemonSet's RBAC is documented in Kubernetes DaemonSet § RBAC).
Example: Docker run, ephemeral, no cache
The simplest ephemeral invocation. Cert chain lives in memory only; a restart re-enrols with whatever value is then in LINUXGUARD_ENROLL_TOKEN.
Notes on the flags:
--cap-addadds the five required caps to the container's bounding set so the file-cap transition atexecvesucceeds.--security-opt seccomp=unconfinedis acceptable for UAT/dev; production should use a custom seccomp profile that explicitly permitsperf_event_open(2).-v /sys/kernel/tracing:/sys/kernel/tracing:rois the tracefs bind-mount required for probe attach.The four env vars supply the token, the tenant, and the workload-id inputs.
LINUXGUARD_ENROLL_TOKENis read once and immediately unset; the other three persist for the lifetime of the agent process.
Example: Docker run, ephemeral, with TLS cache
The same agent with --tls-cache enabled so a container restart reuses the cert chain (within the same TOTP token + workload-id):
The --restart unless-stopped policy is appropriate when --tls-cache is in use because restart no longer triggers re-enrolment (within the same token + workload-id window).
Example: Kubernetes DaemonSet env block (abbreviated)
The full DaemonSet manifest (with securityContext, host-path volumes, PSS comment, and RBAC) lives in Kubernetes DaemonSet. The ephemeral-mode env block within that manifest is:
The TOTP token is sourced from a Kubernetes Secret (not a literal value) per the enrollment-tokens guide. The node name and pod UID come from the Downward API per Downward API integration.
Next Step: Kubernetes DaemonSet →
Related: Container deployment hub | Distroless image reference | Downward API integration | Enrollment tokens | start CLI reference | Environment variables
Last updated
Was this helpful?