Stop taking manual screenshots. Start automating your DevOps monitoring reports with a secure, Dockerized solution.
It's Monday morning. Your stakeholders need a summary of last week's system performance. You open Grafana, adjust the time range, hide the sidebar, take a screenshot, paste it into an email, and repeat the process for five different dashboards.
It's tedious, error-prone, and frankly, a waste of valuable engineering time.
If you're looking to automate this workflow without sacrificing security or flexibility, meet GrafMail.
GrafMail is an automated Grafana dashboard screenshot and delivery tool designed for DevOps teams. It captures PNG or PDF reports using a headless browser inside Docker and delivers them via SMTP email or SFTP. Whether you are running in a cloud-native environment or a strictly air-gapped on-prem setup, GrafMail has you covered.
Why GrafMail?
Existing screenshot tools often lack the flexibility required for enterprise environments. GrafMail was built to solve specific pain points:
- Dual Delivery Modes: Send reports directly via email (
SMTP_INTERNAL) or save them for external processing (FILE_ONLY). - Professional Formatting: HTML emails with inline screenshots (Content-ID) or merged PDF attachments.
- Docker-First: Runs in an isolated container with configurable resource limits (CPU/Memory).
- Air-Gapped Ready: Supports offline deployment via Docker image tarballs.
- Security Focused: Runs as a non-root user, supports SSH key authentication, and avoids committing secrets to Git.
How It Works
At its core, GrafMail is a Python orchestration engine powered by Playwright and Chromium.
- Configuration: You define your Grafana URL, credentials, and delivery preferences in a simple
.envfile. - Capture: The Docker container launches Chromium, logs into Grafana, and captures the dashboard viewport or specific panels.
- Processing: Images can be merged into a single PDF report automatically.
- Delivery: Depending on your mode, the tool either emails the report via SMTP or copies it to a remote server via SFTP (Paramiko).

(Above: A simplified view of the GrafMail workflow. The run_report.sh script orchestrates the Docker container, which handles capture and delivery.)
Key Features
1. Flexible Delivery Modes
You aren't locked into one method of distribution.
- SMTP_INTERNAL: The container sends the email itself. Perfect for simple cron jobs. Supports CC/BCC and enforces a 10MB attachment limit to prevent bounce-backs.
- FILE_ONLY: Screenshots are saved to a local directory. You can optionally configure the tool to push these files to a remote server via SFTP using SSH keys or password authentication.
2. PDF & Panel Support
Need a single document for management? Set SCREENSHOT_FORMAT=pdf. GrafMail captures individual panels and merges them into a single PDF report automatically. You can also target specific panel IDs instead of capturing the entire viewport.
3. Air-Gapped Deployment
Working in a secure environment without internet access? GrafMail supports a two-stage deployment:
- Build and save the Docker image (
docker save) on a connected machine. - Transfer the
.tarfile and run./run_report.sh --load-tar grafmail.taron the secure machine.
4. Robust Error Handling
Network blips happen. GrafMail includes built-in retry logic (CAPTURE_RETRY_COUNT), configurable timeouts, and spinners detection to ensure dashboards are fully loaded before capture.
Quick Start
Getting started takes less than 5 minutes.
1. Configure
Copy the example environment file and fill in your Grafana details:
cp .env.example .env
# Edit .env with your GRAFANA_URL, UID, and SMTP details
2. Build
Build the optimized Docker image (Python 3.11-slim + Chromium):
docker build -t grafmail:latest .
3. Run
Execute the runner script:
./run_report.sh
4. Automate
Add it to your crontab for regular reports:
# Every 30 minutes
*/30 * * * * /path/to/run_report.sh --env-file /path/to/.env >> /path/to/cron.log 2>&1
Security Best Practices
In DevOps, automation shouldn't come at the cost of security. GrafMail follows strict guidelines:
- Secret Management: Never commit
.envto Git. Use environment variables or mounted secrets. - SSH Hardening: When using remote copy, prefer SSH keys over passwords. Set
SSH_HOST_KEY_POLICY=rejectin production to prevent man-in-the-middle attacks. - TLS Enforcement: Use HTTPS for Grafana and TLS/SSL for SMTP connections.
Advanced Configuration
GrafMail is highly configurable via environment variables. Here are a few powerful options:
| Variable | Description |
|---|---|
GRAFANA_DASHBOARD_UID |
The unique ID from your dashboard URL. |
DELIVERY_MODE |
Choose SMTP_INTERNAL or FILE_ONLY. |
DOCKER_MEMORY |
Limit container memory (e.g., 1g). |
FILE_RETENTION_DAYS |
Auto-cleanup old reports (e.g., 7). |
NO_IMAGES_ACTION |
Decide what happens if capture fails (notify, skip, or fail). |
For a full list of configuration options, check the Configuration Reference.
Troubleshooting Common Issues
- SMTP Connection Refused: Check your firewall rules and ensure
SMTP_HOSTandSMTP_PORTare correct. EnableDEBUG_MODE=truefor verbose logs. - Container OOM Killed: Rendering dashboards can be memory-intensive. Increase
DOCKER_MEMORYin your.envfile (e.g., to2g). - SSH Host Key Errors: If using
FILE_ONLYwith Paramiko, ensure yourknown_hostsfile is mounted or setSSH_HOST_KEY_POLICY=warnfor development.
Conclusion
Manual reporting is a relic of the past. With GrafMail, you can ensure your stakeholders receive consistent, high-quality monitoring reports without lifting a finger. It's lightweight, secure, and designed to fit into modern DevOps pipelines.
Ready to automate your Grafana workflows?
- GitHub Repo: View on GitHub
- Documentation: Read the Docs
- License: MIT
Have you tried GrafMail? Share your feedback or contribute to the project on GitHub!
Tags: #DevOps #Grafana #Automation #Python #Docker #Monitoring #SRE #OpenSource
Top comments (0)