Hướng dẫn sử dụng emday
Cài đặt và vận hành emday trên server Linux: theo dõi IP public, CPU, RAM, ổ cứng, process, chứng chỉ TLS và script tuỳ ý — nhận thông báo qua Telegram, Lark, ntfy, Slack, Discord.
Tên gọi: khi server đổi IP, emday nhắn cho bạn — “em đây, IP mới nè!” 😉
1. Cài đặt
Cách nhanh nhất — một lệnh, tự nhận diện OS/kiến trúc máy, tự kiểm tra sha256:
curl -fsSL https://madnh.github.io/emday/install.sh | sh
install vào /usr/local/bin, không đụng gì khác. Cài phiên bản
cụ thể: EMDAY_VERSION=0.1.0 sh; đổi chỗ cài: EMDAY_INSTALL_DIR=...Hoặc cài thủ công từ bản release mới nhất
(chọn linux_amd64 hoặc linux_arm64 tuỳ máy — xem bằng uname -m):
# thay VERSION bằng phiên bản thực tế, ví dụ 0.1.0
curl -fsSL -o emday.tar.gz \
https://github.com/madnh/emday/releases/download/vVERSION/emday_VERSION_linux_amd64.tar.gz
tar -xzf emday.tar.gz emday
sudo install -m 0755 emday /usr/local/bin/emday
emday version
Chỉ cần đúng một file binary — không phải cài thêm gì khác.
2. Khởi tạo cấu hình
sudo emday init
Chạy bằng sudo, emday tạo thư mục /etc/emday chứa toàn bộ những gì nó cần:
/etc/emday/
├── emday.yaml # file cấu hình (file chính bạn sửa)
├── config.md # tài liệu cấu hình, sinh tự động
├── emday.env.example # mẫu khai secret — điền giá trị rồi copy (xem mục 4)
├── state.json # bộ nhớ của engine (emday tự quản — đừng sửa)
├── queue/ # thông báo chưa gửi được (tự quản)
└── tmp/ # chỗ tạm cho exec script (tự quản)
init là lệnh duy nhất tạo thư mục cấu hình, và nó
từ chối ghi đè thư mục đã có. Mọi lệnh khác báo lỗi rõ ràng khi chưa init — không bao giờ
âm thầm tạo dữ liệu sai chỗ.3. Cấu hình
Mở /etc/emday/emday.yaml — file mẫu có sẵn comment giải thích từng phần.
Cấu trúc gồm 3 khối: sources (thu thập gì) → rules (khi nào báo)
→ notifiers (báo đi đâu).
3.1. Theo dõi IP public (use case gốc)
sources:
wan:
type: public-ip # IP public → metric wan.v4
interval: 5m
mode: [v4] # thêm "v6" nếu cần IPv6
endpoints_v4: # nơi hỏi "IP của tôi là gì" — bạn tự chọn,
- https://api.ipify.org # thử lần lượt tới khi có kết quả hợp lệ
- https://checkip.amazonaws.com
lan:
type: local-ip # IP LAN của card mạng → metric lan.eth0_v4
interval: 30s # đọc từ kernel, không gọi mạng
interfaces: [eth0] # xem tên card: ip -br addr
rules:
- metric: wan.v4
on_change: true # báo mỗi khi IP public đổi
notify: [tele]
- metric: lan.eth0_v4
on_change: true # báo khi IP LAN đổi
notify: [tele]
emday chỉ chấp nhận response là đúng một địa chỉ IP hợp lệ — endpoint trả về HTML hay trang lỗi sẽ bị bỏ qua và thử endpoint kế tiếp, không bao giờ bị nhầm thành "IP đổi".
3.2. Ngưỡng CPU / RAM / ổ cứng
sources:
cpu: {type: cpu, interval: 30s}
memory: {type: memory}
disk:
type: disk
interval: 5m
mounts: {root: "/", data: "/data"}
rules:
- metric: cpu.percent
condition: "value >= 90" # biểu thức trên biến `value`
for: 5m # phải cao liên tục 5 phút mới báo (chống nhiễu)
notify: [tele]
- metric: disk.root.percent
condition: "value >= 90"
level: error
notify: [tele]
Khi hết vượt ngưỡng, emday tự gửi thông báo resolved ✅. Bảng cú pháp điều kiện:
| Muốn | Viết |
|---|---|
| So sánh số | value > 90, value <= 10, value == 0 |
| So sánh chuỗi | value == "failed", value != "ok" |
| Chứa / bắt đầu / kết thúc | value contains "err", value startsWith "eth" |
| Thuộc danh sách | value in ["a", "b"], value not in ["ok"] |
| Kết hợp | ... and ..., ... or ..., not (...) |
Thử cú pháp ngay không cần sửa config:
emday test-rule 'value >= 90' --value 95 # in ra: true
emday test-rule 'value not in ["ok"]' --value failed
3.3. Chứng chỉ TLS sắp hết hạn
sources:
cert:
type: cert
interval: 6h # mặc định của loại này — cert đổi theo ngày,
timeout: 10s # không cần probe mỗi phút
endpoints: # alias -> host[:port], port mặc định 443
www: "example.com"
api: "api.example.com:8443"
rules:
- metric: cert.www.days_left
condition: "value <= 14" # còn 14 ngày là phải gia hạn
level: error
notify: [tele]
- metric: cert.www.status
condition: 'value != "ok"' # hết hạn / sai host / chain hỏng / không tới được
for: 15m # bỏ qua trục trặc mạng thoáng qua
notify: [tele]
- metric: cert.www.issuer
on_change: true # cert bị thay giữa chừng
notify: [tele]
Mỗi alias sinh ra ba metric: days_left (số ngày còn lại, âm khi đã hết hạn),
status, và issuer. status nhận một trong các giá trị
ok, expired, hostname-mismatch, untrusted,
dns-failure, refused, timeout,
handshake-error, connect-error.
ubuntu:24.04 chưa có gói ca-certificates: mọi
endpoint đều ra untrusted, kể cả cert hoàn toàn tốt. Cài
ca-certificates là về lại ok. Kiểm tra bằng
ls /etc/ssl/certs/ca-certificates.crt trước khi kết luận một cert là không tin cậy.status, đừng chỉ canh
days_left: khi host không tới được thì days_left không có giá trị
để so sánh, rule im lặng — đúng lúc bạn cần biết nhất. status thì luôn được ghi
nhận, kể cả khi probe thất bại.emday bắt tay TLS nhưng không gửi request nào, lấy chứng chỉ xong là đóng
kết nối. Việc kiểm tra chain chạy riêng sau đó, nên "hết hạn" và "chain không tin cậy" là hai
câu trả lời độc lập — không cái nào che cái nào. Rule issuer +
on_change là thứ duy nhất bắt được trường hợp chứng chỉ bị thay bằng proxy chặn
giữa: cert mới hợp lệ, còn hạn dài, mọi rule khác đều im.
3.4. Đích thông báo
Telegram — tạo bot với @BotFather, thêm bot vào group, lấy chat id:
notifiers:
tele:
type: telegram
token_env: EMDAY_TG_TOKEN # token nằm trong biến môi trường (xem mục 4)
chat_id: "-100123456"
Lark — trong group: Settings → Bots → Add bot → Custom bot, copy webhook URL.
Nếu bot bật chế độ chữ ký (signature) thì khai thêm secret_env:
notifiers:
lark:
type: lark
url: https://open.larksuite.com/open-apis/bot/v2/hook/xxxx
secret_env: EMDAY_LARK_SECRET # TÊN biến env chứa secret (không phải giá trị secret!)
# — hoặc ghi thẳng secret (file config nên là root, chmod 600):
# secret: "xxxxxxxxxxxx"
ntfy — nhận push lên điện thoại không cần đăng ký, chỉ cần đặt topic khó đoán:
notifiers:
phone:
type: ntfy
url: https://ntfy.sh/ten-topic-bi-mat-cua-ban
Ngoài ra còn slack, discord, và webhook (tuỳ biến hoàn toàn) —
xem emday docs notifiers.
Với slack/discord/webhook, URL chính là bí mật (token nằm trong đường dẫn).
Muốn giữ URL ngoài file config, khai url_env (TÊN biến env chứa URL) thay cho url:
notifiers:
slack:
type: slack
url_env: EMDAY_SLACK_URL # nạp qua systemd EnvironmentFile — xem mục 4
3.5. Kiểm tra trước khi chạy
emday check-config # validate config + compile mọi điều kiện
export EMDAY_TG_TOKEN=xxxx # tạm thời, để test
emday test-notify tele # gửi thử một tin — kiểm tra điện thoại!
4. Chạy như service (systemd)
sudo emday install
sudo emday start
emday status # running
emday tự đăng ký vào systemd. Service không kế thừa shell của bạn,
nên mọi biến env của notifier (token_env, secret_env,
url_env) phải khai trực tiếp cho service.
Bạn không cần nhớ tên biến: emday init đã tạo sẵn
/etc/emday/emday.env.example liệt kê đủ các biến EMDAY_*,
cái nào chưa dùng thì để dạng comment. Chỉ việc điền giá trị:
sudoedit /etc/emday/emday.env.example
# /etc/emday/emday.env.example — dạng KEY=VALUE, không có `export`
EMDAY_TG_TOKEN=123456:ABC-token-cua-bot
#EMDAY_LARK_SECRET=xxxx
#EMDAY_SLACK_URL=https://hooks.slack.com/services/T/B/X
Rồi copy nó tới chỗ service đọc. Unit do emday install sinh ra
đã sẵn đọc /etc/sysconfig/emday, nên không cần sửa unit:
sudo install -m 0600 /etc/emday/emday.env.example /etc/sysconfig/emday
sudo systemctl restart emday
Nếu bạn tự viết unit thì trỏ EnvironmentFile= vào bản copy của mình:
sudo install -m 0600 /etc/emday/emday.env.example /etc/emday/emday.env
sudo systemctl edit emday
# nội dung override:
[Service]
EnvironmentFile=/etc/emday/emday.env
sudo systemctl restart emday
EnvironmentFile= trỏ vào thì service vẫn không
thấy secret. Và vì biến chỉ được đọc lúc process khởi động, sửa file xong phải
systemctl restart emday — daemon-reload không đủ.User=emday) cho an toàn. Toàn bộ chuyện triển khai fleet (systemd, non-root,
secret, pin version, gate check-config) gói trong emday docs deploy.sudo emday run
(chạy foreground, log ra màn hình, Ctrl-C để dừng).5. Mở rộng bằng script của bạn
Bất kỳ script nào cũng thành nguồn dữ liệu: ghi KEY=VALUE vào file
$EMDAY_OUTPUT (giống $GITHUB_OUTPUT của GitHub Actions).
stdout để log thoải mái, không bị parse.
#!/bin/sh
# /opt/scripts/check-backup.sh
age=$(( ($(date +%s) - $(stat -c %Y /backup/latest.tar.gz)) / 3600 ))
echo "BACKUP_AGE_HOURS=$age" >> "$EMDAY_OUTPUT"
# logic đặc thù chỉ script này hiểu → tự bắn thông báo trực tiếp:
if [ "$age" -gt 26 ] && [ -f /backup/.full-day ]; then
echo "NOTIFY_ERROR=Full backup quá hạn (${age}h)" >> "$EMDAY_OUTPUT"
fi
sources:
backup:
type: exec
command: /opt/scripts/check-backup.sh
interval: 5m
timeout: 30s
notify: [tele] # đích cho các dòng NOTIFY_*
rules:
- metric: backup.BACKUP_AGE_HOURS
condition: "value > 24"
notify: [tele]
- metric: backup._ok # script chết cũng biết
condition: "value == 0"
notify: [tele]
- Mỗi
KEYthành metricbackup.KEY— rule dùng như metric hệ thống. NOTIFY=...(info),NOTIFY_WARN=...,NOTIFY_ERROR=...— script chủ động bắn thông báo.- Thông báo trùng nội dung bị nén tự động (mặc định 30 phút) — script lặp lại mỗi phút cũng không spam.
- Quy tắc chọn: cái gì diễn đạt được bằng rule thì để rule làm (được chống nhiễu + resolved miễn phí);
NOTIFY_*dành cho logic rule không diễn đạt nổi.
6. Chẩn đoán khi có vấn đề
emday doctor --verdict
Lệnh này tuyệt đối chỉ đọc, trả lời lần lượt: thư mục cấu hình nào đang được dùng? config có hợp lệ không? daemon đã chạy chưa? có thông báo nào đang kẹt trong hàng đợi không? — kèm kết luận và bước xử lý tiếp theo.
| Triệu chứng | Kiểm tra |
|---|---|
| Không nhận được thông báo | emday doctor --verdict — nhìn mục queue; nếu kẹt thì emday test-notify <tên> để xem lỗi cụ thể (sai token? sai URL?) |
| Muốn biết rule có bắn không | journalctl -u emday | grep -E 'alert |delivered' — mỗi thông báo ghi 2 dòng: lúc rule khớp và lúc gửi thành công. Bị chặn bởi cooldown cũng có dòng riêng nói rõ lý do |
| Service không chạy | emday status, rồi journalctl -u emday -n 50 |
| Sửa config xong quên kiểm tra | emday check-config — luôn chạy sau mỗi lần sửa |
| Điều kiện rule không như ý | emday test-rule '...' --value ... |
Lark báo code 19021: sign match fail... | Đồng hồ server lệch quá 1 giờ (timedatectl — bật NTP: sudo timedatectl set-ntp true), hoặc secret sai / env chưa set ở nơi emday chạy (emday doctor sẽ cảnh báo env thiếu) |
7. Tài liệu đầy đủ (trong chính binary)
Mỗi chủ đề là một file Markdown nằm ngay trong binary
(emday docs <chủ-đề>) — cũng chính là file bạn (hoặc AI agent) đọc được
trên GitHub. Trang này chỉ liệt kê, bấm vào để tới đúng file:
- config — thư mục config, định dạng
emday.yaml, thứ tự tìm config - conditions — cú pháp điều kiện của rule
- exec — viết script mở rộng (
$EMDAY_OUTPUT,NOTIFY_*) - notifiers — từng loại đích thông báo
- deploy — chạy như service: systemd, non-root, secret, pin version
- agent — hướng dẫn cho AI agent
Tra cứu từng builtin source (metric chính xác, quyền cần, rule mẫu, cạm bẫy):
- source-public-ip — IP WAN qua endpoint bạn khai
- source-local-ip — địa chỉ NIC đọc từ kernel
- source-cpu — CPU percent và load average
- source-memory — RAM và swap
- source-disk — dung lượng ổ/mount
- source-process — process còn sống + số lượng
- source-cert — hạn chứng chỉ TLS, chain và issuer
emday docs agent — một trang đó đủ để agent tự cấu hình, viết script mở rộng
và chẩn đoán emday, không cần tài liệu nào khác.8. Nâng cấp & gỡ cài đặt
# nâng cấp: thay binary rồi khởi động lại
sudo emday stop
sudo install -m 0755 emday-moi /usr/local/bin/emday
sudo emday start
# gỡ cài đặt
sudo emday stop && sudo emday uninstall
sudo rm /usr/local/bin/emday
sudo rm -rf /etc/emday # xoá luôn cấu hình + state nếu muốn