A self-hosted domain and SSL certificate monitoring application. Track registration expiry dates, SSL certificate validity, and receive email alerts when anything is about to expire.
- JavaScript 83.7%
- CSS 14.5%
- Dockerfile 1.1%
- HTML 0.7%
| backend | ||
| data | ||
| frontend | ||
| .dockerignore | ||
| docker-compose.yml | ||
| Dockerfile | ||
| Dockerfile.backend | ||
| README.md | ||
| screenshot1.png | ||
| screenshot2.png | ||
Domain Watcher 🔍
A self-hosted domain and SSL certificate monitoring application. Track registration expiry dates, SSL certificate validity, and receive email alerts when anything is about to expire.
Created with Claude.ai
Features
- WHOIS lookup — Registrar, creation, update, and expiry dates
- SSL inspection — CN, SANs, issuer, protocol version, validity dates
- Expiry highlighting — Red (≤15 days), Yellow (≤30 days)
- Bulk actions — Watch, unwatch, or forget multiple domains at once
- Email alerts — Configurable SMTP with customizable alert thresholds
- Auto-recheck — Daily cron at 6AM UTC rechecks watched domains nearing expiry
- UTC / Local time toggle — Switch date display in the top bar
- Persistent storage — SQLite database stored in a Docker volume
Screenshots
Quick Start
Requirements
- Docker and Docker Compose
Run
# Clone / copy this directory, then:
docker compose up -d
The app will be available at http://localhost:3001
To use a different port, edit docker-compose.yml:
ports:
- "8080:3001" # Change 8080 to your desired port
Build & run manually
docker build -t domain-watcher .
docker run -d \
--name domain-watcher \
-p 3001:3001 \
-v domain-watcher-data:/data \
--restart unless-stopped \
domain-watcher
Usage
Adding Domains
- Click + Add Domains in the nav bar
- Paste one or more domains (one per line, or comma/space separated)
- Click Lookup Domains — WHOIS and SSL info will be fetched
- Select the domains you want to keep and click Save or Save + Watch
Domains are not saved automatically — you must explicitly save them.
Dashboard
- The main table shows all saved domains with expiry status
- Click any row to see full details
- Use the bulk action dropdown + Apply button to watch/unwatch/delete domains
- Use the Show dropdown to control how many rows appear per page
Domain Detail
Click any domain to see:
- Full WHOIS registration info
- Complete SSL certificate details including all SANs
- Expiry warnings
- Buttons to Refresh, Watch/Unwatch, or Remove
Settings
Configure:
- Alert Days — How many days before expiry to send email alerts (default: 30)
- Recheck Days — How many days before expiry to trigger a data re-fetch (default: 30)
- SMTP — Server, port, credentials, from/to addresses
- Use Test Alerts Now to trigger the alert check immediately
Data Persistence
The SQLite database is stored at /data/domains.db inside the container, mounted as a named Docker volume (domain-watcher-data). Your data survives container restarts and updates.
To back up the database:
docker cp domain-watcher:/data/domains.db ./domains-backup.db
To restore:
docker cp ./domains-backup.db domain-watcher:/data/domains.db
Updating
docker compose down
docker compose build --no-cache
docker compose up -d
Your data in the named volume is preserved.
Architecture
┌─────────────────────────────────┐
│ Docker Container │
│ │
│ ┌─────────────┐ ┌──────────┐ │
│ │ React SPA │ │ SQLite │ │
│ │ (built) │ │ /data/ │ │
│ └──────┬──────┘ └────┬─────┘ │
│ │ │ │
│ ┌──────▼──────────────▼─────┐ │
│ │ Express.js API :3001 │ │
│ │ + node-cron (daily) │ │
│ └───────────────────────────┘ │
└─────────────────────────────────┘
- Backend: Node.js + Express, port 3001
- Frontend: React (served as static files by Express)
- Database: SQLite via better-sqlite3
- WHOIS: Raw TCP socket queries to TLD WHOIS servers
- SSL: Node.js
tlsmodule direct TLS handshake - Scheduler: node-cron (daily at 6AM UTC)
- Email: nodemailer
Environment Variables
| Variable | Default | Description |
|---|---|---|
PORT |
3001 |
HTTP port |
DATA_DIR |
/data |
SQLite database directory |
NODE_ENV |
production |
Node environment |
Notes
- WHOIS lookups may be rate-limited by some registries for frequent queries
- Up to 20 domains can be looked up in a single batch
- Domains without WHOIS servers for their TLD will return partial results with errors noted
- The SSL check connects directly to port 443; non-HTTPS domains will show SSL errors

