Linux server
Install shellz on a systemd Linux server, what the installer changes, and supported distributions.
One command installs shellz on a Linux server and starts recording every login on it. This page covers requirements, what changes on the server, and distribution-specific notes.
Requirements
- Linux with systemd, on amd64 (x86_64) or arm64 (aarch64).
- Root access through
sudo. curland OpenSSL 3, used by the installer to download and verify the release.- If the server runs OpenSSH, its
sshd_configmust include/etc/ssh/sshd_config.d/*.conf. Current versions of every supported distribution do. - Outbound HTTPS (port 443) to
api.shellz.dev,ingest.shellz.devandreleases.shellz.dev.
Supported distributions
| Distribution | Status |
|---|---|
| Ubuntu 24.04 | Tested |
| Debian 13 | Tested |
| Rocky Linux 9, AlmaLinux 9 | Tested, including with SELinux enforcing |
| Fedora 44 | Tested |
| Arch Linux | Tested |
| Ubuntu 22.04, Debian 12, RHEL 9, Amazon Linux 2023 | Expected to work (same packages and OpenSSL 3) |
| Amazon Linux 2, RHEL, Rocky and Alma 8, anything with OpenSSL 1.x | Not supported. The installer refuses and says why. |
LXC containers, systemd-nspawn machines and Proxmox guests count as servers, because they boot their own systemd. To record inside application containers (Docker, Kubernetes and so on), see Choose an install method.
Install
In the dashboard, open ~/servers and click Add server. Copy the command and run it on the server:
curl -fsSL https://get.shellz.dev | sudo sh -s -- szt_<join token>Each join token works once and expires after 10 minutes. It also carries the fingerprint of your org's public key, so the server only trusts keys from your org.
The server appears in ~/servers under its hostname, without the domain part. If that name is taken, shellz adds a number (web-2).
The installer refuses to run, without changing anything, if:
- it isn't running as root, on systemd, on amd64 or arm64;
curlor OpenSSL 3 is missing (it names the package to install for your package manager);- it's running inside an application container;
- sshd doesn't read
/etc/ssh/sshd_config.d(it tells you theIncludeline to add); - the server is already enrolled.
If the release signature or checksum doesn't match, it stops before installing anything.
What the installer changes
| What | Where |
|---|---|
| The shellz binary | /usr/local/bin/shellz |
| The session shell | /usr/local/libexec/shellz-shell, also added to /etc/shells |
| The recorder service | /etc/systemd/system/shellz-recorder.service, enabled at boot |
| Configuration (no secrets) | /etc/shellz |
| State: server key, pinned org keys, policy, spool | /var/lib/shellz (root only) |
| Recorder socket | /run/shellz/broker.sock |
| SSH setting | /etc/ssh/sshd_config.d/00-shellz.conf, containing PermitUserRC no |
| Login shells | root and regular accounts (UID from UID_MIN up to 59999) are switched to the session shell. Original shells are saved and restored on removal. |
On SELinux systems, shellz also installs a one-rule policy module so recorded sessions keep the login's own SELinux context. SELinux is never set to permissive.
Nothing else on the server changes. shellz doesn't install packages, open ports, or modify PAM.
Why PermitUserRC no
OpenSSH runs ~/.ssh/rc for each login before the shell starts, which would let a user run commands outside the recording. shellz turns it off.
Service accounts
Accounts below UID_MIN (usually 1000) other than root, and accounts whose shell is nologin or false, keep their shells. If any of them does start a login session, the session auditor notices and, depending on the recording policy, ends it and raises an alert.
Check that it's working
sudo /usr/local/bin/shellz statusRecorder running and Sessions N active mean the server is recording. Then SSH in from another terminal and watch the session appear in the dashboard. --json prints the same information as JSON for monitoring tools.
Distribution notes
Rocky, Alma, RHEL and Fedora
sudo's secure_path on these distributions doesn't include /usr/local/bin, so sudo shellz status reports "command not found". Use the full path, sudo /usr/local/bin/shellz status. Every hint shellz prints already does.
With SELinux enforcing, the installer needs semodule (package policycoreutils, installed by default). Logins mapped to confined SELinux users (user_u, staff_u, sysadm_u, guest_u, xguest_u) aren't supported: they can't reach the recorder, so their logins are refused, or let through unrecorded under fail-open.
Arch Linux
Check that /etc/ssh/sshd_config contains Include /etc/ssh/sshd_config.d/*.conf. Current Arch packages ship it; older configurations may not.
Unprivileged LXC containers
shellz can't set the immutable flag (chattr +i) on its files in an unprivileged LXC container. It still installs and records, still repairs changes every 15 seconds, and raises one immutable-unsupported warning.
Docker on the same server
If Docker runs on the server, the same install records container sessions too. See Docker host.
Troubleshooting
"This server is already enrolled." shellz is already installed. Run sudo /usr/local/bin/shellz status. To move the server to another org, remove it first.
"This join token is no longer valid." Tokens work once and expire after 10 minutes. Click Add server for a new command.
"The join token checksum does not match." The token was cut off or mistyped while copying. Copy the whole command again.
"sshd does not read sshd_config.d." Add Include /etc/ssh/sshd_config.d/*.conf near the top of /etc/ssh/sshd_config, then run the install command again. Nothing was changed.
OpenSSL 1.x. Amazon Linux 2 and EL8 ship OpenSSL 1.1, which can't verify the Ed25519 release signature. Upgrade to a distribution with OpenSSL 3.