A flexible monitoring and alerting system for ZFS storage pools with support for multiple data sources and notification channels.
- Local Command - Execute
zpool status -jdirectly on the local system - SSH Remote - Fetch ZFS status from remote servers via SSH
- File Reader - Read status from JSON files (for testing or offline analysis)
- Telegram - Send alerts via Telegram Bot API
- Webhook - Send HTTP POST requests to custom webhooks
- Bark - iOS Bark push notification service
- Console - Console output (for debugging)
- Automatic pool state detection (ONLINE/DEGRADED/FAULTED, etc.)
- Device error detection (read, write, checksum errors)
- Scrub/resilver error detection
- Recursive vdev health checks
cargo build --releasezwatch initThis creates a zwatch.toml configuration file.
# Data source configuration
[[data_sources]]
type = "local"
name = "localhost"
command = "zpool"
args = ["status", "-j"]
[[data_sources]]
type = "ssh"
name = "remote-server"
host = "192.168.1.100"
user = "root"
keyfile = "/home/user/.ssh/id_rsa"
# Notification configuration
[[notifiers]]
type = "telegram"
bot_token = "YOUR_BOT_TOKEN"
chat_id = "YOUR_CHAT_ID"
[[notifiers]]
type = "webhook"
url = "https://your-webhook-url.com/endpoint"
# Global settings
[settings]
check_interval = 300 # Check interval in seconds
notify_on_error_only = true # Only send notifications on errors- Continuous monitoring (default):
zwatch [--config PATH] - One-time check:
zwatch check [--config PATH] - Generate example config:
zwatch init [--output FILE]
For more details, run: zwatch --help.
- Platform: Local command data source works on Linux/FreeBSD only; on macOS use SSH or File data sources.
- Config discovery: If
--configis omitted, ZWatch loadszwatch.tomlin the current directory when present; otherwise uses built-in defaults. - Logging: Control verbosity via
RUST_LOG, e.g.RUST_LOG=info zwatchorRUST_LOG=debug zwatch.
Implement the ZpoolDataSource trait:
use async_trait::async_trait;
pub struct CustomDataSource {
// Custom fields
}
#[async_trait]
impl ZpoolDataSource for CustomDataSource {
async fn fetch(&self) -> Result<String> {
// Implementation to fetch and return JSON string
}
fn name(&self) -> String {
// Return data source name
}
}Implement the Notifier trait:
use async_trait::async_trait;
pub struct CustomNotifier {
// Custom fields
}
#[async_trait]
impl Notifier for CustomNotifier {
async fn notify(&self, report: &HealthReport) -> Result<()> {
// Implementation to send notification
}
fn name(&self) -> String {
// Return notifier name
}
}✅ ZFS Pool 'tank' is ONLINE and healthy
⚠️ ZFS Pool 'tank' has issues!
State: DEGRADED
Pool Errors: 0
Scan Errors: 0
Device Errors:
- sda1: state=DEGRADED, read=0, write=5, checksum=0
- sdb1: state=OFFLINE, read=0, write=0, checksum=0
Details: Pool state is DEGRADED; 2 devices have errors
This project is under the MIT License, for more details see the LICENSE file.