Skip to content

cagatayuresin/observer-lite

Repository files navigation

Observer Lite

Observer Lite

Lightweight, self-hosted uptime monitoring with email & Telegram alerts,
SSL certificate tracking, real-time dashboard, and a single Docker image.

Version 0.2.0 MIT License Test Coverage 80% Python 3.12 Vue 3 Docker Image on GHCR


Overview

Observer Lite is a self-hosted uptime monitoring tool built for simplicity and efficiency. It monitors up to 500+ endpoints simultaneously, tracks SSL certificate expiry, sends instant alerts via email and Telegram, and delivers a real-time dark-mode dashboard — all from a single Docker image with no external database required.

Think of it as a lighter, more flexible alternative to Uptime Kuma — with a built-in status code DSL, response body matching, API keys, audit logging, and configurable data retention.

Full documentation is available in docs/ and can be published with GitHub Pages at:

https://cagatayuresin.github.io/observer-lite/

Features

Category Details
Monitor Types HTTP GET / POST / HEAD, Ping (ICMP), SSL Certificate, Heartbeat
Status Code Matching Flexible DSL: 2xx, !5xx, 200|301, 2xx|!503
Body Matching contains, equals, not_equals against response body
SSL Monitoring Certificate validity + configurable expiry warning (default 30 days)
Alerting Email (SMTP) and Telegram with cooldown, retry logic, and recovery notifications
Incidents Automatic open/close lifecycle, acknowledgement, root cause tracking
Maintenance Windows Suppress alerts during planned downtime, optional cron repeat
Real-time Dashboard Server-Sent Events (SSE) push — no polling required
User Management Roles: superadmin, admin, viewer; forced password change on first login
API Keys obs_-prefixed keys, SHA-256 hashed storage, per-key last-used tracking
Audit Log Immutable record of all user actions
Import / Export JSON-based monitor configuration portability
Data Retention Configurable (default 90 days), auto-cleanup runs nightly
UI Dark mode by default, fully bundled — zero CDN dependencies

Quick Start

Docker Run

docker run -d \
  --name observer-lite \
  --restart unless-stopped \
  -p 3000:3000 \
  -v observer_data:/data \
  -e SECRET_KEY="$(openssl rand -hex 32)" \
  -e DATABASE_PATH="/data/observer.db" \
  -e DATABASE_URL="sqlite+aiosqlite:////data/observer.db" \
  ghcr.io/cagatayuresin/observer-lite:latest

Open http://localhost:3000 — log in with admin / admin and set a new password when prompted.


Docker Compose

services:
  observer-lite:
    image: ghcr.io/cagatayuresin/observer-lite:latest
    container_name: observer-lite
    restart: unless-stopped
    ports:
      - "3000:3000"
    volumes:
      - observer_data:/data
    environment:
      SECRET_KEY: "change-this-to-a-long-random-secret-key"
      DATABASE_PATH: "/data/observer.db"
      DATABASE_URL: "sqlite+aiosqlite:////data/observer.db"
      PORT: "3000"

volumes:
  observer_data:
docker compose up -d

Configuration

All configuration is provided through environment variables.

Variable Required Default Description
SECRET_KEY Yes change-me-… HMAC secret for JWT signing and credential encryption. Use a random 32+ byte value.
DATABASE_PATH No /data/observer.db Path to the SQLite database file.
DATABASE_URL No sqlite+aiosqlite:////data/observer.db Full SQLAlchemy async connection URL.
PORT No 3000 Port the application listens on.
DEBUG No false Enable debug logging (true / false).

Security: Never use the default SECRET_KEY in production. Generate one with openssl rand -hex 32.


First Login

  1. Navigate to http://your-host:3000
  2. Log in with username admin and password admin
  3. You will be immediately redirected to the password change screen
  4. Set a strong password — the account is then ready to use

Monitor Types

HTTP (GET / POST / HEAD)

Sends an outbound HTTP request and evaluates the response against your rules.

  • Status Code DSL — combine patterns with | (OR) and prefix ! to negate:

    Expression Matches
    2xx Any 200–299 response
    200 Exactly 200
    2xx|301 Any 2xx or exactly 301
    !5xx Anything except 5xx
    2xx|!503 Any 2xx, or anything that isn't 503
  • Body Matching — optionally assert the response body contains, equals, or not_equals a value.

Ping

Uses the system ping binary to check ICMP reachability. Works with hostnames and IP addresses.

SSL Certificate

Performs a TLS handshake and reports certificate validity and days remaining until expiry. An alert is sent when expiry is within the configured threshold (default: 30 days).

Heartbeat

A passive monitor — your service calls Observer Lite to signal it is alive. If no ping is received within check_interval + grace_seconds, the monitor goes down.

GET /api/heartbeat/{token}
POST /api/heartbeat/{token}

Notifications

Notification channels are configured per-monitor. Each channel can independently toggle alerts for down, recovery, and SSL expiry events.

Email (SMTP)

Configure via the Notification Channels page in the UI. Required fields: SMTP host, port, sender address, recipients list. TLS and STARTTLS are both supported. Passwords are stored with Fernet encryption (AES-128-CBC + HMAC-SHA256).

Telegram

Create a bot via @BotFather, then provide the bot_token and chat_id in the channel settings. A test notification can be sent from the UI before saving.


Architecture

observer-lite/
├── backend/          # Python 3.12 + FastAPI (async)
│   └── app/
│       ├── checkers/ # HTTP, Ping, SSL, Heartbeat probes
│       ├── routers/  # REST API endpoints
│       ├── scheduler/# APScheduler engine + per-monitor jobs
│       ├── services/ # Business logic (incidents, notifications, retention)
│       ├── sse/      # Server-Sent Events broadcaster
│       └── utils/    # Crypto, pagination
└── frontend/         # Vue 3 + Vite + Tailwind CSS + Pinia

Stack highlights:

  • Backend: FastAPI, SQLAlchemy 2.0 async, aiosqlite, APScheduler 3.x (SQLAlchemyJobStore), aiosmtplib, python-jose, bcrypt, slowapi
  • Frontend: Vue 3, Vite, Tailwind CSS, Pinia, uPlot (lightweight charts, ~40 KB)
  • Transport: Server-Sent Events for real-time updates (no WebSocket needed)
  • Packaging: Multi-stage Docker build — Node.js build + Python 3.12-slim runtime, single image

Important: The application must run with --workers 1. The APScheduler and SSE broadcaster are in-memory singletons; multiple workers would duplicate checks and miss events.


API

Interactive API documentation is available at /api/docs (Swagger UI) and /api/redoc (ReDoc) when the server is running.

Key endpoint groups:

POST  /api/auth/login | refresh | logout | change-password
GET   /api/auth/me

GET|POST|PUT|DELETE  /api/monitors/{id}
POST  /api/monitors/{id}/pause | resume | check-now
GET   /api/monitors/{id}/stats | history | incidents

GET|POST|PUT|DELETE  /api/channels    + POST /{id}/test
GET|POST|PUT|DELETE  /api/incidents   + POST /{id}/acknowledge
GET|POST|PUT|DELETE  /api/maintenance
GET|POST|DELETE      /api/api-keys
GET|PUT              /api/settings

GET   /api/sse/dashboard    (SSE stream)
GET   /api/audit-log
GET   /api/export/monitors  |  POST /api/import/monitors

Authentication is via JWT Bearer token or an obs_-prefixed API key.


Development

See CONTRIBUTING.md for the full development guide including local setup, coding standards, and PR process.

# Backend
cd backend
uv venv && uv pip install -e ".[dev]"
alembic upgrade head
uvicorn app.main:app --reload --workers 1

# Frontend (separate terminal)
cd frontend
npm install
npm run dev

# Tests
cd backend
pytest tests/ --cov=app -q

Docker Images

The GitHub Actions workflow publishes the single production image to GHCR. Successful CI runs on main update the moving latest and main tags. Versioned image tags are published only when pushing a matching v* Git tag, with the version read from the root VERSION file.

Moving tags:

ghcr.io/cagatayuresin/observer-lite:latest
ghcr.io/cagatayuresin/observer-lite:main

Release tags include:

ghcr.io/cagatayuresin/observer-lite:0.2.0
ghcr.io/cagatayuresin/observer-lite:v0.2.0
ghcr.io/cagatayuresin/observer-lite:0.2

When pushing a Git tag, use the v-prefixed form that matches VERSION, for example v0.2.0.


Security

Observer Lite is designed with security in mind:

  • Passwords hashed with bcrypt (cost 12)
  • JWT access tokens expire in 15 minutes; refresh tokens in 30 days
  • SMTP/Telegram credentials stored with Fernet symmetric encryption, key derived via PBKDF2
  • API key raw values shown once; only SHA-256 hash stored
  • Login endpoint rate-limited to 5 attempts / minute per IP via slowapi

Please report vulnerabilities privately — see SECURITY.md for the responsible disclosure process.


License

MIT © 2026 Çağatay Üresin

About

Lightweight, self-hosted uptime monitoring with HTTP, ping, SSL, heartbeat checks, incidents, maintenance windows, and email/Telegram alerts.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors