How to Build a Zero-Cost Multi-Server Monitoring Dashboard on Cloudflare
A step-by-step guide to deploying a complete server monitoring system using Cloudflare Workers, D1, and Durable Objects for free. Covers backend setup, cross-platform agent installation, alert configuration, and real-time dashboard access.

How to Build a Zero-Cost Multi-Server Monitoring Dashboard on Cloudflare
Introduction: Why Build Your Own Monitor?
Juggling multiple servers scattered across different cloud providers can be a pain. SSH-ing into each one to check load averages and dig through logs gets old fast. And while commercial SaaS monitoring solutions exist, their monthly fees add up or their free tiers are severely restricted. The good news? You can deploy a fully functional, multi-server monitoring system using Cloudflare's free plan. It costs zero dollars, requires minimal maintenance, and supports real-time monitoring, offline alerts, and historical data tracking.
This tutorial uses CF-Server-Monitor, an open-source project with over 2,300 stars. It cleverly places the monitoring backend on Cloudflare Workers, runs a lightweight probe agent on your servers, and stores metrics in a D1 database. Durable Objects handle WebSocket broadcasting to the frontend. The entire setup requires no extra VPS—Cloudflare's free tier covers personal use perfectly.
By the end of this guide, you will be able to:
- Deploy the monitoring backend on Cloudflare (Worker + D1 + Durable Objects)
- Install the probe agent on Linux, Windows, macOS, NAS, and more
- Configure offline and resource utilization alerts (Telegram, WeCom, Lark/Feishu, Email, etc.)
- Open a web browser to view real-time dashboards, 7-day historical trends, multi-network latency, and a geographic map view
Prerequisites
Before starting, ensure you have:
- A Cloudflare account (takes minutes to register if you don't have one).
- A GitHub account (for forking the repository and configuring CI/CD).
- A target server (Linux VPS, NAS, Windows machine, or even a router, as long as it has public internet access).
- A terminal or SSH client to run commands on your target machines.
Why choose this architecture?
Traditional monitoring stacks (like Zabbix or Prometheus + Grafana) require self-hosting servers, managing databases, and maintaining collectors—overkill for personal use. CF-Server-Monitor leverages Cloudflare's edge computing: Workers handle the API and frontend rendering, D1 acts as a lightweight SQLite database, and Durable Objects manage WebSocket broadcasting. Your servers only need a tiny agent that periodically reports metrics to the Worker. All querying, alerting, and visualization are offloaded to Cloudflare. At a 60-second reporting interval, the free tier supports roughly 60 servers—more than enough for personal labs.
Most importantly, the agent reports data unidirectionally. There's no WebSSH or remote command execution channel, making it inherently more secure.
Quick Start: Deploy Backend & Install Agent
Step 1: Deploy the Monitoring Backend
We recommend using GitHub Actions for automatic deployment. This allows future updates to be deployed with a single Sync fork click in GitHub, eliminating manual Cloudflare console tweaks.
1. Fork the Repository
Visit the CF-Server-Monitor GitHub page and click Fork in the top-right corner to copy it to your account.
2. Create a Cloudflare D1 Database
- Log into the Cloudflare Dashboard. Navigate to Workers & Pages > D1 SQL Database.
- Click Create database and name it anything (e.g.,
server-monitor-db). - Once created, copy the Database ID (a UUID string).
3. Get Account ID & Create an API Token
- Go back to the Workers & Pages homepage. Your Account ID is visible on the right sidebar. Copy it.
- Navigate to API Tokens > Create Token. Select the Edit Cloudflare Workers template (which includes necessary Worker and D1 permissions). Define the scope, create the token, and copy it immediately. Cloudflare won't show it again.
4. Configure GitHub Secrets
In your forked repository, go to Settings > Secrets and variables > Actions. Add the following secrets:
| Secret | Description |
|---|---|
CF_API_TOKEN |
The Cloudflare API Token you just created |
CF_ACCOUNT_ID |
Your Cloudflare Account ID |
D1_DATABASE_ID |
The D1 Database UUID |
API_SECRET |
A strong, random password. This acts as both the Agent reporting key and the initial admin login password |
Generate a strong password with this one-liner:
bash
## Generate API_SECRET (used for Agent auth and initial admin password)
python3 -c "import secrets; print(secrets.token_urlsafe(32))"
5. Trigger Deployment
Navigate to the Actions tab in your repository. Click Run workflow, select the main branch, and run the Deploy to Cloudflare Workers workflow. Wait a few minutes for the green checkmark. Your monitoring backend is now live.
The Worker URL will follow this format: https://your-chosen-name.your-subdomain.workers.dev.
Step 2: Add Servers & Install the Agent
1. Log into the Admin Panel
Visit:
https://your-worker-domain/admin#/admin
The default username is admin, and the password is your API_SECRET. Immediately change the admin password in the backend after logging in to separate it from the API secret. Admin credentials can be changed independently without affecting agent reporting.
2. Add a Server
- Go to Server Management in the admin panel.
- Enter a server name (e.g., "Primary VPS").
- Click Add Server.
- Click the copy button to get the installation command for your target OS (Linux / Docker / Windows / macOS, etc.) and agent version.
3. Run the Installation Command
Paste the copied command into your target server. It automatically injects the Server ID, Worker URL, and Secret—no manual parameter tweaking required.
For Linux, the default one-liner looks like this:
bash
## Linux one-click installation (backend command auto-fills ID, URL, Secret)
curl -fsSL https://raw.githubusercontent.com/huilang-me/cfsm-agent/main/install.sh | sh
After installation, the agent runs as a cf-probe service, reporting metrics to your Worker every 60 seconds by default.
Non-Root Installation Tip: If your Linux system supports systemd --user (most modern distros do), select "Non-root installation" in the backend. Probe files will be placed in ~/.cf-probe/, minimizing the blast radius if compromised. To keep the service running after logging out:
bash
loginctl enable-linger your-username
For Docker environments, the backend generates a command like this:
bash
docker run -d --name cf-probe --restart=unless-stopped --network=host \
-v cf-probe-data:/data \
-e SERVER_ID=<ServerID> -e SECRET='<API_SECRET>' -e WORKER_URL=https://your-domain/update \
ghcr.io/huilang-me/cfsm-agent:latest
Once started, the agent dynamically pulls its reporting interval, ping targets, and network interface settings from the backend using the SERVER_ID. No extra flags needed.
Step 3: Configure Alert Notifications
Monitoring without alerts is pointless. CF-Server-Monitor supports multiple notification channels, configured via Global Settings > Notifications in the admin panel.
Using Bark (highly recommended for iOS users) as an example:
- Select the built-in channel.
- Paste your Bark URL into Bot Token (e.g.,
https://api.day.app/xxxxx/). - Click Send Test Notification to verify.
- Save after confirming receipt.
For email, select SMTP and fill in your mail server details. Note: Cloudflare permanently blocks outbound port 25. You must use 465 (implicit TLS) or 587 (STARTTLS). QQ/163 mail requires an SMTP authorization code, not your regular login password.
Supported alert types:
- Offline Alerts: Triggers when a node drops below the threshold, with an automatic recovery notification.
- Expiration Reminders: Daily alerts 1-7 days before server expiration.
- Resource Load Alerts: Custom rules for CPU, RAM, disk, and network bandwidth.
Real-World Scenario: Monitoring Dev & Prod Environments
Assume you manage three environments:
- Alibaba Cloud ECS (Mainland China)
- AWS EC2 (Singapore)
- Local Mac Mini (Home Network)
Add all three in the backend and run their respective install commands. Chinese mainland nodes may experience network jitter. To stabilize reporting, bind a custom domain to your Worker, or temporarily map it to an available Cloudflare CDN IP in /etc/hosts:
bash
echo <CF_CDN_IP> your-probe-domain | sudo tee -a /etc/hosts
Once installed, open the public dashboard (https://your-worker-domain/). You'll see:
- Real-time status for all servers (online/offline, CPU, RAM, network speed)
- Multi-network latency and packet loss (Telecom, Unicom, Mobile endpoints)
- 7-day historical trend charts to trace load spikes
- A geographic map view pinpointing each node
For customization, Appearance Settings in the backend allows custom backgrounds, CSS, and CSP whitelists. If third-party images fail to load, it's usually blocked by CSP. Add the image domain origin to the CSP static file whitelist and refresh.
Troubleshooting & Common Pitfalls
Deployment returns API_SECRET is required
The Worker environment variable wasn't set correctly. Go to Cloudflare Workers Variables and Secrets, delete the old value, and re-add API_SECRET. If stuck in a Cloudflare cache loop, change the value to something else, save, then change it back to force a redeploy.
Agent not reporting data
ping your-worker-domainfrom the server to verify connectivity.- Append
-debug=1to the install command to check system logs. Remove it and reinstall once fixed to prevent log bloating. - Mainland China servers: As mentioned, use a custom domain or
/etc/hostsCDN mapping.
Is the D1 free tier sufficient?
At a 60-second interval, the free tier supports ~60 servers. For larger fleets, increase the interval to 120 seconds to halve write operations. Frontend reads are optimized with caching and sampling, making it extremely difficult to hit free tier limits in practice.
Forgot the admin password
Access your Cloudflare D1 database, locate the setting table, and edit the password field in site_options. The legacy MD5 hash e10adc3949ba59abbe56e057f20f883e corresponds to 123456. Log in with it and immediately set a strong password.
Summary
In this guide, you successfully:
- Deployed a zero-cost monitoring backend on Cloudflare (Worker + D1 + DO)
- Installed probe agents across multiple OS environments
- Configured multi-channel alert notifications (Email/IM/Webhook)
- Gained a fully functional, real-time monitoring dashboard
What to explore next:
- Build the frontend to GitHub Pages for a static site + remote API aggregation, supporting multi-site scenarios.
- Add a Scriptable widget on iPhone to check server status directly from the lock screen.
- Dive into the source code to master Cloudflare edge programming and Durable Objects in production.
The beauty of this stack? You don't need to buy a single extra server. Cloudflare's free tier is incredibly generous for personal use, and the unidirectional agent ensures security. If your server count is growing, spend 20 minutes setting this up today.