Installation alternatives

Install without curl-pipe-bash

The default curl … | bash install is convenient, but if you'd rather inspect what runs first, verify the binary, or roll the agent out via configuration management, this page is for you.

Inspect the install script before running it

The install script is plain Bash. Read it before piping to your shell:

curl -fsSL https://astrari.io/install.sh -o install.sh
less install.sh                   # read it
bash install.sh https://api.astrari.io YOUR_AGENT_TOKEN

Or audit it on every host by hosting it yourself: drop a copy into your config-management repo and run that copy in your provisioning pipeline.

Verify the agent binary by checksum

Every release publishes a SHA-256 sum alongside each binary. Download the binary, download the sum, and verify before executing:

amd64

curl -fsSL -o astrari-agent \
  https://astrari.io/agent/download/linux-amd64
curl -fsSL -o astrari-agent.sha256 \
  https://astrari.io/downloads/astrari-agent-linux-amd64.sha256

# Compare — should print "astrari-agent: OK"
sed 's| .*| astrari-agent|' astrari-agent.sha256 | sha256sum -c -

arm64

curl -fsSL -o astrari-agent \
  https://astrari.io/agent/download/linux-arm64
curl -fsSL -o astrari-agent.sha256 \
  https://astrari.io/downloads/astrari-agent-linux-arm64.sha256

sed 's| .*| astrari-agent|' astrari-agent.sha256 | sha256sum -c -

Beyond download verification, the agent itself verifies every self-update against an Ed25519 signature served from our API. A binary that doesn't verify will be rejected — even if our CDN is compromised. See the Security page for the full chain.

Manual install (no script)

If you'd rather skip the install script entirely, you can place the binary, write a config, install the systemd units, and start the timer by hand. The agent itself does no installation work — it just runs scans.

1. Place the binary

# After verifying the checksum (see above)
sudo install -m 0755 astrari-agent /usr/local/bin/astrari-agent

2. Write the config

sudo install -d -m 0700 /etc/astrari
sudo tee /etc/astrari/agent.conf > /dev/null <<'EOF'
API_URL=https://api.astrari.io
AGENT_TOKEN=YOUR_AGENT_TOKEN
EOF
sudo chmod 0600 /etc/astrari/agent.conf

3. Install the systemd service

sudo tee /etc/systemd/system/astrari-agent.service > /dev/null <<'EOF'
[Unit]
Description=Astrari security agent
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
EnvironmentFile=/etc/astrari/agent.conf
ExecStart=/usr/local/bin/astrari-agent
Nice=19
IOSchedulingClass=idle

[Install]
WantedBy=multi-user.target
EOF

4. Install the systemd timer (every 30 sec, 20 sec jitter)

sudo tee /etc/systemd/system/astrari-agent.timer > /dev/null <<'EOF'
[Unit]
Description=Run astrari-agent every 30 seconds

[Timer]
OnBootSec=30
OnUnitActiveSec=30
RandomizedDelaySec=20
AccuracySec=1s
Unit=astrari-agent.service

[Install]
WantedBy=timers.target
EOF

5. Enable and start

sudo systemctl daemon-reload
sudo systemctl enable --now astrari-agent.timer
sudo systemctl status astrari-agent.timer
journalctl -u astrari-agent -f

Optional: install the OS scanners (Trivy, ClamAV, rkhunter, MalDet) via your usual package manager. The agent will report findings from whatever scanners it can find. Without them you'll still get configuration, SSH, firewall, file-integrity, and OS-update findings.

Ansible role — minimal example

Drop this into roles/astrari_agent/tasks/main.yml and pass astrari_token as a per-host variable from your inventory or vault.

roles/astrari_agent/tasks/main.yml

---
- name: Resolve architecture
  ansible.builtin.set_fact:
    astrari_arch: "{{ 'arm64' if ansible_architecture in ['aarch64','arm64'] else 'amd64' }}"

- name: Download Astrari agent binary
  ansible.builtin.get_url:
    url: "https://astrari.io/agent/download/linux-{{ astrari_arch }}"
    dest: /usr/local/bin/astrari-agent
    mode: "0755"
    # Pin the exact sha256 you've reviewed — bump on each release.
    # Get it from https://astrari.io/downloads/astrari-agent-linux-{{ astrari_arch }}.sha256
    checksum: "sha256:{{ astrari_agent_sha256 }}"

- name: Create agent config dir
  ansible.builtin.file:
    path: /etc/astrari
    state: directory
    mode: "0700"

- name: Write agent config
  ansible.builtin.copy:
    dest: /etc/astrari/agent.conf
    mode: "0600"
    content: |
      API_URL=https://api.astrari.io
      AGENT_TOKEN={{ astrari_token }}

- name: Install systemd unit
  ansible.builtin.copy:
    dest: /etc/systemd/system/astrari-agent.service
    content: |
      [Unit]
      Description=Astrari security agent
      After=network-online.target
      Wants=network-online.target
      [Service]
      Type=oneshot
      EnvironmentFile=/etc/astrari/agent.conf
      ExecStart=/usr/local/bin/astrari-agent
      Nice=19
      IOSchedulingClass=idle
      [Install]
      WantedBy=multi-user.target
  notify: reload systemd

- name: Install systemd timer
  ansible.builtin.copy:
    dest: /etc/systemd/system/astrari-agent.timer
    content: |
      [Unit]
      Description=Run astrari-agent every 30 seconds
      [Timer]
      OnBootSec=30
      OnUnitActiveSec=30
      RandomizedDelaySec=20
      Unit=astrari-agent.service
      [Install]
      WantedBy=timers.target
  notify: reload systemd

- name: Enable and start the timer
  ansible.builtin.systemd:
    name: astrari-agent.timer
    enabled: true
    state: started
    daemon_reload: true

Per-host inventory needs only astrari_token and astrari_agent_sha256 (per-arch). Pin the sha256 in source control so a tampered binary fails the run with a loud checksum mismatch.

Outbound network requirements

The agent only ever speaks outbound, over HTTPS:

  • api.astrari.io:443 — heartbeat, results upload, config fetch
  • astrari.io:443 — agent self-updates

No inbound ports need to be opened on the server. If your egress is restricted, allow-list the two hostnames above.