DomainMate is a domain and security monitoring tool. It checks WHOIS expiration dates, SSL certificate validity, DNS security records (SPF, DMARC), HTTP security headers, and IP reputation against common RBL blacklists.
- Getting Started Guide
- Configuration Reference
- Monitor Types
- Notification Setup
- Architecture Overview
- Troubleshooting
DomainMate checks each configured domain sequentially across five monitors:
- Domain Validity: WHOIS expiration tracking with parent domain detection for subdomains.
- SSL/TLS: Certificate expiration date and basic protocol check (TLS 1.0/1.1 detection where supported by the local OpenSSL build).
- DNS Security: Presence of SPF and DMARC records.
- Reputation: IP checked against common RBLs (Real-time Blackhole Lists) via standard DNS queries.
- Security Headers: HTTP response headers checked for HSTS, CSP, X-Frame-Options, X-Content-Type-Options, and server information disclosure.
DomainMate is built on Python 3.12. Checks run sequentially per domain.
- DNS Layer: Custom
RobustResolvertries a pool of public DNS servers (Cloudflare, Google, Quad9, OpenDNS) and falls back to DNS-over-HTTPS (Cloudflare) if all fail. - Reporting: Generates static, self-contained HTML reports with DataTables integration.
- Notification System: Sends alerts via GitHub Issues, GitLab Issues, Telegram, Microsoft Teams, Email, and generic Webhooks. A
NotificationManager(used separately from the CLI) adds deduplication and 24-hour cooldown.
- Python 3.12 or higher
- Docker (optional, for containerized execution)
A Makefile is provided for standardizing operations.
# Initialize virtual environment and install dependencies
make install
# Run the audit scan
make run# Build the container image
make docker-build
# Execute the container
make docker-runConfiguration is managed via config.yaml. Sensitive parameters can be overridden via Environment Variables for secure CI/CD integration.
domains:
- example.com
- monitor.io
monitors:
domain:
enabled: true
expiry_warning_days: 30
expiry_critical_days: 7
ssl:
enabled: true
expiry_warning_days: 30
expiry_critical_days: 7
dns:
enabled: true
required_records:
- spf
- dmarc
security:
enabled: true
blacklist:
enabled: true
reports:
output_dir: "reports"
retention_days: 30
# Optional: Notification settings in YAML (Secrets can also be in ENV)
notifications:
telegram:
bot_token: "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
chat_id: "-1001234567890"
# Optional: Dead Man's Switch (GET request on completion)
heartbeat_url: "https://uptime.example.com/api/push/..."
# Optional: JSON Report Upload (POST request with full audit data)
api_url: "https://dashboard.example.com/api/upload"The following environment variables takes precedence over file configuration:
| Variable | Description |
|---|---|
DOMAINMATE_CONFIG_FILE |
Path to valid configuration file (default: config.yaml) |
GITHUB_TOKEN |
GitHub Personal Access Token for issue creation |
GITHUB_REPO |
Target GitHub repository (user/repo) |
GITLAB_TOKEN |
GitLab Private Token |
GITLAB_PROJECT_ID |
GitLab Project ID |
TELEGRAM_BOT_TOKEN |
Telegram Bot API Token |
TELEGRAM_CHAT_ID |
Telegram Chat ID |
TEAMS_WEBHOOK_URL |
Microsoft Teams Connector URL |
GENERIC_WEBHOOK_URL |
Endpoint for JSON alert payloads |
EMAIL_SMTP_SERVER |
SMTP Server Hostname |
EMAIL_SMTP_PORT |
SMTP Port (default: 587) |
EMAIL_USER |
SMTP Username |
EMAIL_PASSWORD |
SMTP Password |
EMAIL_TO |
Recipient Email Address |
The repository includes a workflow in .github/workflows/main.yml configured to execute scans on a daily schedule (08:00 UTC) and publish reports as build artifacts.
If you do not want to expose your domains in a public config.yaml:
Simply create this repository as Private. Your config.yaml and Reports will remain secure and visible only to you. GitHub Pages can also be published privately (requires Enterprise) or you can rely on the Build Artifacts.
You can store your entire config.yaml content as a GitHub Secret.
- Go to Settings > Secrets and variables > Actions.
- Create a New Repository Secret named
DOMAINMATE_CONFIG_CONTENT. - Paste the full content of your
config.yamlthere. - Modify your workflow file (
.github/workflows/pages.yml) to inject it before running:
- name: Inject Secret Config
if: "${{ secrets.DOMAINMATE_CONFIG_CONTENT != '' }}"
run: echo "${{ secrets.DOMAINMATE_CONFIG_CONTENT }}" > config.yamlThe system can be invoked directly via the Command Line Interface:
python src/cli.py --config /path/to/config.yaml --notifyOptions:
--config: Path to the configuration file (overridden byDOMAINMATE_CONFIG_FILE).--notify: Enable dispatching of notifications to configured channels.--demo: Generate a report using mock data for demonstration purposes.
This software is released under the MIT License.
