A lightweight Rust-based uptime monitoring daemon with Discord webhook notifications.
This tool monitors websites and APIs, sending alerts to Discord when they go down or come back up.
Your Discord notifications will look like this:
Note: Discord timestamps automatically convert to the viewer's local timezone!
All commands work both inside and outside Docker. When using Docker, prepend with docker compose exec lumio.
| Command | Description |
|---|---|
monitor add |
Add a new monitor target |
monitor remove <name> |
Remove a monitor target |
monitor list |
List all monitor targets |
monitor edit <name> |
Edit an existing monitor |
monitor stats |
Show resource usage statistics |
monitor test <name> <up|down> |
Send a test notification |
monitor daemon |
Run the monitoring daemon (starts automatically on bootup) |
monitor add \
--name example-website \
--endpoint https://example.com/ \
--status-range 2xx \
--interval 60 \
--webhook https://discord.com/api/webhooks/YOUR_WEBHOOK_URL| Flag | Required | Default | Description |
|---|---|---|---|
--name |
Yes | - | Unique identifier (auto-converted to lowercase with dashes) |
--endpoint |
Yes | - | The URL to check |
--status-range |
Yes | - | What HTTP codes are "good" (2xx, 3xx, or 4xx) |
--interval |
No | 60 | How often to check, in seconds (1-360) |
--webhook |
Yes | - | Your Discord webhook URL |
--display-name |
No | - | Pretty name for Discord (supports spaces!) |
--token |
No | - | Bearer token for authenticated APIs |
--role-id |
No | - | Discord role ID to ping on alerts |
--retries |
No | 3 | Failed checks before alerting |
--timeout |
No | 30 | Request timeout in seconds |
--expected-response |
No | - | Response body must contain this to be healthy |
monitor add \
--name example-api \
--display-name "Example API" \
--endpoint https://api.example.com \
--token "your-bearer-token" \
--role-id "1254982021261037568" \
--status-range 2xx \
--interval 60 \
--retries 3 \
--timeout 30 \
--expected-response "ok" \
--webhook https://discord.com/api/webhooks/YOUR_WEBHOOK_URL# List all monitors
monitor list
# Edit a monitor (change interval to 120 seconds)
monitor edit example-api --interval 120
# Remove a monitor
monitor remove example-api
# Show system resource usage
monitor stats
# Test Discord notifications (positional arguments, NOT flags)
monitor test example-api up # Test "operational" message
monitor test example-api down # Test "unavailable" message
# Get help
monitor help
monitor help addYou can deploy this application using the provided Docker Compose file or through Coolify.
Deploy Using Docker Compose
# Clone the codebase
git clone https://github.com/ShadowArcanist/lumio
cd lumio
docker compose up -d
# The daemon runs automatically and starts monitoring your configured endpointsDeploy Using Coolify
- Add a new resource in Coolify → "Docker Compose Empty."
- Paste the contents of the
coolify-compose.yamlfrom the repo into the input field. - Click "Deploy!"
Deploy Using Docker
# Build
docker build -t lumio .
# Run daemon
docker run -d \
-v $(pwd)/data:/data \
-e LOG_LEVEL=info \
lumio
# Run CLI command
docker run --rm \
-v $(pwd)/data:/data \
lumio listMonitors are stored in /data/config.json. Use the CLI commands (add, edit, remove) to manage monitors.
{
"monitors": {
"example-website": {
"name": "example-website",
"display_name": "Coolify Cloud API",
"endpoint": "https://example.com/api/v1/version",
"bearer_token": "your-secret-token",
"status_range": "2xx",
"interval": 60,
"retries": 3,
"timeout": 30,
"webhook_url": "https://discord.com/api/webhooks/...",
"role_id": "1254982021261037568",
"expected_response": "ok"
}
}| Field | Required | Type | Description |
|---|---|---|---|
name |
Yes | String | Unique ID (lowercase, no spaces, auto-normalized) |
display_name |
No | String | Pretty name for Discord (supports spaces and caps) |
endpoint |
Yes | String | URL to monitor |
bearer_token |
No | String | Optional authentication token |
status_range |
Yes | String | Acceptable HTTP codes (2xx, 3xx, or 4xx) |
interval |
No | Number | Check frequency in seconds (1-360, default: 60) |
retries |
No | Number | Consecutive failures before alerting (default: 3) |
timeout |
No | Number | Request timeout in seconds (default: 30) |
webhook_url |
Yes | String | Discord webhook URL |
role_id |
No | String | Discord role ID to ping (optional) |
expected_response |
No | String | Response body must contain this to be healthy |
Downtimes are stored in /data/downtime.json. This acts as a temporary database:
- Tracks when downtime started
- Stores failure reason
- Automatically removed after recovery notification is sent
- Persists if the app crashes (prevents duplicate alerts)
| Variable | Default | Description |
|---|---|---|
LOG_LEVEL |
info |
Log verbosity (error, warn, info, debug, trace) |
The app automatically creates missing config files now. If you still see this, ensure the /data directory has proper permissions.
- Verify your Discord webhook URL is correct
- Check that the webhook channel still exists
- Use
monitor testto verify the webhook works
- Check that
--status-rangematches your expected status codes - Verify
--retriesisn't too high - Use
docker compose logsto see what's happening
-
Start simple: Add a monitor with just
--name,--endpoint,--status-range,--interval, and--webhook. Add other options later. -
Use the CLI: All configuration changes should be made via
monitor add,monitor edit, andmonitor removecommands. Manual edits to config.json are not supported. -
Test first: After adding a monitor, run
monitor test <name> upto verify Discord is working. -
Use display names: The
--display-nameflag lets you use pretty names like "Production API" instead of "production-api". -
Check logs: If something isn't working, check the logs with
docker compose logs -f lumio. -
Bearer tokens: For APIs requiring authentication, use
--token "your-token". The app sends it asAuthorization: Bearer <token>. -
Response validation: Use
--expected-responseto ensure the response body contains expected content.
The Docker container includes a health check that runs every 30 seconds to ensure the daemon is running. Check container health with:
docker inspect --format='{{.State.Health.Status}}' lumio- This project was entirely created using AI, but the application has been thoroughly tested.
- This project was built primarily for my personal use, so I will not be merging pull requests or adding new features unless I need them myself. If you want to make changes or add features, feel free to fork this repository. It’s open-sourced so others can learn from it, use it as a base for their own projects, or even run the application as-is.
