watches
Public IP, CPU, RAM, disk, processes, TLS certificates — and anything your own scripts can measure.
notifies
Telegram, ntfy, Lark, Slack, Discord, any webhook. Queued and retried — offline alerts arrive when the network returns.
self-contained
One static binary. Installs itself as a service on Linux, macOS, and Windows. No agent phoning home, no UI.
self-teaching
All docs ship inside the binary: emday docs. AI agents get their own guide: emday docs agent.
install
One line on Linux or macOS — detects your platform, verifies the sha256, installs the binary:
curl -fsSL https://madnh.github.io/emday/install.sh | sh
Prefer to read before you run? Inspect the script —
it only downloads the release asset, checks it against checksums.txt, and runs
install. Pin a version with EMDAY_VERSION=0.1.0; change the location
with EMDAY_INSTALL_DIR.
Or install manually from the latest release (Windows: grab the zip):
curl -fsSL -o emday.tar.gz \
https://github.com/madnh/emday/releases/latest/download/emday_VERSION_linux_amd64.tar.gz
tar -xzf emday.tar.gz emday
sudo install -m 0755 emday /usr/local/bin/emday
emday version
quick start
sudo emday init # creates /etc/emday with a commented starter config
sudo vi /etc/emday/emday.yaml # add your notifier, tweak rules
sudo vi /etc/emday/emday.env.example # fill in the secrets it lists
sudo install -m 0600 /etc/emday/emday.env.example /etc/sysconfig/emday
emday check-config # validates config, compiles every rule
emday test-notify my-telegram # make sure alerts actually arrive
sudo emday install && sudo emday start # run as a system service
init seeds emday.env.example listing every
EMDAY_* variable your notifiers can reference, so you fill in values rather than
recall names. emday does not read it — copy it to whatever your unit's
EnvironmentFile= points at (the unit emday install generates already
reads /etc/sysconfig/emday). Details: emday docs deploy.emday doctor --verdict diagnoses the deployment —
which config resolved, what failed, and the next step — without touching anything.configure
version: 1
sources:
wan:
type: public-ip
mode: [v4]
endpoints_v4: # where to ask "what is my IP" — your choice
- https://api.ipify.org
- https://checkip.amazonaws.com
lan: {type: local-ip, interfaces: [eth0]}
cpu: {type: cpu, interval: 30s}
disk: {type: disk, mounts: {root: "/"}}
cert: {type: cert, endpoints: {www: "example.com"}}
rules:
- metric: wan.v4
on_change: true # "em đây, new IP!"
notify: [my-telegram]
- metric: cpu.percent
condition: "value >= 90" # expression over `value`
for: 5m # must hold 5 minutes (anti-flapping)
notify: [my-telegram]
- metric: cert.www.days_left
condition: "value <= 14" # renew before it breaks HTTPS
level: error
notify: [my-telegram]
notifiers:
my-telegram:
type: telegram
token_env: EMDAY_TG_TOKEN
chat_id: "-100123456"
Rule conditions
| goal | write |
|---|---|
| Compare numbers | value > 90, value <= 10, value == 0 |
| Compare strings | value == "failed", value != "ok" |
| Contains / prefix / suffix | value contains "err", value startsWith "eth" |
| In a list | value in ["a", "b"], value not in ["ok"] |
| Combine | ... and ..., ... or ..., not (...) |
Try syntax instantly: emday test-rule 'value > 90' --value 95 → true.
Rules with for: also send a resolved notification when the condition clears.
extend
An exec source runs your command on an interval. The script appends metrics — or direct
notifications — to the file named by $EMDAY_OUTPUT (the GitHub Actions model).
stdout stays free for logging.
#!/bin/sh
age=$(( ($(date +%s) - $(stat -c %Y /backup/latest)) / 3600 ))
echo "BACKUP_AGE_HOURS=$age" >> "$EMDAY_OUTPUT"
[ "$age" -gt 26 ] && echo "NOTIFY_ERROR=backup overdue (${age}h)" >> "$EMDAY_OUTPUT"
sources:
backup:
type: exec
command: /opt/scripts/check-backup.sh
interval: 5m
notify: [my-telegram] # targets for NOTIFY_* lines
Every key becomes a metric (backup.BACKUP_AGE_HOURS) that rules can watch, and
backup._ok catches a silently broken script. Identical NOTIFY messages are deduped,
so a repeating script can’t spam you.
docs
Every topic is a single Markdown file that ships inside the binary
(emday docs <topic>) — the same source you (or an AI agent) can read on
GitHub. This page only indexes them:
- config — config directory,
emday.yamlformat, resolution order - conditions — rule condition syntax cheat sheet
- exec — extending emday with scripts (
$EMDAY_OUTPUT,NOTIFY_*) - notifiers — telegram / ntfy / lark / slack / discord / webhook
- deploy — run as a service: systemd, non-root, secrets, version pinning
- agent — compact operating guide for AI agents
Per-source reference (each built-in: exact metrics, required permissions, rule examples, failure modes):
- source-public-ip — WAN IP via your endpoints
- source-local-ip — NIC addresses from the kernel
- source-cpu — CPU percent and load average
- source-memory — RAM and swap
- source-disk — filesystem used/free
- source-process — named processes up/down + count
- source-cert — TLS certificate expiry, chain and issuer
emday docs agent — that one page is enough for it to configure, extend, and
diagnose emday. doctor, check-config, and test-rule all
speak --json.