Linux Agent Guide
Install Options
One-line installer (recommended)
From the dashboard, open Agent Setup and switch the OS toggle to Linux. Pick an agent token (the dropdown only offers active tokens with public download enabled and a target OS of Linux or Either) and your subdomain — the page renders the exact command to copy:
curl -fsSL https://etducky.com/install.sh \
| sudo bash -s -- --token=<TOKEN_ID> --subdomain=<SUBDOMAIN>
The installer enrolls the host, writes /etc/etducky/agent/AgentConfig.json (owner etducky, mode 0600), and enables + starts the service. It is idempotent: re-running on the same host re-uses the existing agent record (keyed on /etc/machine-id), rotates the agent's bearer token, and restarts the service cleanly. Add --enable-smart or --disable-smart to answer the SMART disk-monitoring prompt non-interactively (opting in installs smartmontools if missing).
Package downloads
The Agent Setup Linux tab also links the raw packages (or fetch them from Downloads):
- .deb — Debian / Ubuntu:
sudo apt install ./etducky-agent_<version>_amd64.deb - .rpm — RHEL / Fedora / Rocky:
sudo dnf install ./etducky-agent-<version>-1.x86_64.rpm - .run — distro-agnostic self-extracting installer for hosts without dpkg/rpm:
sudo bash ./etducky-agent-<version>.run
A SHA256SUMS file is published alongside the packages for verification. Package installs still need enrollment — use the one-liner on fresh hosts, or run the packaged install script with a token afterwards.
The systemd Service
The agent runs as the etducky-agent systemd unit under the unprivileged etducky user — not root. Capabilities are scoped to exactly what eBPF and diagnostics need (CAP_BPF, CAP_PERFMON, CAP_NET_ADMIN, CAP_SYS_PTRACE, CAP_DAC_READ_SEARCH), with filesystem hardening (ProtectSystem=strict, read-only /home, private /tmp) and resource caps (512 MB memory, 50% of one CPU).
sudo systemctl status etducky-agent
sudo journalctl -u etducky-agent -n 50 --no-pager
Paths
/opt/etducky/agent— binary and eBPF objects (read-only)/etc/etducky/agent/AgentConfig.json— configuration (mode 0600; the agent refuses to start if permissions are weaker)/var/lib/etducky— local state/var/log/etducky— log files (stdout/stderr also go to the journal)
Online/offline status is tracked from heartbeat freshness in the cloud, not by systemd. Restart=on-failure handles real crashes.
The Sudoers Policy (/etc/sudoers.d/etducky-rmm)
Packages ship a deliberately narrow sudoers drop-in. It grants the etducky user passwordless sudo for only five categories:
- Read-only diagnostics —
smartctl,dmidecode,lshw,lspci,lsusb,journalctl,dmesg. Root-required to read, but cannot mutate anything; used by heartbeat collectors and AI introspection. - Self-management —
systemctl restart etducky-agentonly (the agent's own restart after an in-place upgrade). Argument-restricted to theetducky-agentunit and the restart verb. - Package operations via the
etducky-pmhelper unit — all privileged package work (third-party app install/remove/upgrade and the agent's own self-update) routes through a constrained systemd template unit rather than a directsudo apt/dnf. The only package grant in the sudoers file is starting that unit:systemctl start --wait etducky-pm@<encoded-op>.service. The agent picks the opaque instance id, but the actual operation is read from a request file and validated by the helper script against a fixed allowlist — only anapt/dnf/zypper/snap/flatpakpaired withinstall/remove/upgradeof a syntactically-valid package name, run as fixed argv, is ever executed. So this constrained package install/remove/upgrade is passwordless by design, but the agent can never turn the grant into an arbitrary root command. Delete this rule to hard-disable all Linux package operations (patch, app-deploy, and self-update) and update out of band. See Package operations & the etducky-pm helper below. - Network isolation — applying/removing the dedicated
etducky_isolationnftables table (iptables fallback on hosts without nft) so a high-confidence ransomware detection can quarantine the host without waiting for an operator. - On-device approval prompt — launching
zenity/kdialog/xmessageas the logged-in console user, never as root, for the unisolate approval flow below.
Everything else requires operator-driven elevation. Direct sudo apt/dnf/zypper, firewall changes, user management, mounting, arbitrary systemctl — none of it is passwordless. Privileged package management is the one write category that is passwordless, and only through the allowlisted helper unit described above — never via a direct package-manager invocation.
Package operations & the etducky-pm helper
Every privileged package operation on Linux — deploying a third-party app, patching it, removing it, and the agent's own self-update — runs through the same constrained path, not a direct sudo apt/dnf.
Why the indirection. The etducky-agent service runs ProtectSystem=strict, so a package manager the agent spawns (even under sudo) inherits that read-only mount namespace and fails to write /usr or the package database. Instead, the agent writes a small request file (manager/op/package) to /var/lib/etducky/pm/<id>.req and asks systemd to start a separate, unsandboxed oneshot unit:
sudo -n systemctl start --wait etducky-pm@<id>.service
That unit (PID 1–launched, so it gets a fresh mount namespace where the package manager can work) runs the helper script /opt/etducky/agent/scripts/etducky-pm-op.sh. The helper validates the request against a fixed allowlist before it runs anything:
- Manager must be one of
apt,dnf,zypper,snap,flatpak. - Operation must be one of
install,remove,upgrade. - Package name must match a strict pattern (no spaces, no shell metacharacters, no leading dash), and is passed as a single argv element — never through a shell.
Each (manager, operation) pair maps to a fixed command (for example apt:upgrade → apt-get install --only-upgrade -y <pkg>). The unit blocks with --wait and the helper writes the package manager's exit code and combined output back for the agent to read. Because the operation is read from the request file and allowlist-validated — not taken from the sudoers command line — the agent's single privileged capability (starting one unit) can never become an arbitrary root command.
The helper is dormant until both the agent's PatchExecuteEnabled config and the server's Patch Management execute flag are on; otherwise the agent simply never starts the unit.
Operator-Driven Elevation
When a live-session command needs root (any sudo-prefixed command outside the allowlist above), the agent does not run it directly. Instead:
- The agent posts an elevation request to the cloud; the dashboard pops a password modal showing the command summary.
- The operator (must be an org admin) types a sudo password for the host. It travels exactly two encrypted hops — browser to backend, backend to agent — and is never persisted or logged.
- The agent feeds the password to
sudo -Svia stdin (never argv), runs the command, zeroes the password buffer, and reports the result. - Every request is audited: who approved, what ran, from where, and the outcome (pending → granted → executed, or denied/expired/failed). Grants expire after 5 minutes.
The trust model: compromising the agent alone no longer equals root — an attacker would also need a real operator to authenticate a future elevation.
Unisolate approval
Lifting network isolation is a dual-party action: in addition to the dashboard operator, a GUI confirmation prompt is shown to the logged-in console user on the host (via zenity/kdialog/xmessage). On headless hosts with no graphical session, the on-device prompt cannot be shown and the lift is rejected through that path.
eBPF Capture vs. Windows ETW
Kernel telemetry on Linux comes from eBPF tracepoint programs (libbpf + CO-RE), loaded when KernelEventsEnabled is true in AgentConfig.json (the default). Three provider buckets can be toggled via KernelProviders:
- Process — exec and exit tracepoints
- File — open and close syscalls
- Network — connect and accept (IPv4 + IPv6)
Events are normalized to the same shape as Windows ETW events, so live-session AI analysis, inflection-bracketed correlation, and behavioral detections work identically on both platforms.
Kernel requirements
- Kernel 5.8+ for
CAP_BPF(older kernels fall back to broader capabilities). - Built-in BTF (
/sys/kernel/btf/vmlinux) — standard on Ubuntu 22.04+ and Fedora 36+. For RHEL 8 / Ubuntu 18.04 / Amazon Linux 2, drop a matching<uname -r>.btffile into/opt/etducky/agent/bpf/btfhub/. - If the eBPF library is absent or capture is disabled, the agent runs in a no-op capture mode: heartbeats, health metrics, live sessions, and remote desktop all keep working — only kernel events are off.
Kill switch: set "KernelEventsEnabled": false in /etc/etducky/agent/AgentConfig.json to disable kernel capture without uninstalling.
Deploying third-party apps
You can deploy third-party applications to Linux agents through the host's OS package manager. On a Software Catalog entry, set the Linux package id field (the package name the target distro's manager knows, e.g. htop) — that gives the entry the linux_pm deploy method. When you deploy, each Linux agent installs the package through the same allowlisted etducky-pm helper unit described above (apt/dnf/zypper/snap/flatpak install), so no direct root shell is involved.
See Patch Management for the full deploy workflow (choosing a method, scheduling, and reading back per-agent job results).
Agent auto-update
The Linux agent can keep itself current by upgrading its own package through the OS package manager — routed through the same etducky-pm helper unit, so it works under the sandboxed service.
It periodically fetches the published version manifest (version.json) and compares the advertised Linux version against the running one. Self-update is gated on the agentLinux.autoUpdate flag in that manifest: when it's off, the agent never self-upgrades and you update out of band. When it's on and a newer version is published, the agent requests an upgrade of the etducky-agent package via the helper; the package's post-install step restarts the service.
Auto-update needs the host to be subscribed to the ET Ducky package repository (the one-line installer sets this up) and the etducky-pm sudoers grant present. Without the repo the upgrade finds no candidate; without the grant the attempt fails fast with a clear log line.
File transfers & POSIX paths
File transfers to Linux agents accept POSIX absolute paths — a single leading forward slash, e.g. /etc/etducky/… or /opt/… — so pushes and pulls aren't rejected as “not rooted” the way a Windows drive path would be validated. The same anti-traversal guards apply on both platforms: ./.. segments, empty interior segments, and control characters are rejected, and the agent re-checks the resolved path at open time.
Known Platform Differences
The Linux agent is at operational parity with Windows for enrollment, heartbeats, health and hardware metrics, live sessions, remote desktop, inventory, alerts, and behavioral rules. Remaining differences:
| Area | Windows | Linux |
|---|---|---|
| Kernel telemetry breadth | 30+ configurable ETW providers (registry, DNS, .NET, firewall, …) | 3 eBPF buckets: Process, File, Network |
| Remote desktop capture | DXGI Desktop Duplication | x11vnc (Xorg) or desktop portal / PipeWire (Wayland), with an H.264 GStreamer helper |
| Privileged commands | Agent runs as LocalSystem; commands execute directly | Operator-driven sudo elevation with per-command audit |
| SMART disk health | On by default (WMI) | Opt-in at install (--enable-smart); requires smartmontools |
| Distro / kernel / init reporting | Full OS version reporting | Partial — basic OS info reported; richer distro detail still in progress |
| H.264 remote desktop prerequisites | Media Foundation (built in) | Needs gstreamer1.0-vaapi (hardware) or gstreamer1.0-plugins-ugly (x264 software); falls back to JPEG without them |
Troubleshooting
- Service won't start; journal says "config has weak permissions" —
AgentConfig.jsonmust be 0600. Re-run the one-liner; it sets permissions atomically. - Crash loop on start — check
journalctl -u etducky-agent -n 200. Common causes: kernel older than 5.8 with eBPF enabled, or missinglibssl3. - 403 from the one-liner — the token isn't public-download enabled, or its target OS is Windows-only. Fix it on the Agent Setup page.
- Agent online but no kernel events — the host is likely in no-op capture mode (no BTF, old kernel, or
KernelEventsEnabledfalse). See the eBPF section above.