A lightweight, self-hosted uptime monitoring engine built with Rust and React.
Monitor HTTP, TCP, DNS, PostgreSQL, MySQL, Redis, and Docker services in real time.
- Features
- Architecture
- Tech Stack
- Getting Started
- Configuration
- API Reference
- Alerting Channels
- Security
- Development
- Testing
- License
- HTTP/HTTPS - Monitor endpoints with full request configuration: methods (GET, POST, PUT, DELETE, PATCH, HEAD), custom headers, JSON request bodies, and accepted status code ranges
- TCP - Verify port reachability on any host with configurable timeouts
- DNS - Resolve and validate A, AAAA, MX, CNAME, and TXT records against expected values with optional custom nameservers
- PostgreSQL - Ping and validate database connectivity with encrypted connection strings
- MySQL - Ping and validate database connectivity with encrypted connection strings
- Redis - Ping and validate database connectivity with encrypted connection strings
- Docker - Monitor Docker container health through a local Docker API proxy
- Automatic SSL certificate expiry tracking for all HTTPS endpoints
- Alerts at 14-day and 7-day thresholds with range-based tolerance for scheduler drift
- Daily background worker scans all HTTPS endpoints for upcoming expirations
- Server-Sent Events (SSE) endpoint streams status transitions (
UP,DOWN,SSL_EXPIRING_*) to the frontend in real time - Broadcast channel architecture ensures zero message loss between polling engine and alerting listeners
- WhatsApp - Meta Cloud API template messages
- Twilio - Voice call alerts via TwiML webhooks
- Slack - Incoming webhook integration
- Discord - Incoming webhook integration
- SMTP - Email alerts via configurable SMTP transport
- Generic Webhooks - Custom HTTP methods, headers, and body templates with variable interpolation (
{status},{monitorUrl},{monitorName},{errorMessage})
- Per-endpoint configurable cooldown timer (
throttle_seconds, default 900s) - Cooldown is bypassed for
UPresolution events to ensure recovery notifications always arrive - Prevents alert storms during intermittent connectivity issues
- AES-256-GCM encryption for database connection strings at rest
- Environment-variable-managed 32-byte hex encryption key
- No hardcoded keys or fallback credentials in the codebase
- Background cleanup worker runs daily with configurable retention period (default 30 days)
- Automatic pruning of old
ping_metricsandstatus_alert_logsrecords - Idempotent cleanup with duplicate-deletion safety
- Monitor List - View all endpoints with live status indicators, response times, and failure counts
- Monitor Details - Per-endpoint latency charts, incident history, and configuration editing
- Integrations Page - Configure all alerting channels from a unified settings panel
- Register/Edit Modal - Type-aware form with Zod schema validation that adapts fields based on monitor type
- Login & Auth - Session-based authentication with API key middleware
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β React Frontend β
β Dashboard β Monitor Details β Integrations β Login β
β β SSE β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Axum API Server β
β CRUD Endpoints β SSE Stream β Auth Middleware β Settings β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Background Workers β
β PollingScheduler β SSL Expiry Worker β Cleanup Worker β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Alerting Pipeline β
β StatusEvent β Throttle Check β Multi-Channel Dispatch β
β (WhatsApp, Twilio, Slack, Discord, SMTP, Webhook) β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β SQLite (WAL Mode) β
β endpoints β ping_metrics β status_alert_logs β settings β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Key design principles:
- Stateless polling engine with database-driven configuration
- Broadcast channel for decoupled event distribution between polling, alerting, and SSE
- Encrypted secrets never leave the server boundary
- Frontend uses optimistic UI updates via SWR with SSE-driven cache invalidation
| Component | Technology |
|---|---|
| Language | Rust (2024 Edition) |
| Runtime | Tokio (async) |
| HTTP Framework | Axum 0.7 |
| Database | SQLite via SQLx (WAL mode) |
| Database Drivers | PostgreSQL, MySQL, Redis |
| Encryption | AES-256-GCM (aes-gcm) |
| TLS Parsing | x509-parser |
| DNS Resolution | Hickory Resolver |
| Lettre (SMTP) | |
| Serialization | Serde + serde_json |
| Component | Technology |
|---|---|
| Framework | React 19 |
| Language | TypeScript 6 |
| Build Tool | Vite 8 |
| Routing | React Router DOM 7 |
| State Management | Zustand 5 |
| Data Fetching | SWR 2 + Axios |
| Validation | Zod 4 |
| Linting | OxLint |
| Mocking | MSW (Mock Service Worker) |
- Rust 1.85+ (2024 Edition)
- Node.js 18+
- npm 9+
# Clone the repository
git clone https://github.com/Divyanshkumar62/uptime.git
cd uptime
# Set the encryption key (required - 64 hex characters / 32 bytes)
export ENCRYPTION_KEY_SECRET="deadbeef0123456789abcdef0123456789abcdef0123456789abcdef01234567"
# Set the admin API key (required)
export ADMIN_API_KEY="your-secure-admin-key"
# Build and run
cargo build --release
cargo run --releaseThe API server starts on port 8080 by default. Override with PORT env var.
cd frontend
# Install dependencies
npm install
# Start development server
npm run dev
# Build for production
npm run buildThe development server starts on port 5173 by default and proxies API requests to the backend.
| Variable | Required | Default | Description |
|---|---|---|---|
ENCRYPTION_KEY_SECRET |
Yes | - | 64-character hex string (32 bytes) used for AES-256-GCM encryption of database connection strings |
ADMIN_API_KEY |
Yes | - | API key for authenticating requests to the backend |
DATABASE_URL |
No | sqlite:uptime.sqlite |
Database connection URL (SQLite, PostgreSQL, or MySQL) |
PORT |
No | 8080 |
Port for the API server |
DOCKER_PROXY_URL |
No | http://localhost:2375 |
Docker daemon API endpoint for container monitoring |
Security note:
ENCRYPTION_KEY_SECRETmust be a valid 64-character hex string. The application will panic on startup if the key is missing, invalid, or the wrong length.
Each endpoint is configured with:
| Field | Description |
|---|---|
monitor_type |
HTTP, TCP, DNS, POSTGRES, MYSQL, REDIS, or DOCKER |
url |
Target host, IP, or URL |
interval_seconds |
Polling interval (15β3600 seconds) |
timeout_seconds |
Request timeout (1β10 seconds) |
consecutive_failure_threshold |
Number of consecutive failures before marking DOWN |
jitter_ratio |
Random delay skew (0.0β1.0) to avoid thundering herd |
throttle_seconds |
Minimum cooldown between repeated alerts (default 900) |
tags |
Optional array of string tags for grouping |
All endpoints require authentication via X-API-Key header or session cookie.
| Method | Path | Description |
|---|---|---|
POST |
/api/endpoints |
Create a new monitored endpoint |
GET |
/api/endpoints |
List all endpoints |
GET |
/api/endpoints/:id |
Get endpoint details |
PUT |
/api/endpoints/:id |
Update endpoint configuration |
DELETE |
/api/endpoints/:id |
Delete an endpoint |
GET |
/api/endpoints/:id/latency |
Get latency history (query: since_hours) |
GET |
/api/endpoints/:id/incidents |
Get incident/alert history |
GET |
/api/sse |
SSE stream for real-time status events |
GET |
/api/integrations |
Get alerting integration settings |
PUT |
/api/integrations |
Update alerting integration settings |
The /api/sse endpoint streams JSON events:
{
"endpoint_id": 1,
"url": "https://api.example.com/health",
"previous_status": "UP",
"new_status": "DOWN",
"consecutive_failures": 3,
"alerted_at": "2026-07-04T12:00:00Z",
"error_message": "Connection timed out"
}Status values: UP, DOWN, SSL_EXPIRING_14, SSL_EXPIRING_7
Configure any combination of alerting channels from the Integrations page or API:
| Channel | Configuration Fields |
|---|---|
| Token, Phone Number ID, To Number, Template Name | |
| Twilio | Account SID, Auth Token, From Number, To Number, Callback URL |
| Slack | Webhook URL |
| Discord | Webhook URL |
| SMTP | Host, Port, Username, Password, From Address, To Address |
| Webhook | URL, Method (GET/POST/PUT/PATCH), Custom Headers (JSON), Body Template |
{status} β "DOWN" / "UP" / "SSL_EXPIRING_14"
{monitorUrl} β "https://api.example.com/health"
{monitorName} β "Production API Health Check"
{errorMessage}β "Connection timed out after 10s"
- Encryption at rest: Database connection strings are encrypted with AES-256-GCM before storage. No plaintext credentials are persisted.
- No hardcoded secrets: The encryption key and admin API key are required environment variables. The application refuses to start without them.
- Error redaction: Database probe failures return generic error messages (
"Database connection or ping failed") to prevent credential leakage through alerting channels. - SSRF protection: Docker probe requests are restricted to a configurable proxy URL (default
http://localhost:2375), preventing arbitrary internal network scanning. - Session-based auth: Protected routes use session cookies with API key middleware.
uptime/
βββ src/
β βββ main.rs # Application entry point
β βββ api/
β β βββ mod.rs # Axum router and server setup
β β βββ auth.rs # API key and session authentication
β β βββ routes.rs # CRUD endpoints, latency, incidents, integrations
β β βββ sse.rs # Server-Sent Events stream
β βββ db/
β β βββ mod.rs # Database initialization and migrations
β β βββ models.rs # Data models (Endpoint, PingMetric, StatusAlertLog, IntegrationsSettings)
β β βββ repository.rs # Database queries and operations
β β βββ crypto.rs # AES-256-GCM encryption/decryption
β β βββ cleanup.rs # Background data retention worker
β βββ polling/
β β βββ mod.rs # Probe execution dispatch
β β βββ scheduler.rs # Polling scheduler with jitter
β β βββ worker.rs # Protocol-specific probes (HTTP, TCP, DNS, DB, Docker)
β β βββ ssl.rs # SSL certificate expiry checks
β βββ monitoring/
β β βββ mod.rs # Monitoring module
β β βββ evaluator.rs # Status evaluation and alert triggering
β β βββ latency.rs # P99 latency calculations
β βββ alerting/
β βββ mod.rs # Alert dispatch orchestrator with throttling
β βββ whatsapp.rs # Meta Cloud API integration
β βββ twilio.rs # Twilio voice call integration
β βββ slack.rs # Slack webhook integration
β βββ discord.rs # Discord webhook integration
β βββ smtp.rs # Email alert integration
β βββ webhook.rs # Generic webhook with template interpolation
βββ frontend/
β βββ src/
β β βββ App.tsx # Root component with routing
β β βββ main.tsx # Entry point
β β βββ pages/ # Dashboard, Login, Monitor Details, Integrations
β β βββ components/ # Shared UI components (Button, Input, Toggle, etc.)
β β βββ features/ # Feature-specific components
β β βββ hooks/ # Custom hooks (useEndpoints, useIncidents, useLatency)
β β βββ stores/ # Zustand stores (auth, search, SSE)
β β βββ lib/ # API client
β β βββ routes/ # Route guards and router config
β β βββ mocks/ # MSW handlers for development
β βββ package.json
β βββ vite.config.ts
βββ schemas/ # JSON schemas
βββ Cargo.toml # Rust dependencies
βββ .gitignore
# Backend tests
cargo test
# Frontend lint
cd frontend && npm run lint
# Frontend build check
cd frontend && npm run buildMIT
Built with Rust and React