Autonomous, ultra-lightweight browser smoke-testing daemon & CLI toolset in Rust.
Continuously monitors web apps, validates DOM assertions, captures failure screenshots, and consumes <30 MB RAM.
Install and run SiteWarden on any Linux server with a single command:
curl -fsSL https://raw.githubusercontent.com/Shantodotdev/sitewarden/master/install.sh | bashThe script sets up /opt/sitewarden, initializes your config.yaml, sets permissions, pulls the official container image, and starts the background daemon.
- ποΈ Hybrid Execution Engine:
- Pure-Rust Static Mode (
reqwest+scraper): Non-interactive tests run purely in-memory (~2 MB RAM, ~5ms latency, 0 browser processes). - On-Demand Headless Browser: Interactive tests (
click,type_text,wait_for_selector) launch headless Chromium on-demand and immediately release all memory upon completion.
- Pure-Rust Static Mode (
- π± Low VPS Resource Footprint: Idles at ~25β30 MB RSS, designed specifically for budget $5/mo (512MB RAM) cloud VPS nodes.
- π Interactive CLI Suite: Rich subcommands (
status,history,check,test,update,prune,doctor) for fast observability without sifting through logs. - π Zero-Downtime Hot-Reloading: Uses inotify filesystem watchers to detect changes to
config.yamland re-schedules cron cycles live in memory. - πΈ Failure Screenshots: Automatically captures full-page high-resolution screenshots on test failures and saves them to the host directory.
- π¨ Vibrant Terminal Tree Reporting: Laser-aligned Unicode columns, ANSI color-coded actions, and clean ASCII summary scorecards.
2026-09-01T06:04:18Z INFO π Starting Smoke Test Cycle β’ 2026-09-01 06:04:18 UTC [2 Suites β’ 2 Tests (8 Steps) β’ Concurrency: 2]
2026-09-01T06:04:19Z INFO βΆ Executing Suite: Example Domain Health Check (https://example.com) [Engine: Browser β’ 1 Tests β’ 4 Steps]
βΆ Test: Verify Homepage Heading and Body
βββ [1/4] π navigate β / [OK β’ 38ms]
βββ [2/4] β³ wait_for_selector β h1 [OK β’ 11ms]
βββ [3/4] π assert_text β 'h1' contains 'Example Domain' [OK β’ 2ms]
βββ [4/4] ποΈ assert_visible β p [OK β’ 7ms]
βββ β
Test Passed (61ms)
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β SiteWarden Test Cycle Report β
ββββββββββββββββββββββββββββββββββββββββ¬βββββββββββ¬βββββββββββββ¬βββββββββββ¬βββββββββββββββββ€
β Suite Name β Engine β Result β Tests β Duration β
ββββββββββββββββββββββββββββββββββββββββΌβββββββββββΌβββββββββββββΌβββββββββββΌβββββββββββββββββ€
β Example Domain Health Check β Browser β β
PASS β 1/1 (4) β 211ms β
β Wikipedia Navigation Test β Browser β β
PASS β 1/1 (4) β 962ms β
ββββββββββββββββββββββββββββββββββββββββ΄βββββββββββ΄βββββββββββββ΄βββββββββββ΄βββββββββββββββββ€
β β
All 2 Suites Passed (100%) β’ Total Cycle Time: 1.37s β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
When installed via install.sh, SiteWarden provides a global host CLI tool:
sitewarden [COMMAND] [OPTIONS]
Displays the overall daemon health, uptime, total runs, success rate, and screenshot disk usage:
sitewarden statusββββββββββββββββββββββββββ SiteWarden Service Status βββββββββββββββββββββββββββ
β Execution Mode: π’ Active Daemon (PID: 1482) β
β Uptime & Cron: Up 4d 12h (Cron: '0 0 6 * * *') β
β Version: v0.1.0 (Latest) β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Total Cycles: 148 runs (146 Passed, 2 Failed β’ 98.6% Success Rate) β
β Last Run: 2026-09-01 06:04:18 UTC (β
Passed, 1366ms) β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Monitored Suites: 2 configured (2 tests, 8 steps) β
β Screenshots: 2 artifacts (1.42 MB) in /opt/sitewarden/screenshots β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Executes a specific test suite or all test suites immediately on demand:
# Run a specific suite
sitewarden test "Example Domain Health Check"
# Run all configured suites
sitewarden testStreams real-time structured logs from the background daemon:
sitewarden logsDisplays a timeline of recent test cycles:
sitewarden history --limit 5ββββββββββββββββββββββββ¬βββββββββββββββββββββββββ¬βββββββββββββ¬βββββββββββββββ¬βββββββββββββ
β Timestamp (UTC) β Suites (Pass/Fail) β Result β Duration β Trigger β
ββββββββββββββββββββββββΌβββββββββββββββββββββββββΌβββββββββββββΌβββββββββββββββΌβββββββββββββ€
β 2026-09-01 06:04:18 β 2/2 (8 steps) β β
PASS β 1.37s β Cycle β
β 2026-09-01 00:00:00 β 2/2 (8 steps) β β
PASS β 1.12s β Cycle β
β 2026-08-31 18:00:00 β 1/2 (7 steps) β β FAIL β 2.45s β Cycle β
ββββββββββββββββββββββββ΄βββββββββββββββββββββββββ΄βββββββββββββ΄βββββββββββββββ΄βββββββββββββ
Pre-flight verification for config.yaml syntax, cron expressions, CSS selectors, and target endpoint reachability:
sitewarden checkπ Validating configuration at: "config.yaml"
β
YAML syntax and schema valid
β
Schedule expression valid (Cron: '0 0 6 * * *')
β
2 Suites loaded (8 Total Steps)
π Testing endpoint connectivity...
β
Reachable: https://example.com (HTTP 200 OK) β [Headless Browser]
β
Reachable: https://en.wikipedia.org (HTTP 200 OK) β [Headless Browser]
π Configuration is 100% valid and production-ready!
Convenient daemon lifecycle controls:
sitewarden restart
sitewarden stop
sitewarden startCleans up old failure screenshot artifacts from disk to prevent VPS storage leaks:
# Simulate pruning screenshots older than 7 days
sitewarden prune --days 7 --dry-run
# Delete screenshots older than 14 days
sitewarden prune --days 14Runs environment and diagnostic health checks (Chromium binary detection, screenshot directory permissions, network DNS):
sitewarden doctorSiteWarden is configured declaratively using YAML:
# Cron schedule expression (sec min hour day month weekday)
schedule: "0 0 6 * * *"
# Resource limits & concurrency
browser_concurrency: 2
timeout_seconds: 30
screenshot_dir: "/app/screenshots"
# Declarative Test Suites
suites:
- name: "Marketing Site Health Check"
base_url: "https://example.com"
tests:
- name: "Verify Homepage Heading"
steps:
- action: navigate
path: "/"
- action: assert_text
selector: "h1"
contains: "Example Domain"
- action: assert_visible
selector: "p"
- name: "User Portal Flow"
base_url: "https://app.example.com"
tests:
- name: "Verify Login Interaction"
steps:
- action: navigate
path: "/login"
- action: wait_for_selector
selector: "input#email"
timeout_ms: 5000
- action: type_text
selector: "input#email"
text: "smoke-test@example.com"
- action: click
selector: "button#submit"| Action | Parameters | Description |
|---|---|---|
navigate |
path: "/route" |
Navigates to a relative path or absolute URL |
assert_text |
selector: "h1", contains: "Text" |
Asserts DOM element contains text substring |
assert_visible |
selector: ".btn" |
Asserts DOM element exists and is visible |
wait_for_selector |
selector: "#modal", timeout_ms: 5000 |
Polls DOM until element appears |
click |
selector: "button#submit" |
Scrolls to element and triggers click event |
type_text |
selector: "input#name", text: "val" |
Focuses input and types characters |
If you prefer deploying manually with Docker Compose:
mkdir -p /opt/sitewarden/screenshots && cd /opt/sitewarden
sudo chown -R 1000:1000 screenshots
curl -fsSL https://raw.githubusercontent.com/Shantodotdev/sitewarden/master/docker-compose.yml -o docker-compose.yml
curl -fsSL https://raw.githubusercontent.com/Shantodotdev/sitewarden/master/config.example.yaml -o config.yaml
docker compose up -dTo compile and run SiteWarden natively:
# Clone repository
git clone https://github.com/Shantodotdev/sitewarden.git && cd sitewarden
# Run automated tests (29 unit & integration tests)
cargo test
# Run configuration pre-flight check
cargo run -- --config config.example.yaml check
# Run on-demand test cycle
cargo run -- --config config.example.yaml test
# Start background daemon
cargo run -- --config config.example.yaml daemonDual-licensed under either:
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT License (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.