Install on Linux with a Script
A repeatable script install for the Linux forwarder: check auditd, install the package, write the config, start the service. Plus the Ansible equivalent.
The Linux forwarder installs from a distribution package and reads its configuration from a file, which makes it straightforward to script. The whole install is four steps: confirm auditd is enabled, install the package, write the configuration with your environment ID and token, and start the service. This page gives you those four steps as commands you can wrap in whatever tooling you already use.
If you manage Debian hosts with apt, see Install on Linux with apt instead.
What do I need before I start?
- Your environment ID and a forwarder authentication token for it. See Environments.
- The package for your distribution. Get the current one from Forwarder Downloads. There is an RPM per RHEL family release and one Debian package.
auditdinstalled and enabled. The forwarder needs it to observe file events. This is a hard requirement, not a recommendation.- Root or
sudoon the target host. - A clean connectivity result from that network. See Pre-Deployment Check.
Note that eBPF is not supported in the Linux forwarder today.
Which host should I install on first?
Not a critical one. The initial backscan walks the disk and is resource-intensive while it runs, and the first hosts you install on upload the most because none of their content is known to Stairwell yet. Subsequent hosts built from the same image find far less. Forwarder Deployment has the full order and the reason it matters.
Step 1: confirm auditd is enabled
sudo systemctl status auditd
sudo systemctl enable --now auditdOn hosts old enough to predate systemd, use the service and chkconfig equivalents. If auditd is not running, the forwarder installs and starts and does not see file events, so make this a hard gate in your script rather than a best-effort step.
Step 2: install the package
Substitute the version and the distribution suffix for what you downloaded.
RHEL family, using the release that matches the host:
curl -LO https://downloads.stairwell.com/linux/2.5.1/stairwell-2.5.1-1.el9.amd64.rpm
sudo rpm -U stairwell-2.5.1-1.el9.amd64.rpmDebian and Ubuntu:
curl -LO https://downloads.stairwell.com/linux/2.5.1/stairwell-2.5.1-1.amd64.deb
sudo apt install -y ./stairwell-2.5.1-1.amd64.debrpm -U and apt install both handle a fresh install and an upgrade over an existing one, which is what you want in a script that may run on either.
Step 3: write the configuration
The forwarder reads /etc/stairwell/config.json. Write it before the first service start, so the forwarder registers on its first attempt rather than failing and retrying.
sudo tee /etc/stairwell/config.json > /dev/null <<EOF
{
"logger": { "loglevel": "error" },
"asset": {
"EnvId": "$ENV_ID",
"Token": "$TOKEN"
},
"interpreters": ["sh","bash","python3","go","ruby","perl","lua","Rscript"],
"ostype": "server",
"enableEvents": true
}
EOF| Key | What it does |
|---|---|
asset.EnvId | The environment the host registers into |
asset.Token | The forwarder authentication token |
interpreters | Interpreter names to watch, so a script run through one of them is collected as an execution |
ostype | server or workstation, which sets the appropriate defaults for the machine's role |
enableEvents | Whether real-time file event collection is on |
logger.loglevel | Forwarder log verbosity |
proxyURL | Optional. Route forwarder traffic through a proxy, as https://host:port |
This file is preserved across package upgrades, so a script that writes it unconditionally will overwrite local changes. If you have per-host configuration, template the file rather than clobbering it.
Treat the token as a secret. It goes to every host in the fleet, so it belongs in your secrets manager and not in the script.
Step 4: start the service
sudo systemctl enable --now stairwell.serviceHow do I confirm it worked?
On the host:
systemctl status stairwell.service
journalctl -u stairwell.service -fThen in Stairwell:
- Open Assets and find the host. Confirm a recent check-in. See Assets.
- Open the asset and confirm objects are arriving. Give it a few minutes.
- Confirm the environment and the policy are the ones you intended.
A service that is active while nothing arrives in Stairwell points at one of two things: auditd is not running, or the network is not permitting intake. Check auditd first because it is local, then run swell verify connectivity from the host. See Connectivity Requirements.
The whole thing as one script
#!/bin/bash
set -euo pipefail
VERSION="2.5.1"
ENV_ID="${STAIRWELL_ENV_ID:?environment ID required}"
TOKEN="${STAIRWELL_TOKEN:?token required}"
systemctl enable --now auditd
if [ -f /etc/debian_version ]; then
curl -fsSLO "https://downloads.stairwell.com/linux/$VERSION/stairwell-$VERSION-1.amd64.deb"
apt install -y "./stairwell-$VERSION-1.amd64.deb"
else
curl -fsSLO "https://downloads.stairwell.com/linux/$VERSION/stairwell-$VERSION-1.el9.amd64.rpm"
rpm -U "stairwell-$VERSION-1.el9.amd64.rpm"
fi
tee /etc/stairwell/config.json > /dev/null <<EOF
{
"logger": { "loglevel": "error" },
"asset": {
"EnvId": "$ENV_ID",
"Token": "$TOKEN"
},
"interpreters": ["sh","bash","python3","go","ruby","perl","lua","Rscript"],
"ostype": "server",
"enableEvents": true
}
EOF
systemctl enable --now stairwell.serviceThe RHEL branch pins el9. If your fleet spans several RHEL family releases, select the suffix from the host rather than hard-coding it.
How do I do this with a configuration management tool?
The same four steps. Here they are as an Ansible play, which is the shape most fleets end up with:
- name: Install the Stairwell forwarder
hosts: linux_hosts
become: true
vars:
stairwell_version: "2.5.1"
tasks:
- name: Ensure auditd is running
systemd:
name: auditd
enabled: true
state: started
- name: Download the RPM
get_url:
url: "https://downloads.stairwell.com/linux/{{ stairwell_version }}/stairwell-{{ stairwell_version }}-1.el9.amd64.rpm"
dest: /tmp/stairwell.rpm
when: ansible_os_family == "RedHat"
- name: Install the RPM
yum:
name: /tmp/stairwell.rpm
state: present
when: ansible_os_family == "RedHat"
- name: Download the DEB
get_url:
url: "https://downloads.stairwell.com/linux/{{ stairwell_version }}/stairwell-{{ stairwell_version }}-1.amd64.deb"
dest: /tmp/stairwell.deb
when: ansible_os_family == "Debian"
- name: Install the DEB
apt:
deb: /tmp/stairwell.deb
state: present
when: ansible_os_family == "Debian"
- name: Write the forwarder configuration
template:
src: config.json.j2
dest: /etc/stairwell/config.json
mode: "0600"
- name: Enable and start the forwarder
systemd:
name: stairwell.service
enabled: true
state: startedFour practices that pay off across a fleet of any size:
- Pin the version. An unpinned install means two hosts provisioned a week apart are running different forwarders, which makes any behavior difference hard to attribute.
- Stagger the rollout. The initial backscans are the load, so start with a slice of hosts rather than all of them.
- Keep tokens in a secrets manager, not in the playbook.
- Mirror the packages internally if your hosts should not reach the internet directly. The RPM and DEB are ordinary packages and work from your own repository.
How do upgrades work?
Not from the Stairwell console. Windows and macOS forwarders can be upgraded over the air from the console; Linux forwarders cannot, and must be upgraded through your package manager or your orchestration tooling.
In practice that means re-running the install step with a newer version. rpm -U and apt install both upgrade in place, /etc/stairwell/config.json is preserved, and the service restarts. Verify with rpm -q stairwell or dpkg -s stairwell on the host, and by the version reported on the asset in Stairwell.
What should I read next?
- Install on Linux with apt, for the apt-native path on Debian hosts.
- Forwarder Downloads, for the current package per distribution and what has been tested.
- Asset Configuration, for the policy settings that control collection and resource use.
Updated 12 days ago