Skip to main content

Profundis Alerting Docker Image

We provide a Docker image that allows you to setup a robust alerting system that receives real-time alerts from Profundis and routes them to your preferred notification channels.

The Profundis Alerting tool is a lightweight client application that connects to the Profundis platform via Server-Sent Events (SSE) and routes security alerts to various notification channels (Discord, email, etc.) based on configurable rules.

Quick Start

We assume

  • Docker is installed on your system (doc).
  • You have a valid Profundis API key.
  • You know the settings / credentials for at least one notification channel (Discord webhook or email).
  • You are comfortable with the Docker CLI usage.

Create a config.yaml file with your settings.

token: "your-profundis-api-token"

# Output channels
channels:
discord_main:
type: "discord"
enabled: true
rate_limit_ms: 500
config:
webhook: "https://discord.com/api/webhooks/your-webhook-url"
template: |
**🚨 New alert received!**

**link:** {{.Protocol}}://{{.Host}}:{{.Port}} {{.StatusCode}} ({{.StatusCodeMessage}}) ({{.Resolution}})
**title:** `{{.Title}} `
**content length:** `{{.ContentLength}} bytes `
**technologies:** `{{join .Technologies ", "}} `
**cert subj:** `{{.CertSubj}} `
**cert org:** `{{.CertSubjOrg}} `

------------------------------------------------------------------------------------
# Alert filters (required even if empty)
filters:
- name: "default_fallback"
channels: ["discord_main"]
conditions: [] # Empty conditions = matches everything (fallback)

Run the Docker container.

docker run -d \
--name profundis-alerting \
--restart unless-stopped \
-v $(pwd)/config.yaml:/config.yaml:ro \
profundis/profundis-alerting:latest

Check the container logs to ensure the container is working properly and connected to profundis.io.

docker logs -f profundis-alerting

Supported Channel Types

  • Discord
discord_alerts:
type: "discord"
enabled: true
rate_limit_ms: 500
config:
webhook: "https://discord.com/api/webhooks/your-webhook"
template: |
**Alert on {{.Host}}**
Status: {{.StatusCode}}
Resolution: {{.Resolution}}
  • Email
email_alerts:
type: "email"
enabled: true
rate_limit_ms: 10000
config:
smtp_host: "smtp.gmail.com"
smtp_port: 587
username: "[email protected]"
password: "your-app-password"
from: "[email protected]"
to: ["[email protected]"]
use_starttls: true
template: |
Alert Details:
Host: {{.Host}}
Status: {{.StatusCode}}

Alerts filtering

You can control which alerts go to which channels using filters.

filters:
- name: "errors_status_codes" # Descriptive name for the filter
channels: ["discord_channel_1"] # List of channels to notify when filter matches
stop_on_match: true # Do not process the other filters
conditions: # Array of matching conditions (all must match)
- field: "status_code"
regex: "^5[0-9]{2}$"

- name: "hosts_containing_prod"
channels: ["my_email_channel"]
stop_on_match: false
conditions:
- field: "host"
regex: ".*prod.*"

You can filter on any field from incoming alerts.

  • host, resolution, port, protocol
  • status_code, status_code_message
  • alert_id, @timestamp
  • cert_expired, cert_trusted
  • technologies, title
  • as_name, ip_country_code
  • And any other field specified here.

Template system

You can customize the notifications content/layout using Go templates. As visible below, conditions can be used.

template: |
**Alert: {{.Host}}**

Status: {{.StatusCode}} ({{.StatusCodeMessage}})
Time: {{.Timestamp}}

{{if .CertExpired}}
Warning: Certificate expired
{{end}}

Technologies: {{join .Technologies ", "}}

You can access any existing field usig the Go template syntax: {{.FieldName}}. Array fields can be joined using the join keyword: {{join .ArrayField ", "}}.

Rate Limiting

You can control the notifications frequency to prevent spam and being rate limited by the output notification system (e.g. Discord, your SMTP, etc).

channels:
discord_main:
rate_limit_ms: 1000 # Max 1 notification per second
email_critical:
rate_limit_ms: 30000 # Max 1 email per 30 seconds

The rate_limit_ms variable can be set the value to 0 for an unlimited rate, but it is not recommended.

Use multiple channels

channels:
default_fallback:
type: "discord"
enabled: true
rate_limit_ms: 1000
config:
webhook: "https://discord.com/api/webhooks/general-channel"
template: |
**Alert: {{.Host}}**
Status: {{.StatusCode}}

discord_critical:
type: "discord"
enabled: true
rate_limit_ms: 2000
config:
webhook: "https://discord.com/api/webhooks/critical-channel"
template: |
@everyone **CRITICAL ALERT**
Host: {{.Host}}
Status: {{.StatusCode}}

filters:
- name: "critical_alerts"
channels: ["discord_critical"]
stop_on_match: true
conditions:
- field: "status_code"
regex: "^5[0-9]{2}$"

- name: "default_fallback"
channels: ["discord_main"]
conditions: [] # Empty conditions = matches everything (fallback)

Troubleshoot common issues

  1. Verify the config file syntax with docker run --rm -v $(pwd)/config.yaml:/config.yaml profundis/profundis-alerting:latest --health-check.
  2. Check file permissions on config.yaml.
  3. Verify the API key validity.
  4. Review filter rules for confl