You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit c512b8d
Browse filesBrowse the repository at this point in the historyBrowse files
Receives data from agents, stores it in TimescaleDB, and checks the alert rules. It updates the database schema by itself when it starts. It listens on port 9000.
83
+
Receives data from agents, stores it in TimescaleDB, checks the alert rules and sends the alerts to the notification channels. It updates the database schema by itself when it starts. It listens on port 9000.
83
84
84
85
### Client
85
86
The web dashboard and its JSON API, on port 8080. It reads everything from the Collector. It also serves the install script and agent builds that new hosts download. It needs a login, see [Security](#security).
86
87
87
-
### Alert processor
88
-
Optional. The Collector sends it alerts as they open, change and resolve, and it passes them on to email, Slack and PagerDuty. Alerts show on the dashboard without it.
89
-
90
88
## Security
91
89
92
90
-**Agent keys.** Each enrolled host gets its own key, stored hashed on the server. It can only send data, and only as that host. `collector -remove-agent <name>` revokes it.
93
-
-**Shared key.** The Collector, Client and Alert processor use a shared key from `collector -init`. Each call carries a short-lived token signed with it.
91
+
-**Shared key.** The Collectorand Client use a shared key from `collector -init`. Each call carries a short-lived token signed with it.
94
92
-**TLS.** Traffic between components can be encrypted. See the `*_TLS_*` and `*_CERT_PATH` settings in each component's `.env-example`.
95
93
-**Dashboard login.** The dashboard stays locked until a user exists. `collector -add-user <name>` creates one and prints its password, `-reset-password`, `-remove-user` and `-list-users` manage them, and users change their own password on the dashboard. A login lasts 30 days. After 10 wrong passwords a user name is locked for 15 minutes. The install script and agent downloads stay public, so new hosts can enroll.
96
94
-**Agent updates.** Agent builds are signed with a key that stays where you build them (`~/.config/symon/agent-signing.key`). Agents only install updates signed with it, so a tampered download or a spoofed update request cannot run code on your hosts.
97
95
-**Tasks.** A host only runs commands from its own tasks file, which the dashboard can start but not change. The agent refuses a run whose command is not the one in its file, so a stolen dashboard login cannot run anything the host's owner did not list. See [Tasks](docs/install.md#tasks).
98
-
-**Roles.** Admins can change alert rules, update agents and run tasks, viewers can only look. `-add-user <name> -role viewer` creates a viewer, `-set-role <name> -role admin` changes it.
96
+
-**Notification secrets.** Passwords, tokens, keys and webhook URLs of notification channels are kept in the collector's database and never shown on the dashboard again after saving. Database backups contain them.
97
+
-**Roles.** Admins can change alert rules and notification channels, update agents and run tasks, viewers can only look. `-add-user <name> -role viewer` creates a viewer, `-set-role <name> -role admin` changes it.
99
98
-**HTTPS.** Put a reverse proxy like Caddy or nginx in front of the dashboard, so passwords and the session cookie are encrypted.
100
99
101
100
## Local development
102
101
103
-
`docker compose up --build` starts TimescaleDB, the Collector, the Alert processor, the Client on http://localhost:8080 and one Agent. The Agent reports on its own container, not the host. Create a user to log in with `docker compose exec collector ./collector -add-user dev`. The stack is for development only.
102
+
`docker compose up --build` starts TimescaleDB, the Collector, the Client on http://localhost:8080 and one Agent. The Agent reports on its own container, not the host. Create a user to log in with `docker compose exec collector ./collector -add-user dev`. The stack is for development only.
104
103
105
104
Building needs Go 1.26 and Node.js 22 or newer.
106
105
@@ -149,6 +148,14 @@ The Client exposes a JSON API under `/api/v1`. Times are unix seconds. Errors re
149
148
* For admins only. Asks the host's agent to run one of its tasks and answers the new run. 404 when the host does not list the task, 409 while the host is running one
150
149
*`GET /api/v1/task-runs/{id}`
151
150
* For admins only. One run with its `output` so far
151
+
*`GET /api/v1/notifications/channels`
152
+
* The notification channels, with the newest message's status. Admins also get the settings, with secrets left empty and `secretsSet` naming the saved ones, and the last error
153
+
*`POST /api/v1/notifications/channels` and `PUT /api/v1/notifications/channels/{id}` with `{"name": "...", "kind": "email", "settings": {...}, "isDefault": true, "skipWarnings": false, "enabled": true}` as JSON, `DELETE /api/v1/notifications/channels/{id}`
154
+
* For admins only. `kind` is `email`, `slack`, `pagerduty` or `webhook`. A secret left empty keeps the saved one, and the name and kind do not change. 409 for a name that is taken, and for deleting a channel that rules pick
155
+
*`POST /api/v1/notifications/channels/{id}/test` with `{}` as JSON
156
+
* For admins only. Sends a test message and answers `{"ok": true}`, or `ok` false with the `error`
157
+
*`GET /api/v1/notifications?limit=`
158
+
* The newest messages to channels, 50 unless `limit` asks for up to 200, with their status and tries
152
159
*`GET /api/v1/rules`
153
160
* The alert rules, each with `id`, `enabled` and `rule`, the rule in the alerts.json format
154
161
*`POST /api/v1/rules` and `PUT /api/v1/rules/{id}` with `{"enabled": true, "rule": {...}}` as JSON, `DELETE /api/v1/rules/{id}`
Copy file name to clipboardExpand all lines: docs/install.md
+51-32Lines changed: 51 additions & 32 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -20,10 +20,9 @@ This guide sets up SyMon on one Linux server and adds hosts to it. It covers upg
20
20
| Collector | the server | 9000, from every host | yes |
21
21
| Client (dashboard) | the server | 8080, from browsers and new hosts | yes |
22
22
| TimescaleDB | the server, or any PostgreSQL host | 5432, from the collector only | yes |
23
-
| Alert processor | the server | 5999, from the collector only | only for email, Slack or PagerDuty |
24
23
| Agent | every monitored host | none | yes |
25
24
26
-
Agents send data to the collector on port 9000. The dashboard only talks to the collector. New hosts download the agent from the dashboard on port 8080, so a new host has to reach both ports.
25
+
Agents send data to the collector on port 9000. The dashboard only talks to the collector. The collector sends alerts out itself, by email, to Slack, to PagerDuty or to a webhook, so it needs to reach those services. New hosts download the agent from the dashboard on port 8080, so a new host has to reach both ports.
27
26
28
27
## Install the server
29
28
@@ -49,7 +48,6 @@ Copy the bundles to the server and extract them:
49
48
sudo mkdir -p /opt/symon /etc/symon
50
49
sudo tar -xf collector_linux_x86_64.tar.gz -C /opt/symon
51
50
sudo tar -xf client_linux_x86_64.tar.gz -C /opt/symon
52
-
sudo tar -xf alertprocessor_linux_x86_64.tar.gz -C /opt/symon # only for alerts
# where new hosts download the agent, as they reach it
91
+
# where new hosts download the agent, as they reach it, and where links
92
+
# in alert messages point
94
93
SYMON_DASHBOARD_URL=http://symon.example.lan:8080
95
-
# only with the alert processor
96
-
SYMON_ALERT_ENDPOINT=localhost:5999
97
94
```
98
95
99
96
Alert rules are edited on the dashboard, see [Alerts](#alerts).
@@ -192,7 +189,7 @@ Where the install script cannot be used, for example on a host that cannot reach
192
189
193
190
## Alerts
194
191
195
-
Alert rules are edited on the dashboard's Rules page. The collector checks the rules that are on every 15 seconds, so a change applies right away, and shows open alerts on the dashboard. To also send them by email, Slack or PagerDuty, run the alert processor.
192
+
Alert rules are edited on the dashboard's Rules page. The collector checks the rules that are on every 15 seconds, so a change applies right away, shows open alerts on the dashboard, and sends them to the [notification channels](#notifications) set up there.
196
193
197
194
A new install starts with one rule, "Host not reporting", which goes critical when any host sends nothing for 5 minutes. Rules can watch every host, including ones added later, or a list of hosts.
198
195
@@ -223,10 +220,7 @@ A rule looks like this:
223
220
"CriticalThreshold": 90,
224
221
"TriggerIntveral": 120,
225
222
"Template": "{subject}\n{serverName} {metricName} {value} {op} {expected} at {timestamp}\n{desc}",
226
-
"Email": false,
227
-
"Slack": true,
228
-
"SlackChannel": "#ops",
229
-
"Pagerduty": false
223
+
"Channels": ["ops email", "team slack"]
230
224
}
231
225
]
232
226
```
@@ -243,36 +237,62 @@ A rule looks like this:
243
237
|`endpoint`| an HTTP check from the collector, no `Servers`|`Endpoint`, `Method`, `ExpectedHTTPCode`, `POSTBody`, `POSTContentType`, `CustomCACert`, `CertWarnDays`, `CertCriticalDays`|
244
238
| any name, with `"IsCustom": true`| a custom metric ||
245
239
246
-
`Servers` lists host names, or `"*"` for every host. `Op` is one of `>`, `<`, `>=`, `<=`, `==` or `!=`. A value has to stay past a threshold for `TriggerIntveral` seconds before the alert opens, and back to normal for as long before it resolves.
240
+
`Servers` lists host names, or `"*"` for every host. `Channels` names the [notification channels](#notifications) the rule's alerts go to; left out, they go to the default channels. `Op` is one of `>`, `<`, `>=`, `<=`, `==` or `!=`. A value has to stay past a threshold for `TriggerIntveral` seconds before the alert opens, and back to normal for as long before it resolves.
247
241
248
242
The collector requests each `endpoint` rule's URL every `SYMON_ENDPOINT_CHECK_INTERVAL` seconds (60 by default) and waits up to 30 seconds for an answer. `SYMON_ENABLE_ENDPOINT_MONITORING=false` stops that. A check passes when the status code is `ExpectedHTTPCode`, 200 if left out. The alert opens once checks have failed for `TriggerIntveral` seconds and resolves once they have passed for as long. Endpoint alerts belong to no host, and every check is kept as long as the 1 hour averages, for the response time and uptime charts on the dashboard's Endpoints page.
249
243
250
244
HTTPS endpoints also alert on their certificate: a warning when it expires in under `CertWarnDays` days (14 if left out) and critical under `CertCriticalDays` (3). 0 switches a level off. The Endpoints page shows when each certificate expires.
251
245
252
246
`disk_forecast` rules use `Op``<`, for example a warning under 14 days and critical under 3. A forecast needs a day of history and steady growth, so a disk that fills and empties, like one with rotating logs, gets none. A disk that is not filling up counts as 365 days. The dashboard shows the forecast in the host's disk table and on a chart of where each filling disk is headed, and on the hosts page when a disk fills up within 30 days.
253
247
254
-
### The alert processor
248
+
### Notifications
255
249
256
-
`/etc/symon/alertprocessor.env` holds the port, the shared key, and the credentials for each channel you use (see [alertprocessor/.env-example](../alertprocessor/.env-example)):
250
+
The collector sends every alert to notification channels when it opens, changes between warning and critical, and resolves. Admins set channels up on the dashboard: Alert rules, then Notification channels. Send test sends a message right away and shows what the service answered.
257
251
258
-
```sh
259
-
SYMON_ALERT_PORT=5999
260
-
SYMON_KEY=...
261
-
SLACK_TOKEN=xoxb-...
262
-
EMAIL_HOST=smtp.example.com
263
-
EMAIL_PORT=587
264
-
EMAIL_USER=...
265
-
EMAIL_PASSWORD=...
266
-
EMAIL_FROM=symon@example.com
267
-
ALERT_EMAIL_LIST=ops@example.com
268
-
```
252
+
| Kind | Needs |
253
+
|---|---|
254
+
| Email | An SMTP server, its port (587 by default), a user and password if it asks for them, a from address and the addresses to send to. Port 465 uses TLS from the start, other ports switch to TLS when the server offers it, and a password is only sent over TLS. |
255
+
| Slack | A Slack app's bot token with the `chat:write` scope, and the channel, like `#ops`. Invite the app to the channel. Each alert is one message, updated when it changes and resolves. |
256
+
| PagerDuty | The integration key of an Events API v2 integration on a PagerDuty service. Each alert is one incident, resolved with the alert. |
257
+
| Webhook | A URL that gets every alert as JSON in a POST, and an optional header, like `Authorization: Bearer ...`. Any 2xx answer counts as delivered. |
- A rule picks channels in its editor. A rule that picks none goes to the channels marked **default**, which is how the built-in "Host not reporting" rule reaches someone.
262
+
- A channel can take **only critical alerts** and skip warnings.
263
+
- A resolved alert goes to the channels that heard about it.
264
+
- A channel that is off gets nothing.
265
+
266
+
Messages wait in the collector's database, so nothing is lost when a service is down or the collector restarts. A failed message is tried again after 30 seconds, 2, 10 and 30 minutes and an hour, then given up on. Messages about one alert go out in order. The Notifications page lists the newest messages, what became of them and the last error of each channel.
267
+
268
+
Set `SYMON_DASHBOARD_URL` on the collector to have messages link to the host's page.
269
+
270
+
The webhook body:
271
+
272
+
```json
273
+
{
274
+
"event": "opened",
275
+
"severity": "critical",
276
+
"subject": "[Critical] CPU usage triggered on web1",
`event` is `opened`, `changed`, `resolved` or `test`, and `severity` is `warning`, `critical`, `resolved` or `test`. `host` is empty for endpoint alerts, whose URL is in `target`.
291
+
292
+
Channel settings, including passwords, tokens, keys and webhook URLs, are kept in the collector's database. The dashboard never shows them again after saving: leave a secret empty when editing to keep it. Database backups contain them, so keep backups safe.
293
+
294
+
**Upgrading from the alert processor.** The collector now sends alerts itself, and the alert processor is gone. Add a channel on the dashboard for each service you used, with the credentials from `/etc/symon/alertprocessor.env`, then stop the alert processor and remove it: `sudo systemctl disable --now symon_alertprocessor`, `sudo rm /etc/systemd/system/symon_alertprocessor.service`. `SYMON_ALERT_ENDPOINT` can go from `collector.env`. Rules with the old `Email`, `Slack` or `Pagerduty` ticks keep working: they send to every channel of that kind. Saving such a rule on the dashboard turns the ticks into channel names. PagerDuty now uses an Events API v2 integration key instead of the REST API key.
295
+
276
296
## Tasks
277
297
278
298
A task is a command a host is willing to run when an admin asks for it on the dashboard, like restarting a service or clearing a cache. Each host has a Tasks page with its tasks, a Run button, and a history of who ran what and how it ended.
@@ -411,7 +431,7 @@ Its history stays until retention drops it.
TLS between the components is set up with the `*_TLS_*` and `*_CERT_PATH` settings. The collector and alert processor need a certificate and key. Agents, the dashboard and the collector (for the alert processor) need the CA file.
473
+
TLS between the components is set up with the `*_TLS_*` and `*_CERT_PATH` settings. The collector needs a certificate and key, and agents and the dashboard need the CA file.
0 commit comments