Usage¶
Starting the Application¶
Development Mode¶
Start both the monitoring agent and Django dashboard using honcho:
uvx honcho start
This will start:
The monitoring agent (executing checks)
The Django dashboard at http://localhost:8000
Production Mode¶
For production deployment, see the deployment section below.
Managing Checks¶
Creating Development Data¶
For development and testing, generate sample services and checks:
uv run src/django/manage.py create_devdata
This creates:
A “Development Server” service
A “Dashboard Check” monitoring http://localhost:8000/ (passes when server is running)
A “Failing Check” monitoring http://localhost:8000/non-existent-url/ (will fail)
To force adding data even if checks already exist:
uv run src/django/manage.py create_devdata --force
Creating Checks via the Dashboard¶
The NyxBoard web UI provides an intuitive way to create and manage health checks without writing JSON or using the CLI.
Check Type Selection¶
When creating a new check, click any “Add Check” or “Create Health Check” button to reveal a dropdown menu with available check types:
🌐 HTTP Check - Monitor web endpoint availability
📋 JSON HTTP Check - Monitor JSON API endpoints
🔍 DNS Check - Monitor DNS resolution and validate IPs
Select the check type to open the appropriate form.
Creating DNS Checks¶
DNS check forms are organized into logical sections:
Basic Information:
Name: Descriptive name for the check (e.g., “DNS - home.wersdoerfer.de from LAN”)
Service: Associate the check with a service
Check Interval: How often to run the check (in seconds)
Disabled: Toggle to temporarily disable the check
DNS Configuration:
Domain: The domain to query (e.g.,
home.wersdoerfer.deorexample.com)Expected IPs: One IP per line - check succeeds if DNS returns any of these IPs
Query Type: A (IPv4) or AAAA (IPv6) record type
Advanced Options (optional):
DNS Server: Specific DNS server to query (uses system default if empty)
Source IP: Source IP to bind for the query (for split-horizon DNS validation)
Timeout: Query timeout in seconds (default: 5.0)
Form-to-JSON Mapping¶
The dashboard form fields map directly to the DNS check JSON structure:
Form Field |
JSON Field |
Example |
|---|---|---|
Domain |
|
|
Expected IPs (one per line) |
|
|
Query Type |
|
|
DNS Server |
|
|
Source IP |
|
|
Timeout |
|
|
Example: Creating a split-horizon DNS check via the form:
Name: DNS - home from LAN
Domain: home.wersdoerfer.de
Expected IPs:
192.168.178.94
Query Type: A
DNS Server: 192.168.178.94
Source IP: 192.168.178.50
Results in this JSON:
{
"url": "home.wersdoerfer.de",
"data": {
"expected_ips": ["192.168.178.94"],
"query_type": "A",
"dns_server": "192.168.178.94",
"source_ip": "192.168.178.50"
}
}
Tip: For detailed DNS check examples and troubleshooting, see DNS Check Configuration Examples.
Using the CLI¶
The monitoring agent can be run directly with custom options:
uv run start-agent --db /path/to/database.sqlite
Options:
--db: Path to SQLite database file (required)--interval: Check polling interval in seconds (default: 5)--cleanup-interval: Seconds between result-cleanup runs (default: 3600)--retention-period: Seconds to retain historical results (default: 86400)--batch-size: Maximum results deleted per cleanup run (default: 1000)--disable-cleaner: Skip scheduling the results cleaner--log-level: Set the logging level (default: INFO)--enable-telegram: Enable Telegram notifications
Running the Django Dashboard¶
PYTHONUNBUFFERED=true uv run src/django/manage.py runserver 0.0.0.0:8000
Notifications¶
Telegram Notifications¶
To enable Telegram notifications:
Create a Telegram bot using BotFather and get the token
Find your chat ID using userinfobot
Set environment variables:
export TELEGRAM_BOT_TOKEN=your_bot_token export TELEGRAM_CHAT_ID=your_chat_id
Or set them in your
.envfile for automatic loading with honcho.
By default, Nyxmon persists the first warning/error sample but waits for 2
consecutive non-OK samples before sending Telegram notifications or creating
OpsGate tickets. Set NYXMON_NOTIFY_CONSECUTIVE_FAILURES=1 to restore immediate
first-failure alerts. While a failure persists, Nyxmon sends a reminder after
every 12 additional failing samples; tune that with
NYXMON_NOTIFY_REPEAT_FAILURES.
Checks are claimed with a fifteen-minute processing lease. If a worker or executor
disappears before storing a result, Nyxmon reclaims the check, emits an immediate
stale_processing_lease error, and schedules it again. Configure the lease with
NYXMON_PROCESSING_LEASE_SECONDS; keep it above the longest legitimate check
runtime. A legacy processing row without a timestamp first receives a complete
lease, preventing an immediate duplicate run while still guaranteeing recovery.
Nyxmon cannot forcibly cancel an executor that remains hung outside its worker;
use finite executor timeouts and keep the lease above the longest valid runtime.
Nyxmon derives a conservative minimum from enabled checks’ timeout and retry
configuration and extends an undersized lease with a warning. The largest
enabled-check estimate is used for the whole batch, so an unusually slow check
also lengthens recovery detection for faster checks. For custom check behavior,
set data.max_runtime_seconds to its maximum legitimate runtime. Derived
per-check values are capped at one hour; a deliberately longer recovery
window must be set globally with NYXMON_PROCESSING_LEASE_SECONDS. At the lease
budget plus a result persistence/notification allowance of one minute per
claimed check, the collector abandons waiting for the executor thread and resumes
lease recovery and alerting; with the default lease this is at most twenty minutes.
New executions remain paused while the wedged thread continues in the background.
Only one abandoned batch is
allowed at a time: stale leases continue to be released and alerted, while new
executions wait for that thread to exit instead of consuming the worker pool.
An hourly paused-collector reminder uses an isolated unit of work and bypasses
the per-check immediate-alert cooldown and check-level maintenance suppression;
disabling every member of the abandoned batch does not silence that process-level
warning. Failed reminder attempts use a one-minute retry backoff.
The reminder is recorded as collector_execution_paused, distinct from a
single check’s lease expiry, and does not alter the anchor check’s schedule or
ordinary immediate-alert cooldown.
The recovered check waits one normal check interval after the lease alert before
running again, avoiding an immediate retry pile-up. Results arriving from an
expired claim remain in history but cannot clear a newer run’s active lease.
They also cannot change that run’s notification streak or trigger an alert.
Claim and stale-recovery batches default to five checks and can be tuned with
NYXMON_CHECK_BATCH_SIZE (range 1–100). The collector runs once per second by
default, so fast checks can drain roughly five due checks per second; slow or
failing checks reduce that throughput. Keep the value low enough that its
worst-case serial notifier time fits the intended abandon deadline.
Notification streak and reminder counters are stored per check in an internal
table rather than derived from retained result history, so result cleanup cannot
cause an alert storm. The state does not live in the editable check JSON.
Immediate lease-expiry alerts do not advance the ordinary reminder counter and
are limited to one per continuously failing check per hour by default; a
successful sample resets that cooldown for the next incident. Tune it with
NYXMON_NOTIFY_IMMEDIATE_COOLDOWN_SECONDS.
Checks may suppress Telegram and OpsGate side effects during known maintenance by
adding data.notification_suppression. The check still runs and the result is
still stored; warning/error samples written during the window include
notification_suppressed metadata and do not count toward the consecutive
failure threshold.
Example:
{
"notification_suppression": {
"url": "http://host.example:9106/.well-known/os-apt-maintenance",
"timeout": 3.0,
"reason": "host_os_apt_maintenance",
"status_path": "$.last_status",
"active_statuses": ["running"],
"finished_epoch_path": "$.last_run_finished_epoch",
"active_for_seconds": 900,
"auth": {
"username": "nyxmon",
"password": "secret"
}
}
}
OpsGate Approval Workflow (Optional)¶
To have Nyxmon create OpsGate remediation tickets directly and append approval links to Telegram alerts, set:
export OPSGATE_SUBMIT_BASE_URL=http://studio.tailde2ec.ts.net:8711
export OPSGATE_SUBMIT_TOKEN=<opsgate_submit_token_nyxmon>
export OPSGATE_APPROVAL_BASE_URL=http://studio.tailde2ec.ts.net:8711
Creating Custom Notifiers¶
Implement the Notifier interface for custom notifications:
from nyxmon.adapters.notification import Notifier
class CustomNotifier(Notifier):
def notify_check_failed(self, check, result):
# Implement your notification logic
pass
def notify_service_status_changed(self, service, status):
# Implement your notification logic
pass
# In your setup code (modify bootstrap.py or cli.py):
my_notifier = CustomNotifier()
bus = bootstrap(notifier=my_notifier)
Deployment¶
NyxMon uses SQLite as its database backend by design - this avoids dependency on a database for monitoring the database itself.
Building the Package¶
uv build --sdist --wheel
Publishing the Package¶
uv publish --token pypi-your-token
Deployment Commands¶
NyxMon includes deployment commands for different environments:
deploy-staging: Deploy to staging environmentdeploy-production: Deploy to production environmentdeploy-macos: Deploy to macOS (uses launchd instead of systemd)remove-macos: Remove macOS deployment
See Configuration for deployment configuration details.