sudo npm i -g signalbird-cli && sudo signalbird agent install --token=sba_live_…Server Agent - install and usage guide
This document covers the Signalbird agent you install on your server. The
agent is the agent role of the signalbird-cli npm package: it reads your
server's state and sends it to Signalbird. It changes nothing on your
server.
You can follow this even if you have never managed a server. Every step says what to type, what you should see, and what to do when something goes wrong. Five minutes, start to finish.
Source code: https://github.com/Pariette-Inc/signalbird.cli (MIT)
Running the old bash agent? The bash and PowerShell agent scripts are retired. Just run the install below on the same server: the new agent takes over and keeps your config file (token, allowed paths, database lines).
1. What is this for? (30 seconds)
You can tell whether your site is up by looking at it from the outside. What you cannot see from the outside:
- The disk is 97% full and will fill up tomorrow.
- Database connections have hit the ceiling; the next traffic spike stops the site.
- MySQL is down and the app is coasting on cache.
- Your nightly backup has not run for three days and nobody knows.
The agent sees these from inside the server and brings them to the panel. There is also the "expected signal": your backup script says "done" every hour, and if it does not, the alarm fires.
2. Glossary
| Term | Meaning |
|---|---|
| Agent | The program you install (signalbird agent). Runs in the background, always. |
| signalbird-cli | The npm package that carries the agent. Installing it gives you the signalbird command. |
| Node.js | The runtime the agent runs on. Version 20 or newer. |
| Terminal / SSH | The text window where you type commands on the server. |
| root / sudo | Administrator rights on the server. Needed to install. |
| Token | The long secret starting with sba_live_…. The agent's identity. |
| Metric | Numeric state: CPU, memory, disk and so on. |
| Radio | Signalbird's log module. Log lines the agent ships land there. |
| Expected signal | A "this job finished" ping. If it does not arrive, Signalbird raises an alarm. |
| Service (systemd) | A program that starts automatically with the server. The agent runs this way. |
3. Before you start
- A Linux server running systemd: Ubuntu, Debian, Rocky, AlmaLinux… (Windows Server is not supported yet, see §5.)
- A way in. SSH.
- Administrator rights.
sudo(or root itself). - Node.js 20 or newer. How to check is below.
- The Server Monitoring module on your Signalbird account. Without it the Servers screen shows a lock and offers to add the module.
- Outbound internet. Port 443 outbound is enough. You never open an inbound port.
Check Node.js:
node --versionIf it prints v20.… or higher you are ready. If it says "command not found"
or the version is below 20, install the NodeSource package on Ubuntu/Debian.
Download the setup script first, read it, then run it:
curl -fsSL https://deb.nodesource.com/setup_20.x -o nodesource_setup.sh
less nodesource_setup.sh
sudo bash nodesource_setup.sh && sudo apt-get install -y nodejs(Press q to leave less.) On Rocky / AlmaLinux and similar, use the
distribution's own Node.js 20 package or the instructions at
https://nodejs.org.
4. Install - Ubuntu / Debian / Linux
Step 1 · Create the server record
- Open Servers in the panel menu.
- Click Add server.
- Give it a name you will recognise:
web-01,database,orders-api. - Enter the allowed log roots: the folders the agent may read. If unsure,
keep the default
/var/log(see "Optional" below). - Click Create.
You get the token (starting with sba_live_…), and the panel then opens
the server's install page (/servers/<id>/install) with the commands to
copy and a live "waiting for first message" panel that turns green the
moment the agent first checks in.
The token is shown once. Copy it before closing the dialog. If you lose it, open the server record and click Rotate key (the old one dies instantly).
Step 2 · Connect to the server
ssh user@your-serverStep 3 · Install the package and the agent
Paste the commands from the install page as they are:
sudo npm install -g signalbird-cli
signalbird --version
sudo signalbird agent install --token=sba_live_YOUR_TOKEN_HEREThe first line installs the package permanently, the second proves the
signalbird command is there (it prints a version number), the third
installs the agent.
Do not use
npx. Something likenpx signalbird-cli agent installruns the package from a temporary cache folder; when that folder is cleaned up, the service breaks. The agent detects this and refuses to install. Runsudo npm install -g signalbird-clifirst.
install does the following, in order:
- Checks the token with Signalbird first. If it is rejected, nothing is written and the install stops.
- Writes the config file
/etc/signalbird/agent.conf, readable by root only (0600). - Installs and starts the systemd service
signalbird-agent. - If the old bash agent is installed, replaces it; the existing
agent.confis kept and only the token and API address are updated.
You are done when you see:
✓ Signalbird anahtarı kabul etti.
Kurulum tamam.
Ayar dosyası : /etc/signalbird/agent.conf
Servis : systemctl status signalbird-agent
Günlük : /var/log/signalbird-agent.log · journalctl -u signalbird-agent
Sinyal örneği: signalbird agent signal db-backup ok "yedek bitti"(The agent's messages are in Turkish: "key accepted", "install complete", config file, service, log, signal example.)
Step 4 · Verify
sudo signalbird agent statusThe agent prints its config and service state, then tries to connect:
Signalbird ajanı 1.1.0 (signalbird-cli …, protokol 1)
API : https://live.signalbird.io/api
Anahtar : sba_live_xxxxxxx…
İzinli yol : /var/log
Veritabanı : yerel ayarda yok
Ayar sürümü: …
Servis : active
Bağlantı deneniyor...
Bağlantı tamam.The last line should read "Bağlantı tamam." (connection OK). Then check the service:
systemctl status signalbird-agentIt should be active (running). The "waiting for first message" panel on the
install page turns green; on Servers the machine shows as online and fills
with CPU, memory and disk within a minute.
Optional · widen the readable log roots
By default the agent may only read files under /var/log. If your
application logs elsewhere, say so at install time:
sudo signalbird agent install \
--token=sba_live_xxx \
--allow=/var/log,/srv/myapp/storage/logsThis list lives on the server. A path chosen in the panel that is not under it is never read - even a stolen Signalbird account cannot open a new file on your machine.
Only pass --api=https://…/api if you connect to your own Signalbird
installation or a test address; otherwise leave it out.
5. Windows Server
There is no agent for Windows Server yet. The old PowerShell script is retired and its replacement has not shipped. When Windows support arrives it will show up as an option on the Add server screen and this guide will be updated.
Until then you can still use expected signals for jobs on a Windows machine with a single HTTP call, no agent needed (see §11, "Without the agent").
6. What you see in the panel
Each server is a card: online state, CPU, memory, disk, last seen. Open it for the detail view:
| Section | Contents |
|---|---|
| Top tiles | CPU, memory, uptime, database health |
| Disks | Usage bar and inode ratio per disk |
| Services | The services you asked about, green or red |
| Socket.io | Connected clients, rooms, events per second |
| Processes | Top N processes by CPU |
| Metric settings | What gets measured |
| Watched logs | Which file flows into Radio |
| Expected signals | Schedule and state of jobs like backups |
There is no "run command" box, and there never will be. What travels from the panel is configuration, not commands. This is a design decision: if the panel could run commands, your Signalbird password would effectively be your server password.
7. Metric settings
| Setting | What it does | Suggested |
|---|---|---|
| Interval | Seconds between metric reports | 60. Lower values load the server; the floor is 30. |
| Process count | How many top-CPU processes to list | 5. Use 0 to disable. |
| Disks | Disk and inode usage | Keep it on. A full disk is a classic silent outage. |
| Listening ports | Which ports are listening | Optional; answers "since when has this port been closed". |
| Services | Service names, comma separated | nginx, mysql, redis. Find names with systemctl list-units --type=service. |
| Database | Connections, response time, size | Requires local credentials (see §9). |
| Socket.io | Clients and rooms | Point it at your own /metrics endpoint (see §10). |
The agent picks up a saved change within 5 minutes. To apply it now:
sudo systemctl restart signalbird-agent.
8. Watching logs
The agent reads log files where they are. It never moves or deletes them and ships only new lines, remembering where it left off.
In the server detail view: Watched logs → Add log.
| Field | What to write | Example |
|---|---|---|
| Path | Full path | /var/log/nginx/error.log |
| Channel | Radio channel it lands in | server |
| Filter | Regular expression; only matching lines ship | \[error\]|\[crit\] |
Common filters: nginx \[error\]\|\[crit\]\|\[alert\] · Laravel
ERROR\|CRITICAL\|EMERGENCY · PHP-FPM child exited\|segfault · MySQL
\[ERROR\]. Leave it empty to ship everything.
Three rules worth knowing:
- History is not shipped on first install. The agent jumps to the end of the file and listens from there - otherwise a year of nginx logs would burn your Radio quota in the first minute.
- The path must be allowed. Anything outside
allow_pathsis skipped and noted in the agent's own log. Escaping the list through a symlink is blocked too. - Logs consume the Radio quota. The agent is only the courier; retention and notification rules live in Radio.
9. Database monitoring
Credentials live only in the local config file. They are not shown in the panel, cannot be set from it, and are never transmitted. Supported databases: MySQL, MariaDB and PostgreSQL.
Create a read-only user:
-- MySQL / MariaDB
CREATE USER 'signalbird_ro'@'localhost' IDENTIFIED BY 'a-strong-password';
GRANT PROCESS, REPLICATION CLIENT ON *.* TO 'signalbird_ro'@'localhost';
GRANT SELECT ON information_schema.* TO 'signalbird_ro'@'localhost';
-- PostgreSQL
CREATE USER signalbird_ro WITH PASSWORD 'a-strong-password';
GRANT pg_monitor TO signalbird_ro;The agent queries through the server's mysql or psql client; install it
if missing (mysql-client on Ubuntu, default-mysql-client on Debian,
postgresql-client for PostgreSQL).
Then edit the config with sudo nano /etc/signalbird/agent.conf. It already
contains commented-out db_* lines; remove the leading # and fill them in:
db_driver=mysql # mysql | mariadb | pgsql
db_host=127.0.0.1
db_port=3306
db_user=signalbird_ro
db_pass=a-strong-password
db_name=my_appRestart the service (sudo systemctl restart signalbird-agent) and switch
Database on in the panel.
The password never appears on a command line: the agent passes it only to that one call's environment as
MYSQL_PWD/PGPASSWORD, otherwise anyone runningpson the box would see it.
10. Socket.io monitoring
The agent only calls localhost addresses (http://127.0.0.1:…,
http://localhost:…, http://[::1]:…) and never follows redirects. That is
deliberate: if the panel could name any address, the agent would become a tool
for scanning the customer's internal network.
// Node.js + socket.io
const http = require('http')
http.createServer((req, res) => {
if (req.url !== '/metrics') { res.writeHead(404); return res.end() }
res.writeHead(200, { 'Content-Type': 'application/json' })
res.end(JSON.stringify({
clients: io.engine.clientsCount,
rooms: io.sockets.adapter.rooms.size,
events_per_second: eventsPerSecond,
}))
}).listen(3001, '127.0.0.1') // localhost ONLYEnable Socket.io in the panel and enter
http://127.0.0.1:3001/metrics.
11. Expected signals - the "backup did not run" alarm
The logic is inverted: the absence of something raises the alarm.
The scenario
Your database backup runs hourly. One day cron breaks and it stops running. There is no error message - because a job that does not run produces no errors. You find out when the disk dies and your latest backup is three weeks old.
Setting it up
1. Create the check. Watchers → New → type Expected signal.
2. Say when. In "Expected signal timing":
| Option | When it is expected |
|---|---|
| Sliding window | Counts from the last signal (legacy behaviour) |
| Every hour | 00:00, 01:00, 02:00 … |
| Every 15 / 30 minutes | :00, :15, :30, :45 |
| Every 6 hours | 00:00, 06:00, 12:00, 18:00 |
| Daily at a given time | e.g. every day at 03:30 |
| Custom (cron) | e.g. 0 4 * * 1 (Mondays at 04:00) |
Tolerance is how long you wait: "every hour + 5 minutes" means the alarm
fires if nothing arrives by 14:05. If the machine runs the agent, also pick
the server and a signal key such as db-backup.
3. Add one line to your script.
#!/bin/bash
if mysqldump --all-databases | gzip > /var/backups/db.sql.gz; then
signalbird agent signal db-backup ok "$(du -h /var/backups/db.sql.gz | cut -f1)"
else
signalbird agent signal db-backup fail "mysqldump failed"
fiRun the script as root.
signalbird agent signalreads the token from/etc/signalbird/agent.conf, which only root can read. Put the script in root's crontab (sudo crontab -e) and prefix manual tests withsudo. Run as another user, it fails with "izin yok, sudo ile çalıştırın" (permission denied, run with sudo).
Without the agent (or for a script that cannot run as root), the check gives you a URL that needs no login:
curl -fsS "https://live.signalbird.io/api/heartbeat/YOUR_TOKEN"
curl -fsS "https://live.signalbird.io/api/heartbeat/YOUR_TOKEN?status=fail&message=mysqldump+failed"Three rules
- The schedule is anchored to midnight, not to your install time. A check created at 14:26 with "every hour" expects XX:00, not XX:26.
- An early signal does not count. A signal at 13:58 does not satisfy the 14:00 slot. Without this rule, a job that ran 59 minutes early would mask a real miss forever.
faildoes not wait. If the job ran and failed, the alarm fires immediately. Silence only catches "the server is gone".
Without touching the script: file mode
If you cannot edit the backup script, give the check a file path
(/var/backups/db.sql.gz). The agent looks at the file's modification time:
if it is fresh it sends the signal itself; if it is stale it sends nothing and
the alarm fires as usual. If the file does not exist at all, it sends fail.
12. Command reference
Every command is signalbird agent <command>. Most need sudo because the
config file is readable by root only.
| Command | What it does |
|---|---|
sudo signalbird agent install --token=… [--allow=…] [--api=…] |
Checks the token with Signalbird, then writes the config, installs and starts the service. Safe to re-run: your config is kept, only the token and API address (and allowed paths, if given) are refreshed. Replaces the old bash agent. Refuses to install from an npx cache. |
sudo signalbird agent status |
Shows the config and service state, tries the connection, ends with "Bağlantı tamam." The first thing to check. |
sudo signalbird agent once |
Runs one cycle: fetch config, ship logs and file signals, send metrics. Good for testing. |
sudo signalbird agent signal <key> [ok|fail] [message] |
Sends an expected signal. Status defaults to ok. |
signalbird agent run |
Runs forever. The service uses this; you never call it by hand. |
sudo signalbird agent uninstall |
Removes the service. /etc/signalbird/agent.conf and /var/lib/signalbird stay, so a reinstall keeps your config and log positions. |
signalbird agent version |
Agent version (e.g. 1.1.0). Separate from the package version, which signalbird --version prints. |
sudo signalbird agent signal db-backup ok "2.4 GB, 51 s"
sudo signalbird agent signal nightly-report fail "report failed"
sudo signalbird agent onceService logs:
systemctl status signalbird-agent
journalctl -u signalbird-agent -f
sudo tail -f /var/log/signalbird-agent.logRemoving it completely
sudo signalbird agent uninstall && sudo npm uninstall -g signalbird-cli && sudo rm -rf /etc/signalbird /var/lib/signalbirdThis removes the service, the package, the config file and the log positions. Delete the server record in the panel too (see §19).
Same package, another role: signalbird fix
On developer machines the signalbird-cli package is also used as the code
fixer (signalbird fix). That role refuses to run as root and is not needed
on servers: servers only use signalbird agent.
13. Config file reference
Path: /etc/signalbird/agent.conf
token=sba_live_xxxxxxxxxxxxxxxxxxxx
api_base=https://live.signalbird.io/api
allow_paths=/var/log,/srv/app/storage/logs
db_driver=mysql
db_host=127.0.0.1
db_port=3306
db_user=signalbird_ro
db_pass=a-strong-password
db_name=my_appPlain key=value lines; the file is never executed, only read line by line.
Readable by root only (0600). Restart the service after changes
(sudo systemctl restart signalbird-agent). State (log read positions) lives
in /var/lib/signalbird/state, the last known panel config in
/var/lib/signalbird/config.json; the agent's own log is
/var/log/signalbird-agent.log (tokens are masked).
14. Using it with the SDK
The agent is a program, not a library: it is not, and should not be, an SDK package. Everything around it, however, is available:
| Need | How |
|---|---|
| Ship your application's own errors and events | Radio SDK (signalbird package, 12 languages). Agent-shipped server logs land in the same place. |
| Read or report on those logs | Management surface (radio:read scope): management.radioEvents({...}) |
| Send an expected signal from code | No agent needed, one HTTP call: /api/heartbeat/<token> |
| List or manage server records | Panel endpoints (/v1/panel/agents) with a Sanctum session. No SDK method yet. |
import { Signalbird } from 'signalbird'
const log = new Signalbird({ domainKey: process.env.SB_RADIO_KEY })
await log.error('Backup script failed', {
channel: 'server',
meta: { host: 'web-01', exit_code: 2 },
})Writing your own agent? The protocol is public: AGENT-PROTOCOL.md.
15. The endpoints the agent speaks
All one-way: the agent brings, Signalbird accepts.
Authorization: Bearer sba_live_…
Content-Type: application/json
Accept: application/json| Endpoint | Purpose |
|---|---|
POST /v1/agent/hello |
Identify; receive configuration and version status. |
GET /v1/agent/config |
Configuration only. |
POST /v1/agent/metrics |
Send metrics. |
POST /v1/agent/logs |
Send log lines (max 100 per request). |
POST /v1/agent/signal |
Send an expected signal (ok / fail). |
curl -X POST https://live.signalbird.io/api/v1/agent/signal \
-H "Authorization: Bearer sba_live_xxx" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"key":"db-backup","status":"ok","message":"2.4 GB"}'Field limits: message 4000, source 120 characters. Do not omit
Accept - without it a validation error comes back as a redirect instead of
JSON.
16. Security - what it can and cannot do
The agent cannot: start or stop services (other than its own, during install and uninstall); delete, modify or create files (beyond its own state folder and log); install packages or change system settings; receive commands from Signalbird (no such endpoint exists); update itself; read files outside the allowed roots; call any address other than the Signalbird API and localhost.
It only ever runs a fixed list of programs: df, systemctl, ss, ps,
mysql, psql. The list is hard-coded; calling anything else is an error.
Commands run without a shell, so nothing from the panel is ever interpreted by
one. The full list with exact arguments:
AGENT-COMMANDS.md.
Reading config and logs and talking to Signalbird is done by Node.js itself;
no curl, python3 or jq needed.
Sent to Signalbird: metric numbers, service names and states, matching lines from the log files you chose, signals. Never sent: your database password, your config file, the contents of files you did not choose.
If the token leaks, the worst anyone can do is send fake metrics and fake
logs; it grants no access to any other team data. Rotate the key in the panel
and re-run sudo signalbird agent install --token=… with the new one.
If the token is rejected (401) the agent stops and systemd does not
restart it, so it never loops on 401s. If the module is disabled (403
MODULE_DISABLED) it waits and resumes on its own once the module is back.
What privileges does it run with? Install and the service need root (for
the service unit, the 0600 config file and reading /var/log). The systemd
unit runs with ProtectSystem=strict: the only writable places are its state
folder (/var/lib/signalbird) and its own log under /var/log.
17. Versions and updates
The agent never updates itself. When a new agent version ships, the server row gets an "update available" badge and you get one notification per version (security releases also push to your phone). The agent also writes a "new agent version available" line to its own log.
To update:
sudo npm install -g signalbird-cli@latest && sudo systemctl restart signalbird-agentYour config and log positions are preserved.
The agent version is reported separately from the package version: the
panel shows what signalbird agent version prints (currently 1.1.0), while
signalbird --version prints the package version.
18. Troubleshooting
| Symptom | Cause and fix |
|---|---|
| Server shows offline | systemctl status signalbird-agent; start it with sudo systemctl start signalbird-agent if stopped. |
signalbird: command not found |
The package is not installed: sudo npm install -g signalbird-cli. |
| "Node 20+ gerekli" (Node 20+ required) | Node.js is too old. Upgrade with the NodeSource steps in §3. |
| "Kurulum root gerektirir" (install needs root) | Prefix the command with sudo. |
| "npx ile servis kurulmaz" (no service from npx) | Run sudo npm install -g signalbird-cli first, then sudo signalbird agent install …. |
| "Ayar dosyası okunamadı … izin yok" (cannot read config) | The config is root-only. Use sudo; for scripts, move them to root's crontab. |
status / install says the key was rejected |
Token wrong or rotated. Take a new one and re-run sudo signalbird agent install --token=…. |
| Install says "Bağlantı doğrulanamadı; kurulum yine de yapılıyor" | The server could not reach Signalbird at that moment (outbound 443, DNS, proxy). The install completes and the service keeps retrying. Fix the network and check with sudo signalbird agent status. |
MODULE_DISABLED |
The Server Monitoring module is missing or your subscription lapsed. Add it in the panel; the agent resumes on its own. |
| Metrics arrive, logs do not | Is the path under allow_paths? Does the filter match? Check /var/log/signalbird-agent.log. |
| "log yolu izinli değil" warning | Widen allow_paths and restart the service. |
Database ok:false |
Check db_* lines, user privileges, and that the mysql/psql client exists. |
| Socket metrics missing | Does the URL start with 127.0.0.1? Does the endpoint return JSON? Try curl http://127.0.0.1:3001/metrics. |
| I sent a signal but the alarm fired | It probably arrived outside the window (see §11, rule 2). The check log shows "arrived outside the window". |
| "… anahtarıyla bir izleme yok" (no check with that key) | The signal key in the panel and in your command differ. |
When in doubt, send support these two outputs:
sudo signalbird agent status
sudo tail -50 /var/log/signalbird-agent.log19. FAQ
Does the agent slow my server down? No. It reads a few files and makes one HTTP request per minute. The only wait is one second for the CPU sample.
What happens if the network drops? It skips the metric, does not advance the log position and retries next cycle. Missed lines ship once connectivity returns.
Can I install two agents on one machine? You should not. One server, one record, one token.
I had the old bash agent. What do I do? Nothing to delete: run the
install in §4. The service name and files are the same; the new agent takes
over and inherits your config file and log positions. The old
/usr/local/bin/signalbird-agent file is no longer used and can be removed.
I deleted my server. Now what? Delete the record in the panel. Expected signals bound to it are deactivated, so no alarm fires for a machine that is gone.
Can I see metric history as a chart? Today the panel shows the current state. History charts are on the roadmap; logs and alarm history are already stored.
Does it monitor Docker containers? Container processes and resource use are included in the server metrics. Per-container metrics are not there yet.
Can I install it on Windows Server? Not yet (see §5). Support will show up in the panel when it lands.
How is it billed? Per server, monthly. Metric volume is never billed. Logs consume the Radio module quota.