Self-hosted uptime monitoring that fits in a single binary.
I got tired of paying for status-page SaaS tools that do one thing: show a green dot. Sentinel checks your sites, APIs, databases, and raw TCP ports — all from a dark dashboard you own and run anywhere. No account, no subscription, no data leaving your network.
Paste any URL into the bar at the top. Hit Check once for a quick one-off result, or + Monitor to add it to the board permanently. Hover a card and click ✕ to stop watching it. That's the whole workflow.
Behind the scenes, every target gets checked concurrently on a configurable interval. Each card shows live latency history as a sparkline, a row of green/red tick bars for the last ~30 minutes, current uptime %, and TLS certificate days remaining. When something flips from up to down (or recovers), the incident lands in the event feed and fires a webhook alert — simultaneously, to as many channels as you've configured.
Supported check types:
| URL format | How it's checked |
|---|---|
https://mysite.com |
HTTP GET — status code, latency, TLS cert expiry |
192.168.1.10:3000 or localhost:5000 |
Same, with http:// assumed |
tcp://host:22 |
Raw TCP dial — SSH, Redis, anything that listens on a port |
mysql://user:pass@host:3306/db |
Real MySQL connection + db.Ping() |
postgres://user:pass@host/db |
Real Postgres connection + db.Ping() |
Alert channels (configured from the 🔔 panel in the dashboard — no YAML needed): Slack · Microsoft Teams · Google Chat · Discord · any custom webhook
Requires Go 1.22+. No database, no Docker, no other services.
git clone https://github.com/sagargoswami2001/sentinel.git
cd sentinel
go run ./cmd/sentinel serveOpen http://localhost:8080.
To build a binary you can copy to a server:
# Linux (from any machine)
GOOS=linux GOARCH=amd64 go build -o sentinel ./cmd/sentinel
# Windows
go build -o sentinel.exe ./cmd/sentinel# Dashboard on :8080, checks every 30s
sentinel serve
# Tune the interval and port
sentinel serve --interval 10s --listen :9090
# One-shot check — prints a table, exits 1 if anything is down
# (useful in cron jobs or CI)
sentinel checkPress / on the dashboard to jump focus to the URL bar.
Targets added via the browser are saved back to the config file automatically, so they survive restarts. You can also manage configs/sentinel.yaml by hand:
defaults:
timeout_seconds: 10
expect_status: 200
targets:
- name: Production API
url: https://api.mysite.com/health
- name: Staging VM
url: http://10.0.0.5:8000
timeout_seconds: 3
- name: Auth service (returns 401 when healthy)
url: https://auth.internal.mysite.com
expect_status: 401
- name: SSH — build server
url: tcp://build-host:22
- name: Azure MySQL
url: mysql://sentinel:password@mydb.mysql.database.azure.com:3306/appOpen the 🔔 Notifications panel in the dashboard, pick a platform, paste the webhook URL, click Add. Send a test alert to confirm it works before you need it. Alerts fire on every up→down and down→up transition for every target on the board.
To keep webhook URLs out of committed YAML (recommended for public repos), use env vars instead:
SENTINEL_SLACK_WEBHOOK=https://hooks.slack.com/... sentinel serveWhere to get a webhook:
- Slack — api.slack.com/apps → Incoming Webhooks
- Teams — channel → ⋯ → Workflows → "Post to a channel when a webhook request is received"
- Google Chat — space settings → Apps & integrations → Webhooks
- Discord — channel → Edit → Integrations → Webhooks
Sentinel exposes a /metrics endpoint on the same port:
curl http://localhost:8080/metricssentinel_target_up{name="Production API",url="..."} 1
sentinel_target_latency_seconds{name="Production API",url="..."} 0.043
sentinel_target_cert_days_left{name="Production API",url="..."} 56
sentinel_checks_total{name="Production API",url="...",status="up"} 24
Add to your prometheus.yml:
scrape_configs:
- job_name: sentinel
static_configs:
- targets: ['localhost:8080']curl http://localhost:8080/api/status{
"last_run": "2026-08-06T14:30:00Z",
"statuses": [
{
"name": "Production API",
"url": "https://api.mysite.com/health",
"up": true,
"status_code": 200,
"latency_ms": 43,
"cert_days_left": 56
}
]
}- Push this repo to GitHub
- render.com → sign in with GitHub → New → Web Service → select the repo
- Render detects the Dockerfile automatically → pick Free → Deploy
Your dashboard is live at https://<app-name>.onrender.com in about two minutes. The free tier sleeps after 15 idle minutes — first visit takes ~30s to wake. For a permanent instance that's always on, Docker on any cheap VPS works well.
docker build -t sentinel .
docker run -d --name sentinel --restart unless-stopped \
-p 8080:8080 \
-v $(pwd)/configs/sentinel.yaml:/etc/sentinel/sentinel.yaml \
sentinelOr pull the image published automatically on every push to main:
docker run -d -p 8080:8080 \
-v $(pwd)/configs/sentinel.yaml:/etc/sentinel/sentinel.yaml \
ghcr.io/sagargoswami2001/sentinel:latestThe container reads the PORT environment variable, so it drops straight into Render, Railway, Fly.io, or any other PaaS without config changes.
sentinel/
├── cmd/sentinel/ # thin CLI entrypoint — flag parsing, nothing else
├── internal/
│ ├── checker/ # HTTP, TCP, MySQL, Postgres health checks
│ ├── config/ # YAML load + save, default merging
│ ├── metrics/ # Prometheus gauge and counter definitions
│ ├── notify/ # Slack, Teams, GChat, Discord, webhook senders
│ ├── report/ # colored terminal table for sentinel check
│ └── server/ # HTTP server, templates, CSS — all go:embed'd
└── configs/sentinel.yaml
MIT — do whatever you want with it.