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.
  • auditd installed and enabled. The forwarder needs it to observe file events. This is a hard requirement, not a recommendation.
  • Root or sudo on 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 auditd

On 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.rpm

Debian 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.deb

rpm -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
KeyWhat it does
asset.EnvIdThe environment the host registers into
asset.TokenThe forwarder authentication token
interpretersInterpreter names to watch, so a script run through one of them is collected as an execution
ostypeserver or workstation, which sets the appropriate defaults for the machine's role
enableEventsWhether real-time file event collection is on
logger.loglevelForwarder log verbosity
proxyURLOptional. 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.service

How do I confirm it worked?

On the host:

systemctl status stairwell.service
journalctl -u stairwell.service -f

Then in Stairwell:

  1. Open Assets and find the host. Confirm a recent check-in. See Assets.
  2. Open the asset and confirm objects are arriving. Give it a few minutes.
  3. 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.service

The 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: started

Four 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?


Did this page help you?