Monitor BGP Announcements with BGPalerter on Linux

9 min read·Matthieu·RPKINetworkingBGPalerterMonitoringBGP|

Deploy BGPalerter v2 on a Linux VPS to monitor your prefixes for hijacks, route leaks, and RPKI invalid states. Configure Slack and email alerts, run as a systemd service.

If you announce your own prefixes via BGP BGP and Bring Your Own IP on a VPS: The Complete Guide, you need to know when something goes wrong. A prefix hijack, a route leak, an RPKI misconfiguration: these can take your network offline or route your traffic through an attacker. BGPalerter watches public route collector data and alerts you in real time.

This tutorial installs BGPalerter v2 on Ubuntu 24.04, configures prefix and ASN monitoring, sets up Slack and email notifications, and runs the whole thing as a systemd service. It assumes you already have BGP running with BIRD2 BIRD2 BGP Configuration on a Linux VPS or FRR FRRouting BGP Configuration on a Linux VPS.

What does BGPalerter monitor and how does it work?

BGPalerter monitors your BGP prefixes in real time using public route collector data from RIPE RIS. It connects via WebSocket to ris-live.ripe.net, which aggregates feeds from 600+ peers worldwide. No integration with your routers is required. It runs on any Linux server with outbound internet access.

BGPalerter ships with these monitors:

Monitor What it detects Default channel
monitorHijack Origin AS mismatch, sub-prefix hijacks hijack
monitorVisibility Prefix withdrawn or seen by too few peers visibility
monitorNewPrefix Unexpected sub-prefix announced by your AS newprefix
monitorPath AS path matches a regex pattern (scrubbing, transit change) path
monitorPathNeighbors Unexpected upstream/downstream AS in path path
monitorAS Your ASN announces an undeclared prefix misconfiguration
monitorRPKI Prefix announced with RPKI invalid state rpki
monitorROAS ROA added, edited, deleted, or expiring roa

Each monitor has a thresholdMinPeers parameter. An alert fires only when the anomaly is confirmed by at least that many route collector peers, reducing false positives.

How do I install BGPalerter on Ubuntu 24.04?

Download the latest BGPalerter binary from GitHub and make it executable. No Node.js install required when using the prebuilt binary. The self-contained binary bundles the Node.js runtime, so plan for at least 1 GB of free RAM on the monitoring server.

Create a dedicated user

Run BGPalerter under its own unprivileged account. Never run network monitoring tools as root when there is no reason to.

sudo adduser --system --group --home /opt/bgpalerter --shell /usr/sbin/nologin bgpalerter

Download the binary

cd /opt/bgpalerter
sudo -u bgpalerter curl -Lo /opt/bgpalerter/bgpalerter-linux-x64 https://github.com/nttgin/BGPalerter/releases/latest/download/bgpalerter-linux-x64
sudo chmod +x /opt/bgpalerter/bgpalerter-linux-x64
ls -la /opt/bgpalerter/bgpalerter-linux-x64

The file should be around 140 MB. The binary is self-contained and bundles the Node.js runtime. No runtime dependencies.

Docker alternative

If you prefer containers:

docker run -d --name bgpalerter \
  -v /opt/bgpalerter/volume:/opt/bgpalerter/volume \
  --restart unless-stopped \
  nttgin/bgpalerter:latest run serve -- --d /opt/bgpalerter/volume/

Place your config.yml and prefixes.yml in /opt/bgpalerter/volume/ before starting the container. The rest of this tutorial covers the binary method. The configuration files are identical for both.

How do I configure prefixes.yml to monitor my ASN?

BGPalerter needs to know which prefixes and ASNs belong to you. The generate command queries public routing data and builds prefixes.yml from what your AS currently announces.

sudo -u bgpalerter /opt/bgpalerter/bgpalerter-linux-x64 generate \
  -a YOUR_ASN \
  -o /opt/bgpalerter/prefixes.yml \
  -i -m

Replace YOUR_ASN with your AS number (digits only, no "AS" prefix). The flags:

Flag Purpose
-a ASN(s) to monitor. Comma-separated for multiple: -a 64496,64497
-o Output file path
-i Ignore delegated prefixes (originated by other ASNs)
-m Auto-detect all origin ASNs for your prefixes

The command produces a file like this:

198.51.100.0/24:
  description: Production network
  asn: 64496
  ignoreMorespecifics: false
  ignore: false

2001:db8::/32:
  description: IPv6 allocation
  asn: 64496
  ignoreMorespecifics: false
  ignore: false

options:
  monitorASns:
    64496:
      group: default

Key fields

ignoreMorespecifics: Set to true if you intentionally deaggregate (e.g., you announce both /24 and /25s). When false, BGPalerter alerts on any more-specific announcement it did not expect. For most operators, false is the right default. Unexpected more-specifics are a hijack signal.

options.monitorASns: Enables monitorAS for your ASN. BGPalerter alerts if your ASN starts originating a prefix not listed in the file.

group: Controls alert routing. The default group maps to notification channels. You can create separate groups (e.g., noc, engineering) and route them to different Slack channels or email lists.

Edit the generated file to add descriptions, adjust ignoreMorespecifics per prefix, or add prefixes that are not yet announced but should be monitored for unauthorized origination.

How do I configure config.yml?

The auto-configuration wizard creates a default config.yml on first run. For production use, you want explicit control over every parameter.

Create /opt/bgpalerter/config.yml:

connectors:
  - file: connectorRIS
    name: ris
    params:
      carefulSubscription: true
      url: ws://ris-live.ripe.net/v1/ws/
      perMessageDeflate: true

monitors:
  - file: monitorHijack
    channel: hijack
    name: basic-hijack-detection
    params:
      thresholdMinPeers: 3

  - file: monitorVisibility
    channel: visibility
    name: withdrawal-detection
    params:
      thresholdMinPeers: 40
      notificationIntervalSeconds: 3600

  - file: monitorNewPrefix
    channel: newprefix
    name: newprefix-detection
    params:
      thresholdMinPeers: 3

  - file: monitorAS
    channel: misconfiguration
    name: asn-monitor
    params:
      thresholdMinPeers: 3

  - file: monitorRPKI
    channel: rpki
    name: rpki-monitor
    params:
      thresholdMinPeers: 3
      checkUncovered: true
      checkDisappearing: true

  - file: monitorROAS
    channel: roa
    name: rpki-diff
    params:
      enableDiffAlerts: true
      enableExpirationAlerts: true
      roaExpirationAlertHours: 2
      checkOnlyASns: true

  - file: monitorPathNeighbors
    channel: path
    name: path-neighbors
    params:
      thresholdMinPeers: 3

reports:
  - file: reportFile
    channels:
      - hijack
      - newprefix
      - visibility
      - path
      - misconfiguration
      - rpki
      - roa
    params:
      persistAlertData: false
      alertDataDirectory: alertdata/

notificationIntervalSeconds: 86400
persistStatus: true
alertOnlyOnce: false
fadeOffSeconds: 360
checkFadeOffGroupsSeconds: 30

logging:
  directory: logs
  logRotatePattern: YYYY-MM-DD
  maxRetainedFiles: 30
  maxFileSizeMB: 15
  compressOnRotation: true
  useUTC: true

rest:
  host: localhost
  port: 8011

rpki:
  vrpProvider: rpkiclient
  refreshVrpListMinutes: 15

monitoredPrefixesFiles:
  - prefixes.yml

checkForUpdatesAtBoot: true
generatePrefixListEveryDays: 0
pidFile: bgpalerter.pid
maxMessagesPerSecond: 6000
multiProcess: false
environment: production
configVersion: 2

Connector notes

connectorRIS streams live BGP updates from RIPE RIS via WebSocket. The carefulSubscription: true setting limits the stream to only your monitored prefixes, reducing bandwidth and CPU.

Your firewall must allow outbound WebSocket connections to ris-live.ripe.net on port 80 (ws://) or 443 (wss://). No inbound rules needed.

The rest section exposes a local HTTP API on port 8011 for health checks and status queries. It binds to localhost by default, so it is not exposed to the network.

Monitor tuning

thresholdMinPeers controls sensitivity. A value of 3 means at least 3 route collector peers must confirm an anomaly before alerting. Lower values catch more events but produce more false positives. For hijack detection, 3 is a good starting point. For visibility, 40 is appropriate since RIPE RIS has 600+ peers.

notificationIntervalSeconds at the monitor level overrides the global setting. For visibility, 3600 (1 hour) prevents alert fatigue during flapping.

How do I monitor RPKI invalid announcements with BGPalerter?

BGPalerter checks the RPKI validity of every BGP announcement it receives for your prefixes. If your prefix appears with an RPKI invalid state, you get an alert. This catches ROA misconfigurations and certain hijack types that RPKI-based filtering would reject.

The monitorRPKI section in config.yml handles this:

The separate monitorROAS module watches for ROA changes at the RPKI level: new ROAs created, existing ROAs edited or deleted, and ROAs approaching expiration. The roaExpirationAlertHours: 2 setting gives you a 2-hour heads-up before a ROA expires.

A sample RPKI alert looks like:

The prefix 198.51.100.0/24 (AS64496) is announced with RPKI state Invalid.
Seen by 5 peers. Top 3 AS paths: 64496 174 3356, 64496 6939, 64496 1299

How do I set up email alerts in BGPalerter?

Add a reportEmail block to the reports section of config.yml. BGPalerter uses SMTP directly.

reports:
  # ... keep reportFile from above ...

  - file: reportEmail
    channels:
      - hijack
      - newprefix
      - visibility
      - path
      - misconfiguration
      - rpki
      - roa
    params:
      showPaths: 5
      senderEmail: bgpalerter@example.com
      smtp:
        host: mail.example.com
        port: 587
        secure: false
        ignoreTLS: false
        auth:
          user: bgpalerter@example.com
          pass: your-smtp-password-here
          type: login
        tls:
          rejectUnauthorized: true
      notifiedEmails:
        default:
          - noc@example.com

Replace the SMTP values with your mail server details. The showPaths: 5 setting includes up to 5 AS paths in the alert email so you can see where the anomalous route propagated.

Since config.yml contains the SMTP password in plain text, restrict the file permissions so only the bgpalerter user and root can read it:

sudo chown root:bgpalerter /opt/bgpalerter/config.yml
sudo chmod 640 /opt/bgpalerter/config.yml

The notifiedEmails section maps groups to email addresses. The default group receives all alerts. If you defined custom groups in prefixes.yml, add matching entries:

      notifiedEmails:
        default:
          - noc@example.com
        noc:
          - oncall@example.com
          - sre@example.com

How do I set up Slack notifications in BGPalerter?

Add a reportSlack block to the reports section. You need a Slack incoming webhook URL.

Create the webhook in Slack: go to your workspace settings, find "Incoming Webhooks" under Apps, and create a webhook for the channel where you want alerts.

reports:
  # ... keep reportFile and reportEmail ...

  - file: reportSlack
    channels:
      - hijack
      - newprefix
      - visibility
      - path
      - misconfiguration
      - rpki
      - roa
    params:
      showPaths: 3
      colors:
        hijack: "#d60b1c"
        newprefix: "#fa9548"
        visibility: "#fad648"
        path: "#42cbf5"
        rpki: "#d892f0"
        roa: "#d892f0"
      hooks:
        default: https://hooks.slack.com/services/T00/B00/xxxx

The colors map gives each alert type a distinct color in Slack. Red for hijacks, yellow for visibility loss, purple for RPKI issues.

Replace the webhook URL placeholder with your actual Slack webhook. The config.yml permissions set earlier (640, root:bgpalerter) keep the webhook URL readable only by the service.

How do I run BGPalerter as a systemd service?

Create the systemd unit

sudo tee /etc/systemd/system/bgpalerter.service > /dev/null << 'EOF'
[Unit]
Description=BGPalerter - BGP Monitoring
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=bgpalerter
Group=bgpalerter
WorkingDirectory=/opt/bgpalerter
ExecStart=/opt/bgpalerter/bgpalerter-linux-x64
Restart=on-failure
RestartSec=30s

# Hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/bgpalerter
PrivateTmp=true

[Install]
WantedBy=multi-user.target
EOF

The ProtectSystem=strict and ProtectHome=true directives restrict filesystem access. BGPalerter only needs to write to its own directory.

Enable and start

sudo systemctl daemon-reload
sudo systemctl enable --now bgpalerter

enable makes the service start on boot. --now starts it immediately.

systemctl status bgpalerter
 bgpalerter.service - BGPalerter - BGP Monitoring
     Loaded: loaded (/etc/systemd/system/bgpalerter.service; enabled; preset: enabled)
     Active: active (running) since Thu 2026-03-20 10:20:00 UTC; 5s ago
   Main PID: 1373 (bgpalerter-linu)
      Tasks: 10 (limit: 9443)
     Memory: 724.3M
        CPU: 4.483s
     CGroup: /system.slice/bgpalerter.service
             └─1373 /opt/bgpalerter/bgpalerter-linux-x64

The self-contained binary bundles the entire Node.js runtime, so baseline memory is around 500-800 MB regardless of prefix count. Make sure you have at least 1 GB of free RAM on the monitoring server.

Check the logs

journalctl -u bgpalerter -f --no-pager

On startup, BGPalerter loads the config and connects to RIPE RIS. The first lines in the journal look like:

Loaded config: /opt/bgpalerter/config.yml
BGPalerter, version: 2.0.1 environment: production

BGPalerter also writes logs to /opt/bgpalerter/logs/. The logRotatePattern: YYYY-MM-DD setting creates a new log file daily. With maxRetainedFiles: 30 and compressOnRotation: true, you keep a month of compressed logs without manual intervention.

How do I test BGPalerter alerts?

Run BGPalerter with the -t flag to send test alerts through all configured notification channels. This uses a built-in test connector that simulates every alert type without waiting for real BGP events.

sudo -u bgpalerter /opt/bgpalerter/bgpalerter-linux-x64 -t

This sends test messages to your Slack channel and email. Check that alerts arrive with the correct formatting and routing. If you defined multiple groups, each group should receive its mapped alerts.

For ongoing monitoring, watch the journal:

journalctl -u bgpalerter --since "1 hour ago" --no-pager

How does BGPalerter compare to alternatives?

BGPalerter is not the only BGP monitoring option. Here is a quick comparison:

Tool Type Best for
BGPalerter Self-hosted, open source Single AS, prefix monitoring, real-time alerts
ARTEMIS Self-hosted, open source Large networks, custom detection modules, research
Cloudflare Radar SaaS Quick lookup, no self-hosting, limited alerting
BGPStream Library/SaaS Programmatic analysis, historical data research
bgp.tools SaaS Visual exploration, community data, quick checks

BGPalerter fits the self-hosted single-AS use case well. It requires no router integration and runs on a small VPS. ARTEMIS is more powerful but significantly more complex to deploy.

For defense in depth, combine BGPalerter with RPKI ROA deployment RPKI ROA Setup for BGP: Create ROAs, Validate Routes in BIRD2 and FRR and proper route filtering BGP Route Filtering: Prefix Lists, AS-Path Filters, Bogon Rejection, and GTSM on your BGP sessions.

Something went wrong?

BGPalerter exits immediately: Check journalctl -u bgpalerter -e. Common causes: malformed YAML in config.yml or prefixes.yml. Validate with python3 -c "import yaml; yaml.safe_load(open('config.yml'))".

No data from RIPE RIS: Your firewall must allow outbound connections to ris-live.ripe.net on port 80 (WebSocket). If you are behind a restrictive proxy, use the wss:// URL on port 443 instead. Update the connector URL in config.yml accordingly.

Alerts not arriving (email): Run with -t to isolate. Check SMTP credentials in config.yml. Verify the sender address is allowed by your mail server (SPF, authentication). Check journalctl -u bgpalerter for SMTP error messages.

Alerts not arriving (Slack): Verify the webhook URL is valid. Slack deactivates webhooks for unused apps. Test the webhook directly: curl -X POST -H 'Content-type: application/json' --data '{"text":"test"}' "https://hooks.slack.com/services/T00/B00/xxxx".

High memory usage: Large prefix lists consume more memory. If you monitor many ASNs, consider increasing swap or splitting into multiple BGPalerter instances with separate prefix files.

Service fails to restart: RestartSec=30s in the unit file adds a 30-second delay between restart attempts. For persistent failures, check the exit code in systemctl status bgpalerter.


Copyright 2026 Virtua.Cloud. All rights reserved. This content is original work by the Virtua.Cloud team. Reproduction, republication, or redistribution without written permission is prohibited.

Ready to try it yourself?

Deploy your own server in seconds. Linux, Windows, or FreeBSD.

See VPS Plans