Skip to content

Notifications ​

MeshMonitor supports two notification methods: Web Push notifications for browsers/PWAs and Apprise for external notification services. Choose the method that works best for your needs, or use both!

4.0 — notifications are scoped

  • Per-user, per-source Apprise URLs — set on each source's Notifications tab; each user configures their own URLs for each source they subscribe to, so home-source alerts can go to your phone without spamming the warehouse-mesh Discord channel.
  • Security Digest Apprise URL — a single admin-set URL on the Security tab that fires the weak-key / duplicate-key digest, independent of any user's preferences.

Notifications

Overview ​

MeshMonitor provides flexible notification options to ensure you never miss important messages:

Web Push Notifications ​

Browser-based notifications using the Web Push API with VAPID authentication. Works on iOS 16.4+ (Safari), Android (Chrome/Edge/Firefox), and desktop browsers - all without requiring any Apple certificates or platform-specific configuration.

Key Features:

  • Cross-Platform: Works on iOS 16.4+, Android, and desktop browsers
  • Zero Configuration: VAPID keys auto-generate on first run
  • No Apple Certificates: Uses standard Web Push API
  • Background Notifications: Receive alerts even when app is closed
  • iOS-Compliant: Proper implementation prevents subscription cancellation

Apprise Notifications ​

External notification delivery via Apprise, supporting 100+ notification services including Discord, Slack, Telegram, Email, Microsoft Teams, and many more.

Key Features:

  • 100+ Services: Discord, Slack, Telegram, Email, SMS, and more
  • Bundled Integration: Apprise API included in MeshMonitor container
  • Flexible Delivery: Use multiple notification services simultaneously
  • Server-Side: Works without browser requirements
  • Persistent Configuration: URLs stored in persistent volume

Browser Support ​

PlatformBrowserVersionStatusNotes
iOSSafari16.4+✅ SupportedPWA install required
AndroidChromeLatest✅ SupportedWorks in browser or PWA
AndroidFirefoxLatest✅ SupportedWorks in browser or PWA
AndroidEdgeLatest✅ SupportedWorks in browser or PWA
DesktopChromeLatest✅ Supported
DesktopFirefoxLatest✅ Supported
DesktopEdgeLatest✅ Supported
DesktopSafari16+✅ Supported

Server Requirements ​

HTTPS Requirement ​

Push notifications require HTTPS in most scenarios:

DeploymentHTTPS Required?Notes
Production (public)✅ RequiredMust use valid SSL certificate
Production (internal)✅ RequiredSelf-signed certificates work for internal networks
Development (localhost)❌ OptionalWorks on http://localhost or http://127.0.0.1
iOS (any)✅ RequirediOS requires HTTPS for PWA and push notifications

HTTPS is Critical for iOS

iOS requires HTTPS for push notifications, even on internal networks. Use a self-signed certificate or reverse proxy with SSL for testing on iOS devices.

SSL/TLS Certificate Options ​

Best for internet-facing deployments:

bash
# Install Certbot
sudo apt install certbot python3-certbot-nginx

# Obtain certificate
sudo certbot --nginx -d meshmonitor.example.com

# Certificates auto-renew

Pros: Free, trusted by all browsers, automated renewal

Cons: Requires public DNS, 90-day validity

2. Self-Signed Certificates (Internal Networks) ​

For internal/testing deployments:

bash
# Generate self-signed certificate
openssl req -x509 -newkey rsa:4096 -nodes \
  -keyout key.pem \
  -out cert.pem \
  -days 365 \
  -subj "/CN=meshmonitor.local"

Pros: Free, works for internal networks, no external dependencies

Cons: Browser warnings, must manually trust on each device

Trusting Self-Signed Certificates

  • iOS: Settings → General → About → Certificate Trust Settings
  • Android: Settings → Security → Install certificate
  • Desktop: Browser will prompt to accept certificate

Use NGINX, Traefik, or Caddy to handle SSL:

nginx
server {
    listen 443 ssl http2;
    server_name meshmonitor.local;

    ssl_certificate /etc/ssl/certs/meshmonitor.crt;
    ssl_certificate_key /etc/ssl/private/meshmonitor.key;

    location / {
        proxy_pass http://meshmonitor:3001;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

See the Reverse Proxy guide for complete setup.

VAPID Configuration ​

VAPID (Voluntary Application Server Identification) keys are used to authenticate push notification requests.

MeshMonitor automatically generates and stores VAPID keys in the database on first run. No manual configuration needed!

Manual Configuration (Optional) ​

If you prefer to manage VAPID keys manually:

  1. Generate keys:

    bash
    node generate-vapid-keys.js
  2. Add to .env or docker-compose.yml:

    env
    VAPID_PUBLIC_KEY=your-public-key-here
    VAPID_PRIVATE_KEY=your-private-key-here
    VAPID_SUBJECT=mailto:admin@example.com
  3. Restart MeshMonitor

Environment Variables

The following environment variables are optional:

  • VAPID_PUBLIC_KEY - VAPID public key (auto-generated if not set)
  • VAPID_PRIVATE_KEY - VAPID private key (auto-generated if not set)
  • VAPID_SUBJECT - Contact email starting with mailto: (can be set via admin UI)

Docker Configuration ​

For Docker deployments, ensure you have HTTPS configured via reverse proxy:

yaml
services:
  meshmonitor:
    image: ghcr.io/yeraze/meshmonitor:latest
    container_name: meshmonitor
    environment:
      - MESHTASTIC_NODE_IP=192.168.1.100
      # VAPID keys auto-generate - no configuration needed!
    volumes:
      - meshmonitor-data:/data
    restart: unless-stopped

  nginx:
    image: nginx:alpine
    ports:
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./certs:/etc/ssl/certs:ro
    depends_on:
      - meshmonitor

Kubernetes Configuration ​

For Kubernetes, use cert-manager for automated certificate management:

yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: meshmonitor-tls
spec:
  secretName: meshmonitor-tls
  issuerRef:
    name: letsencrypt-prod
    kind: ClusterIssuer
  dnsNames:
  - meshmonitor.example.com

Client Setup ​

iOS Setup (Step-by-Step) ​

iOS requires the app to be installed as a PWA before notifications can work:

Step 1: Install MeshMonitor as PWA ​

  1. Open MeshMonitor in Safari (must be Safari, not Chrome or other browsers)
  2. Navigate to your MeshMonitor URL (must be HTTPS)
  3. Tap the Share button (square with arrow pointing up) at the bottom of the screen
  4. Scroll down and tap "Add to Home Screen"
  5. Tap "Add" in the top right corner

Only Safari Works for iOS PWA

PWA installation on iOS only works in Safari. Chrome, Firefox, and other browsers on iOS cannot install PWAs.

Step 2: Open from Home Screen ​

  1. Go to your home screen
  2. Tap the MeshMonitor icon (don't open Safari)
  3. The app should open in standalone mode (no Safari UI visible)

Verify Standalone Mode

You should NOT see the Safari address bar or navigation buttons. If you do, you're not in PWA mode and notifications won't work.

Step 3: Enable Notifications ​

  1. In MeshMonitor, navigate to Configuration → Notifications (in the sidebar)
  2. Verify all checkmarks are green under "Browser Support"
  3. Ensure "PWA Installed" shows ✅ Yes
  4. Click "🔔 Enable Notifications"
  5. When prompted, tap "Allow" to grant notification permission
  6. The app will automatically subscribe you to notifications
  7. You should see "✅ You are subscribed to push notifications!"

Step 4: Test Notifications (Optional) ​

  1. Have another user send a message on the mesh
  2. You should receive a notification even with the app closed
  3. Tap the notification to open MeshMonitor to that message

iOS Notification Permissions

If you deny permission, you must go to iOS Settings → MeshMonitor → Notifications to re-enable it. The app cannot re-request permission after denial.

Android Setup (Step-by-Step) ​

Android supports notifications both in the browser and as a PWA:

Option 1: Browser Notifications (Chrome/Edge/Firefox) ​

  1. Open MeshMonitor in your browser (HTTP or HTTPS both work for localhost)
  2. Navigate to Configuration → Notifications
  3. Click "🔔 Enable Notifications"
  4. When prompted, tap "Allow" to grant notification permission
  5. The app will automatically subscribe you
  6. You should see "✅ You are subscribed to push notifications!"
  1. Open MeshMonitor in Chrome/Edge
  2. Tap the ⋮ menu (three dots in top right)
  3. Tap "Install app" or "Add to Home screen"
  4. Tap "Install"
  5. Open the app from your home screen
  6. Follow the "Browser Notifications" steps above

PWA Benefits on Android

Installing as PWA provides:

  • Standalone app experience
  • Faster loading (offline support)
  • Better notification reliability
  • No browser address bar

Testing Notifications ​

  1. Have another user send a message
  2. Lock your screen or switch to another app
  3. You should receive a notification
  4. Tap notification to open MeshMonitor

Desktop Setup (Step-by-Step) ​

Desktop browsers support notifications without PWA installation:

Chrome/Edge/Brave ​

  1. Open MeshMonitor in your browser
  2. Navigate to Configuration → Notifications
  3. Click "🔔 Enable Notifications"
  4. When prompted, click "Allow" in the browser popup
  5. The app will automatically subscribe you
  6. You should see "✅ You are subscribed to push notifications!"

Firefox ​

  1. Open MeshMonitor in Firefox
  2. Navigate to Configuration → Notifications
  3. Click "🔔 Enable Notifications"
  4. Click "Allow" in the Firefox permission popup
  5. The app will automatically subscribe you
  6. You should see "✅ You are subscribed to push notifications!"

Safari (macOS) ​

  1. Open MeshMonitor in Safari 16+
  2. Navigate to Configuration → Notifications
  3. Click "🔔 Enable Notifications"
  4. Click "Allow" when Safari prompts for permission
  5. You'll be automatically subscribed

Desktop Notifications

Desktop notifications work even when the browser is minimized or in the background. The browser does NOT need to be in focus.

Administrator Configuration ​

Updating VAPID Contact Email ​

The VAPID subject (contact email) is sent with each push notification request:

  1. Go to Configuration → Notifications (admin only)
  2. Scroll to "VAPID Configuration"
  3. Update the "Contact Email" field (must start with mailto:)
  4. Click "Update Contact Email"

Example: mailto:admin@example.com

Viewing Subscription Status ​

Admins can see:

  • VAPID Status: Whether keys are configured
  • Active Subscriptions: Number of users subscribed to notifications
  • Public Key: First 50 characters of the VAPID public key

Testing Notifications ​

Admins can send test notifications:

  1. Go to Configuration → Notifications
  2. Scroll to "Test Notifications" section
  3. Click "🧪 Send Test Notification"
  4. Every browser you have subscribed receives a test notification

Only you receive the test

The test goes to your own subscriptions, on every source you subscribed a browser on. Other users are not notified. The button shows only when this browser is subscribed.

Apprise Notifications Setup ​

Apprise allows you to send notifications to 100+ external services including Discord, Slack, Telegram, Email, and more.

What is Apprise? ​

Apprise is a universal notification library that supports a vast array of notification services through a simple URL-based configuration. MeshMonitor bundles Apprise directly in the Docker container for easy setup.

Supported Services ​

Apprise supports 100+ notification services including:

  • Chat & Messaging: Discord, Slack, Microsoft Teams, Telegram, Matrix, Rocket.Chat
  • Email: SMTP, Gmail, SendGrid, Mailgun, Amazon SES
  • SMS: Twilio, MessageBird, Nexmo, Clickatell
  • Push Notifications: Pushover, Pushbullet, Pushsafer, Notify
  • Social Media: Twitter/X
  • Development Tools: GitHub, GitLab, JIRA
  • Home Automation: Home Assistant, MQTT
  • And many more...

See the full list of supported services in the Apprise documentation.

Enabling Apprise ​

  1. Navigate to Configuration → Notifications in MeshMonitor
  2. In the Notification Services section at the top, toggle "Apprise Notifications" to enabled (green border)
  3. Click "Save Preferences"
  4. The Apprise Configuration section will appear below

Configuring Notification URLs ​

Apprise uses URL-based configuration. Each service has a unique URL format:

Discord Example ​

discord://webhook_id/webhook_token

To get your Discord webhook URL:

  1. In Discord, go to Server Settings → Integrations → Webhooks
  2. Create a new webhook or edit an existing one
  3. Copy the webhook URL (e.g., https://discord.com/api/webhooks/123456789/abcdefg...)
  4. Convert to Apprise format: discord://123456789/abcdefg...

Slack Example ​

slack://token_a/token_b/token_c

Email Example ​

mailto://user:password@gmail.com

For Gmail, you'll need to use an App Password:

mailto://your-email@gmail.com:app-password@gmail.com

Telegram Example ​

tgram://bot_token/chat_id

Microsoft Teams Example ​

msteams://token_a/token_b/token_c

Adding Multiple Services ​

You can configure multiple notification services simultaneously. Simply add one URL per line in the Apprise Configuration textarea:

discord://webhook_id/webhook_token
slack://token_a/token_b/token_c
mailto://user:password@gmail.com
tgram://bot_token/chat_id

All configured services will receive notifications for new messages.

Testing Apprise Notifications ​

After configuring your URLs:

  1. Click "Save Configuration" to save your Apprise URLs
  2. Click "Send Test Notification" to verify the configuration works (admins only)
  3. You should receive test notifications on all configured services
  4. Send a test message in MeshMonitor to verify real notifications work

URL Format Reference ​

Each service has a specific URL format. Here are some common examples:

ServiceURL FormatNotes
Discorddiscord://webhook_id/webhook_tokenGet from Server Settings → Webhooks
Slackslack://token_a/token_b/token_cFrom Slack app configuration
Email (SMTP)mailto://user:pass@smtp.example.comStandard SMTP configuration
Gmailmailto://user:app-password@gmail.comRequires App Password
Telegramtgram://bot_token/chat_idGet from BotFather
Pushoverpover://user_key@tokenFrom Pushover account
Microsoft Teamsmsteams://token_a/token_b/token_cFrom Teams webhook

For complete URL format documentation for all services, see the Apprise Wiki.

Persistent Configuration ​

Apprise URLs are stored in the MeshMonitor database with the rest of your notification settings, per user and per source. This means your Apprise configuration will survive:

  • Container restarts
  • Container upgrades
  • System reboots

Security Considerations ​

Protect Your Notification URLs

Apprise URLs contain authentication tokens that allow sending notifications to your services. Keep these URLs secure:

  • Don't commit them to version control
  • Each user's URLs are stored with that user's own settings and are not shown to other users
  • Rotate tokens if compromised
  • Use read-only or limited-permission tokens when possible

Troubleshooting Apprise ​

URLs Not Saving ​

  • Check that you clicked "Save Configuration" after entering URLs
  • Check that you are on the source you meant to configure: URLs are saved per source
  • Check Docker logs for errors: docker logs meshmonitor

Notifications Not Receiving ​

  1. Verify Apprise is enabled in Notification Services section
  2. Click "Send Test Notification" (admins only) to verify URLs are correct
  3. Check Docker logs for error messages:
    bash
    docker logs meshmonitor | grep -i apprise
  4. Verify the URL format matches the service requirements
  5. Check that tokens/credentials are still valid

Connection Test Fails ​

  • Verify the URL format is correct for your service
  • Check that authentication tokens are valid and not expired
  • Ensure the container has network access to the notification service
  • For Discord/Slack, verify the webhook still exists

Muting Channels and DMs ​

You can silence notifications for a specific channel or direct message conversation without disabling notifications globally. Mutes are stored on the server, per source, and apply across all your devices and browsers. Muting a channel on one source does not mute it on another.

Muting a Channel ​

  1. Open the Channels tab
  2. Click the 🔔 icon next to the channel name in the channel header
  3. Select a mute duration from the dropdown:
    • Mute indefinitely — stays muted until you unmute it
    • Mute for 1 hour — automatically expires after 60 minutes
    • Mute for 1 week — automatically expires after 7 days
  4. The channel icon changes to 🔇 in both the header and the sidebar

Muting a DM Conversation ​

  1. Open a direct message thread
  2. Click the Actions ▼ menu at the top of the conversation
  3. Select a mute option (indefinitely, 1 hour, or 1 week)
  4. The DM entry in the sidebar shows a 🔇 indicator while muted

Unmuting ​

  • Channel: Click the 🔇 icon in the channel header and select Unmute
  • DM: Open the Actions ▼ menu and select Unmute

What Muting Affects ​

Muting a channel or DM suppresses:

  • Browser audio notification sounds
  • Web Push notifications sent to your browser/device
  • Apprise notifications (Discord, Slack, email, etc.) delivered by the server

Whitelist Overrides Mutes

If a message contains a keyword on your notification whitelist, it will still trigger a notification even if the channel is muted. Use the whitelist for high-priority terms (like your call sign) that should always break through.

Mute Expiry

Time-based mutes expire automatically — no server-side job runs. Expiry is checked at the moment each notification is evaluated, so a mute that expires while you are away is correctly lifted the next time a message arrives.

MeshCore Channels ​

A MeshCore channel has the same bell button, in the conversation toolbar of the MeshCore Channels view, with the same choices. MeshCore channel messages raise no push, Apprise or sound alert, so there the mute only hides unread marks: the dot on the channel row, its share of the header total, and the sidebar Channels dot.

Cross-Device Sync ​

Mute preferences are stored in your user account on the MeshMonitor server (in user_notification_preferences), with the settings of the source they belong to. They apply regardless of which browser or device you use to access MeshMonitor.

Notification Settings ​

Notification Services ​

Users can enable or disable notification services independently:

  • Web Push Notifications: Browser/PWA-based notifications
  • Apprise Notifications: External notification services (Discord, Slack, etc.)

Both services can be enabled simultaneously, and they share the same filtering preferences.

Settings Are Saved Per Source ​

Every setting on the Notifications tab is saved for the source you are looking at, and only that source: the Web Push and Apprise switches, Apprise URLs, enabled channels, keyword lists, the direct message, emoji, MQTT, new-node, traceroute, server-event and waypoint toggles, and the message format. Channel numbers and node IDs mean different things on each source, so one source never uses another's settings.

A source you have never saved settings for uses the built-in defaults. The tab shows a note saying so, and the first Save creates that source's own settings.

SettingBuilt-in default
Web PushOn (you still have to subscribe the browser on that source)
AppriseOff, no URLs
Enabled channelsNone
Direct messagesOn
Emoji reactionsOn
MQTT messagesOn
Newly found nodesOff
Successful traceroutesOff
Server eventsOff
Waypoint arrivalsOff, 10 km radius
Mentions (MeshCore)Off
Inactive node / low batteryOff (20 %, 3300 mV)
WhitelistEmpty
BlacklistEmpty
Message formatThe default template

So on a source you have not set up, you are notified of direct messages only, over Web Push, if this browser is subscribed on that source. Channel messages, new-node alerts and traceroute alerts are off until you turn them on and save.

Changed in 4.17

A source with no saved settings used to borrow the settings you saved for another source: its channel ticks, keywords, toggles and Apprise URLs. It now uses the defaults above. If you run several sources and only ever saved settings on one, open the Notifications tab on each of the others and save what you want there. In particular, Apprise is off on a source until you turn it on and add URLs for that source, and channel, new-node and traceroute alerts are off until you turn them on. The defaults also changed: new-node and traceroute alerts used to default to on, and the keyword lists used to start with Hi, Help and Test, Copy. Settings you already saved are not changed.

Three things are not per source:

  • Channel and DM mutes set before per-source mutes existed still apply on a Meshtastic source that has no settings of its own. They are copied into that source's settings on its first save.
  • Inactive node and low battery alerts use one watch list per user: the nodes you picked on any source's tab are watched wherever they appear, and the alert goes out through whichever of your sources has Web Push or Apprise set up.
  • Web Push for new nodes, traceroutes and server events goes only to browsers subscribed on the source the event came from, the same as message notifications.

Filtering Preferences ​

Notification filtering applies to both Web Push and Apprise notifications:

  • Whitelist: Keywords that always trigger notifications (highest priority)
  • Blacklist: Keywords that never trigger notifications (second priority)
  • Emoji Reactions: Enable/disable notifications for reactions: tapbacks and emoji-only messages (third priority)
  • Newly Found Nodes: Enable/disable notifications when new nodes are discovered
  • Successful Traceroutes: Enable/disable notifications for completed traceroute responses
  • Waypoint Arrivals: Enable/disable notifications when a waypoint arrives from the mesh nearby
  • Enabled Channels: Specific channels to receive notifications from
  • Direct Messages: Enable/disable direct message notifications

The filtering follows this priority order for message notifications:

  1. Whitelist → Always send notification if keyword matches
  2. Blacklist → Never send notification if keyword matches
  3. Emoji Reactions → Filter tapbacks and emoji-only messages if disabled
  4. Channel/DM Settings → Send only if channel is enabled or DM is enabled

Special Event Notifications (bypass message filtering):

  • Newly Found Nodes → Sent when a new node appears on the mesh (includes node name and hop count)
  • Successful Traceroutes → Sent when a traceroute completes (includes full forward and return route)
  • Waypoint Arrivals → Sent the first time a waypoint arrives from the mesh inside your radius (see below)

Emoji Reaction Filtering

When "Emoji Reactions" is disabled, notifications are suppressed for tapbacks (reactions sent with the protocol's reaction flag, whatever they contain) and for messages containing only emojis (e.g., "👍", "😀", "❤️"), keycap emoji such as "1️⃣" included. Typed messages that mix emojis with text still trigger notifications normally.

Special Event Notifications

New Node and Traceroute notifications bypass normal message filtering (whitelist/blacklist/channel settings) and are only sent if you have that specific preference enabled. These notifications help you stay informed about mesh network topology changes and connectivity testing without cluttering your message notifications.

Message Notification Format ​

You choose what a new-message notification says. Open a source's Notifications tab and find Message Notification Format: two templates, one for the title and one for the body, with a live preview underneath. Templates are saved per user and per source, so a template you set for one source never changes another source's notifications, or another user's.

Leave a field empty to use the default.

The default ​

TitleBody
Channel message · :
Direct message ·

So a channel message reads:

LongFast · Home Base
Alice Mobile: Anyone on the summit today?

The source name appears once. Earlier versions put it in a [Source] prefix on the title and again on the first line of the body, which left little room on a phone's lock screen for the sender and the text.

Tokens ​

Write a token as {{ name }}. Anything else in the template is shown as typed.

TokenShows
{{ sourceName }}Name of the source that heard the message
{{ channelName }}Channel name. Empty for a direct message
{{ senderName }}Sender's long name
{{ senderShortName }}Sender's short name (the long name when there is none)
{{ text }}The message text, cut to 100 characters
{{ serviceLabel }}Network type: Meshtastic, MeshCore, MQTT or Reticulum
{{ isDM }}DM for a direct message, empty otherwise

Examples:

Title templateBody templateResult
{{ channelName }}{{ senderShortName }}: {{ text }}LongFast / ALC: Anyone on the summit today?
{{ isDM }} {{ senderName }}{{ text }}DM Alice Mobile / Anyone on the summit today?
{{ serviceLabel }} · {{ sourceName }}{{ channelName }} · {{ senderName }}: {{ text }}Meshtastic · Home Base / LongFast · Alice Mobile: Anyone on the summit today?

Rules ​

  • One pair for channels and direct messages. Your templates apply to both. For a direct message {{ channelName }} is empty, and a separator left dangling beside an empty token (·, •, |, :, ,, -, /) is dropped, so {{ channelName }} · {{ sourceName }} reads Home Base for a DM, not · Home Base. The preview shows both cases.
  • Unknown tokens are rejected when you save. A typo such as {{ source_name }} is flagged under the field and the save fails with a message that names it. Only the seven tokens above are valid here; Automation tokens such as {{ trigger.text }} are not.
  • Limits. A title template can be 200 characters and a body template 500. The rendered title is cut at 150 characters and the body at 400. The title is one line; the body may have several.
  • Plain text only. < and > are not allowed in a template, and nothing in a notification is treated as markup.
  • A template that renders to nothing falls back to the default, so a notification is never blank.
  • Filters are not affected. Whitelist and blacklist keywords match the original message text, never the formatted notification. A template changes what a notification says, not whether it is sent.
  • Prefix with Node Name still works. With that option on, [YourNodeName] goes in front of the body after your template is rendered. It never goes in the title.

Templates apply to message notifications. Other alerts keep their own wording, and each of them also names the source once:

AlertWhere the source name is
New nodeBody ("… detected by Home Base")
Traceroute, low battery, inactive node, waypointStart of the body ([Home Base] …)
Server start, node connected / disconnectedEnd of the title (Node Disconnected · Home Base)
Security digestStart of the title ([Home Base] MeshMonitor Security Digest)

Waypoint Arrivals ​

Alerts you when someone places a waypoint near you. Configured per source, on that source's Notifications tab, beside the other alert toggles. Meshtastic only — MeshCore has no waypoint concept, so the block is hidden there.

Off by default. Turning it on reveals two settings:

  • Alert within — the radius, in kilometres. Default 10 km, roughly a LongFast neighbourhood. This is what keeps a busy mesh from alerting you about waypoints two counties away.
  • Measured from — a latitude and longitude. Leave both empty (the normal case) and the radius is measured from that source's own node, which follows it when the node is mobile. Fill them in when your server's node sits somewhere other than the area you care about.

Waypoint arrival settings on a source's Notifications tab

No reference point, no alerts

If you leave the coordinates empty and the source's node has never reported a position, nothing is sent. This is deliberate: the alternative would be treating "no centre" as "no radius", which alerts on every waypoint anywhere on the mesh.

You are alerted once per waypoint ​

Waypoints rebroadcast on a schedule, so the first alert is the only one. MeshMonitor records which waypoints it has told you about and stays silent on every rebroadcast of the same one.

That record is keyed on the waypoint's id, not its name or position — and that is what you want, because waypoints do not move. Someone who "moves" a waypoint actually creates a new one with a new id, and you are alerted about it, correctly, as a new waypoint. The record is cleared when a waypoint is deleted or expires, so an id that gets reused later alerts again.

The record lives in the database rather than in memory, so restarting the container does not re-alert you about everything in range.

What does not alert you ​

Only waypoints that arrive over the air trigger a notification. Waypoints you create or edit in MeshMonitor, and the periodic rebroadcasts MeshMonitor sends of your own waypoints, are silent — you already know about those.

Airtime ​

None. This feature transmits nothing; it reacts to packets that already arrived.

MeshCore Sources ​

MeshCore sources have their own Notifications tab, and the settings are tailored to what MeshCore actually supports. Because MeshCore and Meshtastic expose different capabilities, the notification options shown for a MeshCore source are a subset:

NotificationMeshCoreNotes
Low Battery✅MeshCore reports battery as a voltage (mV), so the threshold is in millivolts (default 3300 mV) rather than a 0–100 percentage.
Inactive Node✅Alerts when a monitored MeshCore node hasn't been heard within the configured window.
Newly Found Nodes✅Sent the first time a contact advertises (display name + device type: Companion / Repeater / Room Server).
Mentions✅Sent when a channel message or room post names this source's own node as @[Name]. Off by default. See below.
Server Events✅Source connect/disconnect/reconnect.
Web Push / Apprise / Monitored-node picker✅Delivery and node selection work the same as Meshtastic.
Direct Messages, Emoji Reactions, MQTT, Traceroutes, Waypoint arrivals, Channel selection, Keyword filtering, percentage battery threshold❌Hidden for MeshCore — these depend on Meshtastic-only protocol features or data.

Preferences are saved per source, so a MeshCore source and a Meshtastic source can have independent thresholds. The monitored-node watch list is the exception: nodes picked on any source's tab are watched together (see Settings Are Saved Per Source).

MeshCore Mentions ​

Turn on Mentions on a MeshCore source's Notifications tab to be alerted when someone names that source's node. MeshCore clients write a mention as @[Name], and a reply starts with @[Name]:, so a reply to you alerts too.

  • The whole name must match the node's current name, ignoring case. @[Bob] does not alert a node called Bobby. If you rename the node, old mentions of the previous name no longer match.
  • Channel messages and room posts are checked. Direct messages are not.
  • At most one alert per sender every 5 minutes, per source. Other senders still get through. The limit is stored, so a restart does not reset it.
  • Your own messages, and senders you have ignored or blocked, never alert.
  • The alert goes to users who have the option on for that source and can read its messages. Channel selection and keyword filters do not apply to it.
  • A MeshCore MQTT source has no node of its own, so it has nothing to mention.

Client-Side Settings (Web Push Only) ​

For Web Push notifications specifically:

  • Enable/Disable: Grant or revoke browser permission
  • Subscribe/Unsubscribe: Opt-in or opt-out of receiving notifications
  • Per-Device: Each device (phone, tablet, desktop) requires separate subscription

Browser Permissions

Notification permissions are controlled by the browser. If denied, you must reset permissions in browser settings:

  • Chrome: Click lock icon → Site settings → Notifications
  • Safari: Safari → Settings → Websites → Notifications
  • Firefox: Click lock icon → Permissions → Notifications

Server-Side Settings ​

Web Push:

  • No configuration required - VAPID keys auto-generate on first run
  • Optional: Update VAPID Contact Email via admin UI
  • Optional: Set manual VAPID keys via environment variables

Apprise:

  • Bundled Apprise API runs automatically in Docker container
  • Each user's Apprise URLs are stored in the database, per source
  • No environment variables required

One Notification When Several Sources Hear a Packet ​

With two or more sources on the same mesh, each source that hears a packet used to raise its own notification. MeshMonitor now sends one notification per packet to each recipient, however many sources heard it.

What counts as the same packet: the same sender, packet id and port number, heard again within 60 seconds of the first copy. The window is fixed; it is not a setting yet. A copy that arrives later than that is a new notification. So is a packet with a different id or port, so a node's text, position and node info stay apart.

This also covers MQTT: if a radio source and an MQTT source both deliver a packet, or a source hears its own packet come back through MQTT, you are alerted once.

Your per-source settings still decide. Nothing about the settings changed. Each source's copy is checked against your settings and permissions for that source, exactly as before. A copy that would not have notified you (channel off, muted, blacklisted, MQTT alerts off, no read permission, browser not subscribed on that source) does not count and never uses up the notification. The first copy that passes is the one you get.

Which sources are named: only sources whose copy passed your own checks. You never see the name of a source you cannot read.

What each delivery method does:

MethodFirst copyLater copies inside 60 s
Web PushSent at once, naming the source that heard it firstThe notification on screen is replaced, without a new sound or vibration, by one that lists every source: LongFast · Hilltop, Valley
AppriseSent at once, naming the source that heard it firstNot sent. Apprise cannot change a message it has delivered
Desktop appShown at once, naming the source that heard it firstNot shown. A native notification cannot be changed once shown

The first notification is never held back to wait for other sources.

Which events are covered:

EventDeduplicated across sources?
Channel messages and direct messages (Meshtastic radio and MQTT)Yes, by sender + packet id + port
New MeshCore deviceYes, by the device's public key
Waypoint alertsYes, by waypoint id
New Meshtastic nodeAlready one alert per node (first source to complete it), unchanged
Server events (start, node connect / disconnect)No. These are about a source, so you get one per source
Inactive node, low batteryNo. These are periodic checks per source, with their own cooldown
Traceroute resultsNo. A traceroute belongs to the source that ran it
Security digest, automation notificationsNo. A report and an explicit rule; neither is a packet

After a restart

The 60-second memory lives in the server's memory only. If the server restarts between two copies of one packet, you may get one extra notification for that packet.

Custom templates

When Web Push lists several sources, it re-renders the template you saved for the source that heard the packet first, with {{ sourceName }} set to the joined list. A template without {{ sourceName }} shows the same text for the update.

Troubleshooting ​

Notifications Not Working ​

Check Browser Support ​

  1. Go to Configuration → Notifications
  2. Verify all checkmarks under "Browser Support" are green:
    • ✅ Notifications API: Supported
    • ✅ Service Workers: Supported
    • ✅ Push API: Supported
    • ✅ Permission: Granted
    • ✅ Subscription: Subscribed

iOS-Specific Issues ​

Problem: "PWA Installed" shows ⚠️ No

Solution:

  1. Ensure you opened MeshMonitor in Safari (not Chrome)
  2. Add to Home Screen via Safari's Share button
  3. Open from the home screen icon (not Safari)

Problem: Notifications not appearing

Solution:

  1. Go to iOS Settings → MeshMonitor → Notifications
  2. Ensure "Allow Notifications" is ON
  3. Check notification settings (Lock Screen, Banner, etc.)

Problem: "Subscription Cancelled" message

Solution:

  • This shouldn't happen with MeshMonitor's iOS-compliant implementation
  • If it does, unsubscribe and re-subscribe in app
  • Check browser console for errors

Android-Specific Issues ​

Problem: Permission denied

Solution:

  1. Go to Android Settings → Apps → [Browser] → Notifications
  2. Enable notifications for the browser
  3. Return to MeshMonitor and try again

Problem: Not receiving notifications

Solution:

  1. Ensure browser is allowed to run in background
  2. Disable battery optimization for browser:
    • Settings → Battery → Battery optimization
    • Find browser, set to "Don't optimize"

Desktop-Specific Issues ​

Problem: Permission denied

Solution:

  • Chrome: chrome://settings/content/notifications
  • Firefox: Options → Privacy & Security → Permissions → Notifications
  • Safari: Safari → Settings → Websites → Notifications
  • Find MeshMonitor URL and set to "Allow"

Problem: Notifications not appearing when browser is closed

Solution:

  • Most desktop browsers require the browser to be running (can be minimized)
  • On Windows/Linux, check system notification settings
  • On macOS, check System Settings → Notifications

HTTPS/SSL Issues ​

Problem: "PWA cannot be installed" on iOS

Solution:

  • iOS requires HTTPS for PWA installation
  • Use valid SSL certificate or self-signed certificate
  • Trust the certificate in iOS settings if self-signed

Problem: Mixed content warnings

Solution:

  • Ensure ALL resources load over HTTPS
  • Check browser console for specific HTTP resource URLs
  • Update any hard-coded HTTP URLs to HTTPS

VAPID Configuration Issues ​

Problem: "VAPID public key not available"

Solution:

  1. Check server logs for VAPID key generation errors
  2. Ensure database is writable
  3. Restart MeshMonitor to trigger auto-generation
  4. Alternatively, manually set VAPID keys via environment variables

Problem: Push notifications fail to send

Solution:

  1. Check server logs for push notification errors
  2. Verify VAPID keys are configured correctly
  3. Ensure subscription endpoint is valid
  4. Check network connectivity from server to push service

How It Works ​

Architecture Overview ​

┌─────────────┐          ┌──────────────┐          ┌─────────────┐
│   Browser   │          │  MeshMonitor │          │ Push Service│
│             │          │    Server    │          │ (Browser)   │
└─────────────┘          └──────────────┘          └─────────────┘
       │                         │                         │
       │  1. Request Permission  │                         │
       │────────────────────────>│                         │
       │                         │                         │
       │  2. Subscribe with VAPID│                         │
       │────────────────────────>│                         │
       │                         │                         │
       │  3. Store Subscription  │                         │
       │                         │──┐                      │
       │                         │  │ Database             │
       │                         │<─┘                      │
       │                         │                         │
       │                         │  4. New Message Arrives │
       │                         │──┐                      │
       │                         │<─┘                      │
       │                         │                         │
       │                         │  5. Send Push           │
       │                         │────────────────────────>│
       │                         │                         │
       │  6. Receive Notification│                         │
       │<──────────────────────────────────────────────────│
       │                         │                         │
       │  7. Click Notification  │                         │
       │─────────────────────────────────────────>        │
       │         (Opens/Focuses App)                       │

Subscription Flow ​

  1. User clicks "Enable Notifications"
  2. Browser requests permission from user
  3. User grants permission
  4. Frontend subscribes with PushManager using VAPID public key
  5. Browser generates subscription (endpoint + keys)
  6. Frontend sends subscription to backend API
  7. Backend stores subscription in database
  8. User receives push notifications for new messages

Notification Flow ​

  1. New message arrives on Meshtastic node
  2. Backend processes and stores message
  3. Backend sends push via Web Push API to browser's push service
  4. Push service routes to user's browser
  5. Service Worker receives push event (even if app closed)
  6. Service Worker shows notification to user
  7. User sees notification on lock screen/notification center

iOS-Specific Handling ​

iOS Safari has strict requirements to prevent abuse:

  • event.waitUntil(): Must be used to keep service worker alive
  • Silent push detection: Sending 3+ silent pushes cancels subscription
  • PWA requirement: Only works when installed to home screen
  • User interaction: Permission must be requested via user action

MeshMonitor handles all of these requirements automatically with iOS-compliant service worker implementation.

Security & Privacy ​

VAPID Authentication ​

  • All push requests are authenticated with VAPID keys
  • Push services verify the request came from your server
  • Prevents unauthorized parties from sending notifications

User Control ​

  • Users must explicitly grant permission
  • Users must explicitly subscribe
  • Users can unsubscribe at any time
  • Each device requires separate subscription

Endpoint Security ​

  • Subscription endpoints are unique per user/device
  • Endpoints are stored securely in database
  • Expired subscriptions are automatically cleaned up

Privacy ​

  • Push payload only contains message preview (not full message)
  • No personal data stored in push subscription
  • User can revoke permission at any time in browser settings

API Reference ​

Subscribe to Push Notifications ​

http
POST /api/push/subscribe
Content-Type: application/json

{
  "subscription": {
    "endpoint": "https://push.service.com/...",
    "keys": {
      "p256dh": "base64-encoded-key",
      "auth": "base64-encoded-key"
    }
  },
  "sourceId": "your-source-id"
}

sourceId is required. A browser subscribes once per source, and needs messages:read on that source.

Unsubscribe from Push Notifications ​

http
POST /api/push/unsubscribe
Content-Type: application/json

{
  "endpoint": "https://push.service.com/...",
  "sourceId": "your-source-id"
}

This removes the subscription for that source only. The response carries remainingSources, the number of other sources the same browser is still subscribed on. POST /api/push/unsubscribe-all with only endpoint removes the browser from every source.

Get VAPID Public Key ​

http
GET /api/push/vapid-key

Response:
{
  "publicKey": "BFz...",
  "status": {
    "configured": true,
    "subscriptionCount": 5
  }
}

Send Test Notification (Admin Only) ​

http
POST /api/push/test
Content-Type: application/json

{}

Response:
{
  "success": true,
  "sent": 1,
  "failed": 0
}

The test goes to the calling admin's own subscriptions only.

Update VAPID Subject (Admin Only) ​

http
PUT /api/push/vapid-subject
Content-Type: application/json

{
  "subject": "mailto:admin@example.com"
}

Get VAPID Status ​

http
GET /api/push/status

Response:
{
  "configured": true,
  "publicKey": "BFz...",
  "subject": "mailto:admin@example.com",
  "subscriptionCount": 5
}

References ​