Website Monitoring Automation
An asynchronous, production-grade monitoring platform that continuously watches websites, APIs, SSL certificates, DNS records, TCP ports and network reachability — then records history, raises de-duplicated alerts, and serves a live dashboard, REST API and Prometheus metrics.
Built for Windows, Linux and macOS with security first: every outbound request passes an SSRF guard (scheme allow-list, private-IP blocking, per-hop redirect validation), and secrets never touch the logs.
Features
| Area | What it does |
|---|---|
| 🌐 Availability | HTTP status, response time, expected/forbidden keywords, redirect tracking, security-header hygiene |
| 🔐 TLS/SSL | Certificate issuer, validity window, expiry countdown with early warning |
| 🧭 DNS | Resolves A/AAAA/MX/TXT/NS (custom resolvers) and detects record changes |
| 🔌 Ports | Concurrent TCP reachability with per-port latency |
| 📡 Network | ICMP ping (packet loss / latency) |
| 🧩 API | JSON validation via dotted json_path checks |
| 🕵️ Content | SHA-256 checksum + change detection |
| 🚨 Alerting | Telegram / Slack / Discord / e-mail / signed webhook — with flap-suppression and recovery notices |
| 🗃 History | SQLite store of checks, results, events, alerts + availability analytics |
| 📊 Reports | HTML, JSON, CSV, Markdown, PDF |
| 📈 Dashboard | FastAPI live dashboard, read-only REST API, Prometheus /metrics |
| 🔒 Security | SSRF guard, redirect re-validation, response-size caps, secret redaction |
Installation
Requires Python 3.10+.
git clone https://github.com/mojtaba-py-code/website-monitoring-automation.git
cd website-monitoring-automation
python -m venv .venv
# Windows: .venv\Scripts\activate
# Linux/mac: source .venv/bin/activate
pip install -e . # core
pip install -e ".[web,pdf,dev]" # + dashboard, PDF reports, dev tools
This installs the webmon command (and python -m webmon).
Quick start
# Ad-hoc checks — no config needed
webmon website example.com # HTTP + SSL
webmon ssl example.com # certificate expiry
webmon dns example.com # DNS records
webmon ports example.com 443 80 # TCP ports
webmon ping example.com # packet loss / latency
# Configured monitoring
cp config/config.example.yaml config/config.yaml # then edit your targets
webmon list # show configured targets
webmon check # run one cycle over all targets
webmon --json --html report # cycle + write reports
webmon run # continuous scheduled monitoring
webmon dashboard # live dashboard at http://127.0.0.1:8899
Command overview
webmon <command> [options]
check Run one monitoring cycle over configured targets
run Continuous scheduled monitoring (per-target intervals)
website Ad-hoc HTTP + SSL check of a URL/host
api Ad-hoc JSON API check
ssl Ad-hoc certificate check
dns Ad-hoc DNS resolution
ping Ad-hoc ICMP ping
ports Ad-hoc TCP port check
report Run a cycle and write reports
export Export monitoring history (json/csv)
list List configured targets
dashboard Launch the web dashboard + REST API + metrics
schedule Print cron / Task Scheduler equivalents
Global: --config --data-dir --timeout --interval --threads
--verbose --silent --json --csv --html
Full reference: docs/CLI.md.
Architecture
flowchart TD
CLI[cli.py] --> SVC[monitor.py MonitorService]
DASH[web/server.py FastAPI] --> SVC
SCHED[scheduler.py] --> SVC
SVC --> GUARD[security.py UrlGuard SSRF]
SVC --> DB[(database.py SQLite)]
SVC --> ALERT[alerting/ flap-suppression]
SVC --> CHECKS
subgraph CHECKS[Async probes]
HTTP[http] --- API[api] --- SSL[ssl] --- DNS[dns]
PORT[port] --- PING[ping] --- CONTENT[content]
end
CHECKS --> GUARD
SVC --> REP[reports.py]
SVC --> MET[metrics.py Prometheus]
A thin CLI / web / scheduler layer drives a single async MonitorService, which runs independent probes concurrently (bounded by a semaphore), persists results, detects state/content/DNS changes, and dispatches alerts. Everything is injected (config + guard), so each probe is unit-testable in isolation. See docs/ARCHITECTURE.md.
Security model
- SSRF guard — outbound requests are validated before connecting: scheme
allow-list, host block/allow-lists, and rejection of private / loopback /
link-local / reserved IPs (configurable). The cloud-metadata endpoint
169.254.169.254is block-listed by default, and the block-list is enforced against the resolved addresses too, so a hostname pointing at a blocked IP cannot slip through. - Redirect re-validation — redirects are followed manually and every hop is
re-checked, so an open redirect cannot bounce a probe onto an internal host.
Authorization/Cookieheaders are dropped on cross-host hops. - Response caps — bodies are read with a hard size limit to bound memory.
- Secret hygiene — tokens/passwords are referenced via
${ENV:VAR}and redacted from any log line; failed alert deliveries log only a status code / error type, never the URL or token. - Verified SMTP TLS — the e-mail channel passes its own SSL context, so the
certificate chain and hostname are checked (
smtplib's default STARTTLS context verifies neither), and credentials are never sent over cleartext. - Read-only web API — the dashboard never mutates state. When
web.api_tokenis set it gates every data route —/api/*,/metricsand the dashboard — compared in constant time; browsers exchange the token at/loginfor an HttpOnly, SameSite=Strict cookie holding an HMAC derived from it, so a stolen cookie cannot be replayed as an API credential. The server refuses to bind to a non-localhost interface unless a token is set.
Configuration (excerpt)
security:
block_private_networks: true # keep true for internet monitoring
blocklist_hosts: ["169.254.169.254"] # matched on the host AND its resolved IPs
targets:
- name: "Example Website"
url: "https://example.com"
checks: ["http", "ssl", "dns", "content"]
expected_status: [200]
expected_keywords: ["Example Domain"]
alerting:
enabled: true
failure_threshold: 2 # alert after N consecutive failures
channels:
telegram: { enabled: true, bot_token: "${ENV:TELEGRAM_BOT_TOKEN}", chat_id: "${ENV:TELEGRAM_CHAT_ID}" }
Full reference: docs/CONFIGURATION.md.
Dashboard, API & metrics
pip install -e ".[web]"
webmon dashboard --host 127.0.0.1 --port 8899
- Dashboard:
http://127.0.0.1:8899 - REST API:
/api/status,/api/target/{name},/api/events,/api/alerts - Prometheus:
/metrics(scrape into Grafana)
See docs/API.md and docs/DASHBOARD.md.
Docker
docker compose -f deploy/docker-compose.yml up --build
See docs/DEPLOYMENT.md.
Development
pip install -e ".[dev,web,pdf]"
ruff check src tests # lint + flake8-bandit security rules
mypy # strict type-check
pytest --cov # tests + coverage
Quality gates on every change: ruff clean (security rules included), mypy
strict clean, pytest green (126 tests, ~84% coverage), and no real network in
tests — HTTP is mocked with respx, and DNS/ICMP/TLS are monkeypatched. CI runs
all three on Linux, Windows and macOS across Python 3.10–3.12, plus a package
build, a Docker build, a pip-audit dependency scan and CodeQL analysis.
Use a virtual environment: running mypy against a global site-packages
directory can surface errors from unrelated third-party stubs.
See docs/DEVELOPER.md, CONTRIBUTING.md and, for common issues, docs/TROUBLESHOOTING.md.
Project
| Changelog | CHANGELOG.md |
| Contributing | CONTRIBUTING.md |
| Security policy & threat model | SECURITY.md |
| Code of conduct | CODE_OF_CONDUCT.md |
Found a security issue? Please report it privately — see SECURITY.md, not the public issue tracker.
License
MIT — see LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file website_monitoring_automation-1.0.0.tar.gz.
File metadata
- Download URL: website_monitoring_automation-1.0.0.tar.gz
- Upload date:
- Size: 64.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d4e02cca943161f369419d1f2b89cee8f0d4fecd089a51065f969c985dfc7aa1
|
|
| MD5 |
6591dcd5abce02e665b1f245e75154bb
|
|
| BLAKE2b-256 |
acd9fed0d1521feea54635544d11ce5ab0ac598e6b7128926abd45fff818979f
|
Provenance
The following attestation bundles were made for website_monitoring_automation-1.0.0.tar.gz:
Publisher:
publish.yml on mojtaba-py-code/website-monitoring-automation
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
website_monitoring_automation-1.0.0.tar.gz -
Subject digest:
d4e02cca943161f369419d1f2b89cee8f0d4fecd089a51065f969c985dfc7aa1 - Sigstore transparency entry: 2704415135
- Sigstore integration time:
-
Permalink:
mojtaba-py-code/website-monitoring-automation@5309cb38b8b9c4c69f4dbdc9401ac7163f562ca9 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/mojtaba-py-code
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@5309cb38b8b9c4c69f4dbdc9401ac7163f562ca9 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file website_monitoring_automation-1.0.0-py3-none-any.whl.
File metadata
- Download URL: website_monitoring_automation-1.0.0-py3-none-any.whl
- Upload date:
- Size: 60.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
735f7450d5db6acff97d3e0790459beca641d8e344d026eb443385aa0b68a3c0
|
|
| MD5 |
685d872bce782f59543cb3949e5628f1
|
|
| BLAKE2b-256 |
bfae9350f7d8d7304fde21ec1c36c53bf1418cd8e73b0600a5981f44ddbc57d8
|
Provenance
The following attestation bundles were made for website_monitoring_automation-1.0.0-py3-none-any.whl:
Publisher:
publish.yml on mojtaba-py-code/website-monitoring-automation
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
website_monitoring_automation-1.0.0-py3-none-any.whl -
Subject digest:
735f7450d5db6acff97d3e0790459beca641d8e344d026eb443385aa0b68a3c0 - Sigstore transparency entry: 2704415215
- Sigstore integration time:
-
Permalink:
mojtaba-py-code/website-monitoring-automation@5309cb38b8b9c4c69f4dbdc9401ac7163f562ca9 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/mojtaba-py-code
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@5309cb38b8b9c4c69f4dbdc9401ac7163f562ca9 -
Trigger Event:
workflow_dispatch
-
Statement type: