Content
<div align="center">
<img src="docs/logo.svg" alt="Orveil" width="80" />
<h1>Orveil</h1>
<p>Unified monitoring dashboard with notifications via <a href="https://github.com/caronc/apprise/wiki">Apprise</a>.<br>Monitor your self-hosted services, get alerted on incidents, and send notifications to any channel.</p>
[](https://hub.docker.com/r/zlimteck/orveil)
[](https://github.com/zlimteck/orveil/actions/workflows/docker.yml)
[](LICENSE)
[](https://hub.docker.com/r/zlimteck/orveil)
</div>

## Table of contents
- [Features](#features)
- [Stack](#stack)
- [Quick start](#quick-start)
- [Available monitors](#available-monitors)
- [Alerts sent per monitor type](#alerts-sent-per-monitor-type)
- [Notifications (Apprise)](#notifications-apprise)
- [MCP Server](#mcp-server)
- [Orveil AI](#orveil-ai)
- [Environment variables](#environment-variables)
- [License](#license)
## Features
- **Unified dashboard** — status overview of all your services at a glance, grid or list view
- **23 monitor types** — HTTP/HTTPS, Ping/TCP, Port Forwarding, SSH, DNS, MySQL, Redis, Proxmox, Cloudflare, AdGuard DNS, AdGuard Home, Home Assistant, Portainer, Docker, Syncthing, Immich, HostMyServers, Ultra.cc, Heartbeat, Unraid, Speedtest Tracker, Jellyfin, Ollama
- **Public status page** — shareable `/status` page (no login required) with uptime bars, open incidents, and 90-day history per service; toggle visibility per service
- **Search & sort** — filter cards by name, sort by status / name / manual order
- **Drag & drop reordering** — manually reorder cards in grid view
- **Category grouping** — assign a category to each service to group cards on the dashboard
- **Incident tracking** — automatic incident open/close with duration history; P1–P4 severity (auto-assigned, manually overridable); failure reason displayed inline; incidents grouped by date
- **War room** — dedicated full-screen view of all active incidents sorted by severity, with auto-refresh every 30 s
- **Post-mortem reports** — attach a structured post-mortem (summary, root cause, impact, resolution, lessons learned) to any resolved incident
- **SLA tracking** — set a target uptime % per monitor; met/breached indicator displayed on the Stats page
- **Statistics** — 30-day global view: uptime per service with trend, SLA status, incident count, MTTR, MTTD, severity breakdown, notification log, incident heatmap by day/hour
- **Maintenance windows** — per-service maintenance mode, immediate or scheduled (date/time picker); presets 30 min to 8 h or custom duration; upcoming windows shown as a badge on the card — no alerts or incidents during the window
- **Adaptive polling** — when a service goes down, check interval drops automatically to 30 s (configurable) for near-instant recovery detection; reverts to the normal interval once the service is back up; Speedtest and Heartbeat monitors are excluded
- **Notification cooldown** — configurable minimum delay (in minutes) between repeated down alerts for the same service; prevents alert storms during flapping; recovery notifications always pass through
- **Monitor dependencies** — link a monitor to a parent; down alerts are suppressed when the parent is also down
- **Backup & restore** — export all monitors and settings as JSON; import on another instance (Settings page)
- **Status badges** — embeddable SVG badge per service (`/api/badge/:id`) with live status color; Markdown and HTML snippets available in the service detail modal
- **Metric graphs** — sparkline graphs on dashboard cards and in service detail; smooth Bézier curves, incident overlays, and user annotations pinned to the timeline
- **Apprise notifications** — Pushover, Telegram, Discord, Slack, email, and [100+ more](https://github.com/caronc/apprise/wiki)
- **Weekly report** — optional weekly Apprise summary (services in error, average uptime)
- **Manual notifications** — send a message to all channels directly from the UI
- **Proxy library** — save multiple named proxies (HTTP, HTTPS, SOCKS5, SSH tunnel); activate/deactivate any proxy as the global default in one click; assign a specific proxy per monitor; test each proxy from the UI; passwords and private keys encrypted at rest
- **Clone monitor** — duplicate any monitor with one click (opens in disabled state for safe editing before enabling)
- **Real-time toast notifications** — live in-app alerts when a monitor changes status (via SSE), with coloured toasts per status (error / warning / online)
- **Auto / light / dark theme** — follows system preference, persisted per browser
- **FR / EN interface** — language toggle synced to notification language (one setting controls both UI and alerts)
- **REST API** — full API with Bearer token auth, documented in-app
- **MCP server** — Model Context Protocol server exposing monitors, incidents, stats, annotations and uptime history to AI assistants (Claude Desktop, etc.) via Streamable HTTP and stdio transports
- **Orveil AI** — built-in AI assistant (powered by Anthropic Claude) answering questions about your monitors, incidents, and SLA directly from the dashboard; API key stored encrypted in the database; model selectable from live Anthropic catalogue
## Stack
| Layer | Tech |
|-------|------|
| Frontend | React 18 + Vite + Tailwind CSS |
| Backend | Node.js + Express |
| Database | MongoDB |
| Notifications | Apprise (self-hosted sidecar) |
| Deployment | Single Docker image (frontend + backend) |
| CI/CD | GitHub Actions → Docker Hub (amd64 + arm64) |
## Quick start
**Prerequisites:** Docker + Docker Compose
```bash
git clone https://github.com/zlimteck/orveil.git
cd orveil
cp .env.example .env
# Edit .env — change JWT_SECRET and ADMIN_PASSWORD before exposing publicly
docker compose up -d
```
| Service | URL |
|---------|-----|
| App (frontend + API) | http://localhost:3050 |
| Apprise API | http://localhost:8008 |
Default credentials: `admin` / `orveil`
## Available monitors
| Type | What it checks |
|------|----------------|
| **HTTP** | HTTP/HTTPS endpoint — status code or custom accepted codes list, keyword present/absent match, Bearer/Basic/custom auth, multiple methods (GET/POST/PUT…), SSL certificate expiry with issuer and exact date displayed on the card, response time threshold |
| **Ping** | ICMP ping or TCP port reachability — latency and packet loss |
| **DNS** | DNS record resolution (A, AAAA, CNAME, MX, TXT, NS) — optionally assert expected value |
| **MySQL** | Ping a MySQL/MariaDB server and retrieve version via `mysql2` |
| **Redis** | PING a Redis instance and retrieve version via `ioredis` |
| **SSH** | CPU / RAM via SSH (password or private key) |
| **Heartbeat** | Cron job / script monitor — alerts if no ping received within expected interval |
| **Docker** | Container count and status via Docker socket |
| **Proxmox** | Node CPU / RAM via API token |
| **Cloudflare** | Tunnel status and hostnames via API token |
| **AdGuard DNS** | DNS protection status and request stats via cloud API |
| **AdGuard Home** | Self-hosted DNS protection — blocked queries %, total queries, safebrowsing |
| **Portainer** | Container list per environment via API key |
| **Syncthing** | Synced folders and connected devices via API key |
| **Immich** | Photo / video count and disk usage via API key |
| **HMS (HostMyServers)** | VPS status and specs via API token |
| **Ultra.cc** | Seedbox storage and traffic via Stats API URL |
| **Unraid** | Array state, disk usage, CPU / RAM, temperature via GraphQL API |
| **Home Assistant** | Instance status, version, and selected entity states via Long-lived access token. Numeric entities (temperature, humidity, power…) can be graphed — non-numeric states (on/off, home/away) are displayed but not graphable |
| **Speedtest Tracker** | Latest speedtest result — download, upload, ping, jitter |
| **Jellyfin** | Active sessions, library counts (movies / series / songs), server version |
| **Ollama** | Running model list and server availability via Ollama API |
| **Port Forwarding** | TCP connect check to verify a forwarded port is reachable from outside (router/firewall NAT verification) |
## Alerts sent per monitor type
All monitor types send exactly **one alert when going down** and **one alert on recovery** — no repeat notifications while the service stays down. Incidents are opened on first alert and closed on recovery.
Additional type-specific alerts:
| Type | Extra alerts |
|------|-------------|
| **HTTP** | SSL expiry warning · SSL expired · Response time threshold exceeded |
| **SSH** | High CPU · High RAM · High disk usage |
| **Proxmox** | High CPU · High RAM |
| **Cloudflare** | Per-tunnel offline / restored |
| **AdGuard DNS** | Protection disabled / re-enabled |
| **AdGuard Home** | Protection disabled / re-enabled |
| **Syncthing** | Folder error · Device disconnected / reconnected |
| **Immich** | Critical disk usage |
| **HMS** | Per-VPS unreachable · High CPU · High memory |
| **Ultra.cc** | Low storage · Low traffic |
| **Unraid** | Array stopped · Disk error |
| **Home Assistant** | Entity becomes unavailable · Entity restored |
## Notifications (Apprise)
Go to **Settings** and add your Apprise URLs — one per line:
```
pover://UserKey@ApiToken/ # Pushover
tgram://BotToken/ChatID/ # Telegram
discord://WebhookID/WebhookToken/ # Discord
slack://TokenA/TokenB/TokenC/ # Slack
mailto://user:pass@gmail.com # Email
```
Full list: https://github.com/caronc/apprise/wiki
## MCP Server
Orveil exposes a [Model Context Protocol](https://modelcontextprotocol.io) server so AI assistants can query your monitoring data directly.
### Tools available
| Tool | Description |
|------|-------------|
| `list_monitors` | List all monitors with status, SLA target, category, maintenance state (filterable by status / category / enabled) |
| `get_monitor` | Full details + metrics + recent snapshot history for a specific monitor |
| `list_incidents` | Recent incidents with severity, duration, MTTR — filterable by open/resolved or monitor name |
| `get_stats_detailed` | Full statistics: MTTR, MTTD, uptime per monitor (30d), SLA compliance, incidents/day, severity breakdown |
| `list_annotations` | Manual event markers attached to monitors (with resolved monitor names) |
| `get_uptime` | Daily uptime history per monitor (up to 90 days) |
| `trigger_check` | Trigger an immediate check for a monitor |
Resources `orveil://monitors/{name}` are also available for direct URI access.
### Streamable HTTP (remote)
The MCP endpoint is available at `/api/mcp`. The API key is auto-generated on first start and visible in **Settings → Integrations → MCP Server**.
```json
{
"mcpServers": {
"orveil": {
"url": "http://your-server:3050/api/mcp",
"type": "streamable-http",
"headers": {
"Authorization": "Bearer <your-mcp-api-key>"
}
}
}
}
```
### stdio (local / Claude Desktop)
```json
{
"mcpServers": {
"orveil": {
"command": "node",
"args": ["/path/to/orveil/backend/mcp-stdio.js"],
"env": {
"MONGO_URI": "mongodb://orveil:orveil_pass@localhost:27017/orveil"
}
}
}
}
```
The same API key also works as a Bearer token on all `/api` REST endpoints.
## Orveil AI
Orveil embeds an AI assistant powered by [Anthropic Claude](https://www.anthropic.com) that can answer natural-language questions about your infrastructure directly from the dashboard.
**How it works:**
- A floating button appears in the bottom-right corner once an Anthropic API key is configured
- The assistant has access to your monitors, incidents, statistics, annotations, and SLA data via the same tools as the MCP server
- Conversations are scoped strictly to Orveil — the assistant will not answer unrelated questions
- Responses are given in the same language as the user (FR/EN auto-detected)
**Setup:**
1. Go to **Settings → Integrations → Orveil AI**
2. Enter your Anthropic API key (`sk-ant-...`)
3. Select the Claude model to use (loaded live from the Anthropic catalogue)
4. Save — the AI button appears immediately
The API key is encrypted at rest using AES-256-GCM (same as monitor credentials). It is never exposed to the frontend.
## Environment variables
| Variable | Default | Description |
|----------|---------|-------------|
| `MONGO_USER` | `orveil` | MongoDB username |
| `MONGO_PASS` | `orveil_pass` | MongoDB password |
| `JWT_SECRET` | `orveil-change-me-in-production` | JWT signing secret — **change this** |
| `ENCRYPTION_KEY` | *(none)* | AES-256-GCM key for encrypting sensitive monitor credentials at rest — **strongly recommended** |
| `ADMIN_USERNAME` | `admin` | Admin account username |
| `ADMIN_PASSWORD` | `orveil` | Admin account password — **change this** |
### Setting up encryption at rest
Generate a key and add it to your `.env`:
```bash
echo "ENCRYPTION_KEY=$(openssl rand -hex 32)" >> .env
```
When set, all sensitive monitor fields (API keys, tokens, passwords, private keys) **and proxy credentials** are encrypted in the database using AES-256-GCM before being stored. The encryption is transparent — credentials are decrypted automatically at runtime.
> **Note:** If you add `ENCRYPTION_KEY` to an existing deployment, credentials saved before that point remain in plaintext until you re-save each monitor. New monitors and any monitor you edit after setting the key will be encrypted automatically.
## License
[MIT](LICENSE)
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
No recommendations available