AI Automation

Những workflow nên có cho sysadmin trên VPS

Vấn đề: VPS chạy ổn, nhưng bạn có đang ngủ ngon?

Bạn vừa SSH vào một VPS mới, cài xong Nginx, MariaDB, PHP 8.3, Docker và fail2ban. Mọi thứ chạy ngon lành. Nhưng ba tháng sau, ổ đầy log, service chết lúc 2h sáng, database bị corrup, và bạn phải restore từ bản backup… nếu có. Với một thuê VPS chạy production, việc thiết lập những workflow tự động hóa ngay từ đầu là khác biệt giữa “hệ thống vận hành” và “hệ thống tự vận hành”. Bài viết này dành cho sysadmin đã có kiến thức cơ bản, muốn xây dựng bộ 7 workflow thiết yếu: backup, monitor, cảnh báo, deploy, log rotate, bảo mật và DNS động. Mỗi workflow đều có lệnh chạy được trên Ubuntu 24.04 LTS.

Yêu cầu trước khi bắt đầu

  • Một VPS chạy Ubuntu 24.04 LTS, user sudo non-root.
  • Domain trỏ về IP VPS (cho Coolify và monitor).
  • Tài khoản Telegram Bot + token (cho cảnh báo).
  • Tài khoản S3-compatible (Backblaze B2, MinIO hoặc AWS S3) cho backup.
  • Kiến thức cơ bản về systemd, crontab và Docker.

Workflow 1: Backup tự động lên S3 bằng Restic

Restic là công cụ backup mã nguồn mở, hỗ trợ snapshot dedup và mã hóa. Cài đặt:

sudo apt update && sudo apt install restic -y
restic version
# restic 0.16.4

Khởi tạo repository trên S3 (ví dụ Backblaze B2):

export RESTIC_REPOSITORY="s3:https://s3.us-west-004.backblazeb2.com/my-bucket/vps-backup"
export RESTIC_PASSWORD="your-strong-password-here"
restic init

Tạo script backup tại /usr/local/bin/backup-vps.sh:

#!/bin/bash
export RESTIC_REPOSITORY="s3:https://s3.us-west-004.backblazeb2.com/my-bucket/vps-backup"
export RESTIC_PASSWORD="your-strong-password-here"
restic backup /etc /var/www /var/lib/mysql --tag auto-$(date +%Y%m%d)
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 3 --prune
sudo chmod +x /usr/local/bin/backup-vps.sh

Thêm cron job chạy hàng ngày lúc 2h sáng:

sudo crontab -e
# Thêm dòng:
0 2 * * * /usr/local/bin/backup-vps.sh >> /var/log/backup.log 2>&1

Verify: Kiểm tra log và snapshot:

sudo cat /var/log/backup.log
restic snapshots

Nếu không có S3, bạn có thể dùng rclone backup lên Google Drive. Xem hướng dẫn chi tiết tại bài dùng rclone backup VPS lên Google Drive.

Workflow 2: Giám sát hệ thống với Prometheus + Grafana

Prometheus thu thập metric từ node_exporter, Grafana vẽ dashboard. Dùng Docker Compose để triển khai nhanh:

mkdir ~/monitoring && cd ~/monitoring
nano docker-compose.yml
version: '3.8'
services:
  prometheus:
    image: prom/prometheus:v2.53.0
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus-data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.retention.time=30d'
    ports:
      - "9090:9090"
    restart: unless-stopped
  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=strongpassword
    volumes:
      - grafana-data:/var/lib/grafana
    restart: unless-stopped
  node_exporter:
    image: prom/node-exporter:latest
    command:
      - '--path.rootfs=/host'
    pid: host
    volumes:
      - /:/host:ro,rslave
    restart: unless-stopped
volumes:
  prometheus-data:
  grafana-data:
docker compose up -d

Tạo file prometheus.yml:

global:
  scrape_interval: 15s
scrape_configs:
  - job_name: 'node'
    static_configs:
      - targets: ['node_exporter:9100']

Verify: Mở http://<VPS-IP>:9090/targets, node_exporter status UP. Grafana tại http://<VPS-IP>:3000, import dashboard ID 1860 (Node Exporter Full). Nếu cần kỹ thuật chuyên sâu hơn, xem bài giám sát VPS với Prometheus và Grafana từ host.

Workflow 3: Cảnh báo Telegram khi service chết hoặc tài nguyên cạn

Bot Telegram gửi thông báo nếu service down hoặc disk/ram cao. Tạo script /usr/local/bin/alert-telegram.sh:

#!/bin/bash
BOT_TOKEN="your-bot-token-here"
CHAT_ID="your-chat-id-here"
MESSAGE="$1"
curl -s -X POST "https://api.telegram.org/bot$BOT_TOKEN/sendMessage" \
  -d "chat_id=$CHAT_ID" \
  -d "text=$MESSAGE"
sudo chmod +x /usr/local/bin/alert-telegram.sh

Tạo systemd service check: /etc/systemd/system/check-nginx.service

[Unit]
Description=Check Nginx and alert
[Service]
Type=oneshot
ExecStart=/bin/bash -c 'if ! systemctl is-active --quiet nginx; then /usr/local/bin/alert-telegram.sh "Nginx died on $(hostname)"; fi'

Kích hoạt timer: /etc/systemd/system/check-nginx.timer

[Unit]
Description=Check Nginx every 5 minutes
[Timer]
OnCalendar=*:0/5
Persistent=true
[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable --now check-nginx.timer

Verify: Dừng Nginx tạm thời, đợi 5 phút, kiểm tra Telegram có tin nhắn không. sudo journalctl -u check-nginx.service -f xem log. Tham khảo bài gửi cảnh báo hệ thống VPS qua Telegram bot bằng script Bash để mở rộng.

Workflow 4: Deploy ứng dụng tự động với Coolify

Coolify là PaaS tự host (thay thế Heroku), cho phép deploy từ Git repository với một click. Cài đặt nhanh:

curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash

Quá trình cài tự động kéo Docker images và chạy trên port 8000. Truy cập http://<VPS-IP>:8000, tạo tài khoản admin. Thêm server của bạn (localhost) và deploy một ứng dụng Node.js hoặc PHP từ GitHub bằng webhook tự động. Mỗi lần push code, Coolify tự build và redeploy. Hướng dẫn chi tiết tại bài tự host PaaS kiểu Heroku trên VPS bằng Coolify.

Lưu ý: Coolify chiếm khoảng 1-2 GB RAM. Dùng VPS Linux tối thiểu 2GB RAM, hàng đầu 4GB. Nếu xài thuê VPS giá rẻ 2GB RAM, chỉ deploy 1-2 ứng dụng nhẹ.

Workflow 5: Log rotate tự động, không để ổ đầy

Mặc định Ubuntu có logrotate chạy hàng ngày, nhưng cần cấu hình cho ứng dụng custom. Tạo file /etc/logrotate.d/custom-apps:

/var/log/myapp/*.log {
    daily
    rotate 7
    compress
    delaycompress
    missingok
    notifempty
    create 0640 www-data adm
    postrotate
        systemctl reload myapp > /dev/null 2>&1 || true
    endscript
}

Kiểm tra cấu hình:

sudo logrotate -d /etc/logrotate.d/custom-apps

Verify: Chạy thử logrotate force:

sudo logrotate -f /etc/logrotate.d/custom-apps
ls -la /var/log/myapp/

File cũ nén thành .gz. Xem thêm bài cấu hình logrotate quản lý log trên VPS Ubuntu.

Workflow 6: Bảo mật tự động, Fail2ban + SSH key + firewall

Fail2ban giám sát log và block IP brute-force. Cài đặt:

sudo apt install fail2ban -y
sudo systemctl enable --now fail2ban

Tạo file /etc/fail2ban/jail.local:

[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 1h
findtime = 10m

Khoá SSH password, chỉ dùng key:

sudo nano /etc/ssh/sshd_config
# PasswordAuthentication no
# PermitRootLogin prohibit-password
sudo systemctl restart sshd

Firewall UFW chỉ mở port cần:

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow 80,443/tcp
sudo ufw enable

Verify: sudo fail2ban-client status sshd, hiện số IP bị ban. sudo ufw status verbose, hiện rules. Bài chi tiết: hướng dẫn cấu hình UFW firewall cơ bản trên Ubuntu VPS.

Workflow 7: DNS động cho VPS, hết IPv4 cố định vẫn truy cập

Nếu VPS dùng IP động (ví dụ mạng gia đình), dùng DNS động để luôn truy cập bằng domain. Dùng DuckDNS (miễn phí). Tạo script /usr/local/bin/duckdns-update.sh:

#!/bin/bash
DOMAIN="your-domain"
TOKEN="your-duckdns-token"
curl -s "https://www.duckdns.org/update?domains=$DOMAIN&token=$TOKEN&ip=" > /dev/null
sudo chmod +x /usr/local/bin/duckdns-update.sh

Thêm cron job chạy mỗi 5 phút:

*/5 * * * * /usr/local/bin/duckdns-update.sh >> /var/log/duckdns.log 2>&1

Verify: cat /var/log/duckdns.log, kiểm tra response "OK". Ping domain thử xem trùng IP VPS không. Workflow này hữu ích khi bạn thuê VPS Ubuntu có IPv4 tĩnh sẵn, nhưng nếu cần dự phòng, hãy thiết lập DNS động.

Xử lý lỗi thường gặp

Lỗi: Restic không kết nối được S3

Kiểm tra endpoint và credentials. Dùng lệnh: restic check. Thêm biến môi trường RESTIC_REPOSITORY chính xác. Nếu dùng Backblaze B2, đảm bảo bucket đã public? không, B2 private là được, Restic dùng key riêng.

Lỗi: Coolify không deploy được, báo lỗi "no space left"

Docker chiếm nhiều disk. Chạy docker system prune -a -f để dọn images cũ. Kiểm tra dung lượng: df -h. Nếu VPS dùng NVMe dung lượng nhỏ, hãy dọn thường xuyên.

Lỗi: Fail2ban không ban IP dù log có brute-force

Kiểm tra logpath có đúng không: sudo fail2ban-client status sshd. Xem filter: sudo fail2ban-client get sshd filter. Sửa jail.local: thêm logpath = /var/log/auth.log cho Ubuntu.

Câu hỏi thường gặp

Có cần thiết lập tất cả 7 workflow cùng lúc không?

Không. Ưu tiên workflow 1 (backup) và 6 (bảo mật) trước, vì đó là những thứ bảo vệ dữ liệu và hệ thống. Sau đó thêm workflow 2 và 3 (giám sát + cảnh báo) khi hệ thống có service production.

Coolify có thay thế được CI/CD như GitLab CI không?

Coolify phù hợp deploy ứng dụng nhỏ- vừa (Node.js, PHP, static site). Nếu cần CI/CD mạnh với test tự động, GitLab CI hoặc GitHub Actions vẫn tốt hơn. Coolify làm việc deploy nhanh, không làm pipeline phức tạp.

Logrotate có cần cấu hình cho Docker container không?

Có. Docker container log có thể làm đầy disk nhanh. Thêm flag khi chạy container: --log-opt max-size=10m --log-opt max-file=3 hoặc cấu hình trong daemon.json.

Dùng VPS giá rẻ có đủ chạy Prometheus + Grafana không?

VPS 2GB RAM chạy được. Prometheus + node_exporter dùng ~300MB, Grafana ~200MB. Nhưng nếu VPS đã chạy database và web, nên dùng bảng giá VPS để chọn gói 4GB RAM hoặc thuê máy chủ riêng nếu cần.

Telegram bot alert có gửi được cảnh báo disk đầy không?

Có. Thêm đoạn kiểm tra disk trong cron: df -h | awk '{if ($5+0 > 90) system("/usr/local/bin/alert-telegram.sh \"Disk full on $HOSTNAME\")"}'.

Bài viết liên quan

Lưu ý: Bài viết mang tính tham khảo, tổng hợp kiến thức chung. Mỗi hệ thống, hạ tầng và nhu cầu có đặc thù riêng, nên kiểm thử trong môi trường an toàn và tham vấn kỹ sư trước khi triển khai thực tế.