{"id":15517327,"url":"https://github.com/skx/purppura","last_synced_at":"2025-04-23T04:12:47.121Z","repository":{"id":57554365,"uuid":"126932857","full_name":"skx/purppura","owner":"skx","description":"A server for receiving and processing alerts \u0026 events.","archived":false,"fork":false,"pushed_at":"2025-04-16T21:59:40.000Z","size":181,"stargazers_count":22,"open_issues_count":2,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-23T04:12:41.293Z","etag":null,"topics":["alerts","dead-man-switch","devops","golang","monitoring","notification"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/skx.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"skx","custom":"https://steve.fi/donate/"}},"created_at":"2018-03-27T05:21:00.000Z","updated_at":"2024-12-24T17:40:59.000Z","dependencies_parsed_at":"2024-05-04T06:28:49.010Z","dependency_job_id":"ff7ddc14-d57a-48d4-984e-e13b66c31766","html_url":"https://github.com/skx/purppura","commit_stats":{"total_commits":126,"total_committers":3,"mean_commits":42.0,"dds":"0.015873015873015928","last_synced_commit":"764b19d43dde190f130fecbd75692722a26fe58b"},"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skx%2Fpurppura","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skx%2Fpurppura/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skx%2Fpurppura/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skx%2Fpurppura/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/skx","download_url":"https://codeload.github.com/skx/purppura/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250366717,"owners_count":21418772,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["alerts","dead-man-switch","devops","golang","monitoring","notification"],"created_at":"2024-10-02T10:12:32.386Z","updated_at":"2025-04-23T04:12:47.099Z","avatar_url":"https://github.com/skx.png","language":"Go","funding_links":["https://github.com/sponsors/skx","https://steve.fi/donate/"],"categories":[],"sub_categories":[],"readme":"[![Go Report Card](https://goreportcard.com/badge/github.com/skx/purppura)](https://goreportcard.com/report/github.com/skx/purppura)\n[![license](https://img.shields.io/github/license/skx/purppura.svg)](https://github.com/skx/purppura/blob/master/LICENSE)\n[![Release](https://img.shields.io/github/release/skx/purppura.svg)](https://github.com/skx/purppura/releases/latest)\n\nTable of Contents\n=================\n\n* [Purppura](#purppura)\n* [Alerts](#alerts)\n* [Installation](#installation)\n  * [Source Installation go \u0026lt;=  1.11](#source-installation-go---111)\n  * [Source installation go  \u0026gt;= 1.12](#source-installation-go---112)\n  * [Post-Installation Setup](#post-installation-setup)\n* [Notifications](#notifications)\n* [Links](#links)\n* [Docker](#docker)\n* [Github Setup](#github-setup)\n\n\n# Purppura\n\nPurppura is an alert manager which allows the centralised collection and distribution of events or alerts.  (Things submitted are _events_ and they become alerts when they _alert_ a human!)\n\nFor example a trivial heartbeat-style alert might be implemented by having a host send a message every minute:\n\n* \"Raise an alert if you don't hear from me in 5 minutes\".\n   * i.e. This is a [dead man's switch](https://en.wikipedia.org/wiki/Dead_man%27s_switch) system.\n\nIf that host were to suffer a crash then five minutes after the last submission of the event an alert would be raised, and a human would be notified.\n\n\n# Alerts\n\nEvents are submitted by making a HTTP POST-request to the server, with a JSON-payload containing a [number of fields](ALERTS.md).  When a new POST request is received it will be transformed into an event:\n\n* If the event is new it will be saved into the database.\n* If the event has been previously seen, then the fields of that existing entry will be updated.\n   * This is possible because events are uniquely identified by a combination of the submitted `id` field and the source IP address from which it was received.\n\nEvents have several states:\n\n* Pending.\n   * An event might become raised at some point in the future.\n* Raised.\n   * A raised event will trigger a notification every **minute** to inform your sysadmin(s).\n* Acknowledged\n   * An alert in the acknowledged state will not re-notify.\n   * An event can be acknowledged via the HTTP-server, and it is assumed a human will do that to indicate they're handling the issue.\n* Cleared\n   * Alerts in the cleared-state are reaped over time.\n\nThe required fields for a submission are documented in [ALERTS.md](ALERTS.md),\nbut in brief you need to submit:\n\n|Field Name | Purpose                                                   |\n|-----------|-----------------------------------------------------------|\n|id         | Name of the alert                                         |\n|subject    | Human-readable description of the alert-event.            |\n|detail     | Human-readable (expanded) description of the alert-event. |\n|raise      | When this alert should be raised. (\"now\", \"+5m\", etc)     |\n\n\n\n\n## Installation\n\nThere are two ways to install this project from source, which depend on the version of the [go](https://golang.org/) version you're using.\n\nIf you just need the binaries you can find them upon the [project release page](https://github.com/skx/purppura/releases).\n\n\n### Source Installation go \u003c=  1.11\n\nIf you're using `go` before 1.11 then the following command should fetch/update the project, and install it upon your system:\n\n     $ go get -u github.com/skx/purppura\n\n### Source installation go  \u003e= 1.12\n\nIf you're using a more recent version of `go` (which is _highly_ recommended), you need to clone to a directory which is not present upon your `GOPATH`:\n\n    git clone https://github.com/skx/purppura\n    cd purppura\n    go install\n\n\n### Post-Installation Setup\n\nOnce installed you'll be ready to launch the server, but first of all you\nmust create the (MySQL) database and save the connection-details in the\nenvironment.  The definition of the appropriate tables can be found in\nthe [purppura.sql](purppura.sql) file.\n\nAssuming you're using MySQL on the local-host you can export the details\nlike so:\n\n      ~ $ export PURPLE_DSN=\"user:pass@tcp(localhost:3306)/purple?timeout=5s\"\n\nOnce the environment has the correct details you can now launch the\nserver:\n\n      ~ $ purppura serve\n      Listening on http://localhost:8080/\n\nYou'll want to add at least one user who can login to the web-based user-interface.  Users are stored in the database, and can be added/listed/removed  while the server is running:\n\n      ~ $ purppura add-user\n      Enter Username: moi\n      Enter Password: kissa\n      ~ $\n\n\u003e **NOTE**: You must set the `$PURPLE_DSN` environmental-variable for adding, listing, or removing users.\n\nOnce the user has been added you should be able to login to the web interface with username `moi` and password `kissa`.\n\nTo see your users you can run:\n\n      ~ $ purppura list-users\n\nAnd to delete a user:\n\n      ~ $ purppura del-user\n      Enter Username: moi\n\n\n\n## Notifications\n\nThe web-based user-interface lists alerts which are pending, raised, or acknowledged.  While this is useful it isn't going to wake anybody up if something fails overnight, so we have to allow notification via SMS, WhatsApp, etc.\n\nThere is no built-in facility for routing notifications to people directly, instead the default alerting behaviour is to simply pipe any event which is in the raised state into a binary called `purppura-notify`.\n\n**NOTE**: Remember that you need to add this script somewhere upon your `PATH`.\n\n* You can find a sample `purppura-notify` beneath [notifiers/](notifiers/).\n\nThe notification binary is executed with a JSON-representation of the event\npiped to it on STDIN, and will be executed in two situations:\n\n* The first time an event becomes raised.\n* Once every minute, as a reminder, as the event continues to be in the raised state.\n\nIn addition to the actual event-details the JSON object will have a `NotifyCount` attribute, which will incremented once each time the alert has been piped to the binary.  This allows you to differentiate between the two obvious states:\n\n* The event has become raised for the first time.\n* This is a reminder that the event continues to be outstanding, neither fixed nor acknowledged.\n\nUsing the count is useful if you're using an external service to deliver your alert-messages which has its own reminder-system.  For example I use the [pushover](http://pushover.net/) service, and there is a facility there to repeat the notifications until they are read with the mobile phone application.\n\nUsing the count-facility I configure my alerter to notify Pushover __once__,\nand if the event continues to be outstanding I don't need to needlessly repeat the phone-notification.\n\nA second use for the reminder-facility is to allow alerts to be raised through a hierarchy:\n\n* You might notify an individual the first ten times an event is raised.\n* But after that you'd switch to notifying their boss too.\n\n\n\n## Links\n\nA simpler implementation of a similar idea is nanny:\n\n* https://github.com/lunemec/nanny/\n\nAs an example of something that extensively communicates with `purppura` please see my network monitoring tool:\n\n* https://github.com/skx/overseer\n\n`overseer` carries out network testing, and submits the results of each test to a central purppura instance - automatically raising/clearing alerts as systems and services come and go.  The notification system that `overseer` provides is [very flexible](https://github.com/skx/overseer/#notifications); but I use purppura exclusively.\n\n\n\n## Docker\n\nBuilding the Docker image is as simple as you would expect:\n\n```\n$ docker build -t purppura:latest .\n```\n\nHowever note that when it comes to _deployment_ there are a couple of complications:\n\n* We need the MySQL database to be created and populated.\n  * Due to this you'll need to copy the `purppura.sql` file to the host you're running on.\n* We need to have an external binary to issue the notifications.\n  * When an alert is raised an executable will be launched, with the alert details piped to STDIN.\n  * So you'll need to bind-mount the notification script to `/srv/bin/purppura-notify`.\n\nOn the host you're running the application upon that means you'll need these three files:\n\n* `docker-compose.yml`\n  * The helper to launch the containers.\n* `purppura-notify`\n  * The script executed when an alert is raised.\n* `purppura.sql`\n  * The database file.\n\nAssuming those files are present:\n\n```\n$ docker-compose up -d\n```\n\nNow you can add your user:\n\n```\n$ docker exec -t -i purppura_purppura_1 /app/purppura add-user\n```\n\nAfter the first run you won't need the `purppura.sql` file, as the MySQL state will be persisted locally, but leaving it in-place is safest.\n\n\n\n## Github Setup\n\nThis repository is configured to run tests upon every commit, and when\npull-requests are created/updated.  The testing is carried out via\n[.github/run-tests.sh](.github/run-tests.sh) which is used by the\n[github-action-tester](https://github.com/skx/github-action-tester) action.\n\nReleases are automated in a similar fashion via [.github/build](.github/build),\nand the [github-action-publish-binaries](https://github.com/skx/github-action-publish-binaries) action.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskx%2Fpurppura","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskx%2Fpurppura","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskx%2Fpurppura/lists"}