Module 02 Foundation 5 labs

Linux Administration for Cloud & DevOps

Linux là nền tảng bắt buộc cho DevOps: filesystem, process, service, networking, SSH, logs, package, troubleshooting — toàn bộ kỹ năng một Cloud/DevOps Engineer cần thành thạo để vận hành hệ thống production.

Công cụ thực hành CLI, VS Code, Git, Linux Terminal, WSL2
Nền tảng Linux (Ubuntu 22.04 / WSL2), Windows Terminal
Thời điểm phát hành 23/05/2026
Ngày biên soạn 23/05/2026
Người biên soạn Trần Văn Hòa — Microsoft Certified Trainer (MCT)

Mục tiêu học tập

1. Lý thuyết cốt lõi

1.1. Filesystem & Permission Model

Linux dùng mô hình DAC (Discretionary Access Control): mỗi file/thư mục có owner, group và bộ quyền rwx cho 3 lớp: owner / group / others. Biểu diễn octal: chmod 755 = owner rwx, group r-x, others r-x. Các lệnh then chốt: ls -la, chmod, chown, chgrp, umask. Với môi trường cloud/DevOps, principle of least privilege là bắt buộc: không dùng root khi không cần, tạo service account riêng cho từng ứng dụng.

Cấu trúc thư mục FHS quan trọng cho DevOps

  • /etc — cấu hình hệ thống và service (nginx, sshd, systemd units).
  • /var/log — log hệ thống; /var/lib — dữ liệu runtime (Docker, databases).
  • /opt — ứng dụng cài ngoài package manager.
  • /proc, /sys — virtual FS để đọc trạng thái kernel/hardware.
  • /home, /root — home directory của users.

1.2. Process & Service Management (systemd)

systemd là init system mặc định trên Ubuntu, RHEL, Debian. Nó quản lý vòng đời service qua các unit file (.service, .timer, .socket). Mỗi service trong production phải được chạy dưới systemd để tự khởi động lại khi crash (Restart=on-failure). journald là log daemon tích hợp với systemd, lưu log có cấu trúc, tra cứu với journalctl.

1.3. SSH & Remote Access Security

SSH (Secure Shell) là giao thức mã hóa dùng để quản trị server từ xa. SSH key-based authentication an toàn hơn password vì: key dài 256-bit (Ed25519) không thể brute-force, không truyền secret qua mạng. Các hardening cơ bản theo CIS Benchmark: tắt PasswordAuthentication, đổi port (tùy chọn), giới hạn AllowUsers, bật Protocol 2, tắt root login.

1.4. Log Management & Troubleshooting

Linux có 2 lớp log: syslog/rsyslog (text files trong /var/log) và journald (binary, tra cứu nhanh). Trong DevOps, log là nguồn telemetry đầu tiên khi có sự cố. Pipeline phân tích log điển hình: journalctl -u nginx --since "1h ago" | grep -i "error" | awk '{print $1,$2,$3,$NF}'. Công cụ hữu ích: tail -f, grep, awk, sed, cut, sort | uniq -c | sort -rn.

1.5. Health Monitoring Script Pattern

Trong DevOps, script health-check là bước tiền trạm trước khi đưa vào monitoring stack (Prometheus/Grafana). Các chỉ số cần thu thập: CPU usage (top, /proc/stat), RAM (free -m), disk (df -h), service status (systemctl is-active), network connectivity (ping, curl). Script phải có exit code 0/1 để tích hợp vào CI/CD pipeline hoặc cron job.

2. Thực hành (Labs)

LAB-006

Cấu hình Linux user/group/permission

CLI · Linux Terminal · WSL2

🎯 Mục tiêu: Tạo user/group cho môi trường multi-tenant, phân quyền đúng principle of least privilege, kiểm chứng bằng susudo.

🧰 Công cụ / nền tảng: Ubuntu 22.04 (VM hoặc WSL2), terminal Bash.

📦 Chuẩn bị: Ubuntu 22.04 chạy được (WSL2: wsl --install -d Ubuntu-22.04). Có quyền sudo.

▶️ Các bước (CLI — Bash):

# 1. Tạo group và 2 user cho team devops
sudo groupadd devops-team
sudo useradd -m -s /bin/bash -G devops-team alice
sudo useradd -m -s /bin/bash -G devops-team bob
sudo passwd alice        # đặt password khi được yêu cầu
sudo passwd bob

# 2. Tạo thư mục dự án với quyền nhóm
sudo mkdir -p /opt/devops-project
sudo chown root:devops-team /opt/devops-project
sudo chmod 2775 /opt/devops-project   # setgid: file mới kế thừa group
ls -ld /opt/devops-project

# 3. Kiểm tra: alice có thể tạo file, user ngoài nhóm thì không
su - alice -c "touch /opt/devops-project/alice-test.txt && ls -la /opt/devops-project"
su - bob   -c "touch /opt/devops-project/bob-test.txt && ls -la /opt/devops-project"

# 4. Thiết lập sudo chỉ cho alice (không cho bob)
echo "alice ALL=(ALL) NOPASSWD: /usr/bin/systemctl" | sudo tee /etc/sudoers.d/alice-systemctl
sudo visudo -c    # validate syntax

# 5. Kiểm tra sudo alice vs bob
su - alice -c "sudo systemctl status ssh"
su - bob   -c "sudo systemctl status ssh"   # expect: permission denied

🖥️ Đối chiếu PowerShell (Windows — tham khảo):

# Tương đương trên Windows (Local Users & Groups)
New-LocalUser -Name "alice" -Password (Read-Host -AsSecureString)
New-LocalGroup -Name "devops-team"
Add-LocalGroupMember -Group "devops-team" -Member "alice","bob"

✅ Kết quả mong đợi:

  • ls -ld /opt/devops-project hiển thị drwxrwsr-x 2 root devops-team.
  • Cả alice và bob đều tạo được file trong thư mục; file mới có group devops-team.
  • Alice chạy sudo systemctl status ssh thành công; Bob bị từ chối.

🧹 Cleanup:

sudo userdel -r alice && sudo userdel -r bob
sudo groupdel devops-team
sudo rm /etc/sudoers.d/alice-systemctl
sudo rm -rf /opt/devops-project
LAB-007

Quản lý service bằng systemctl

CLI · Linux Terminal · WSL2

🎯 Mục tiêu: Cài nginx, tạo custom systemd unit, kiểm soát vòng đời service và đọc log qua journalctl.

🧰 Công cụ / nền tảng: Ubuntu 22.04, Bash terminal.

📦 Chuẩn bị: Kết nối internet để cài nginx; WSL2 cần chạy sudo service dbus start nếu systemd chưa active.

▶️ Các bước (CLI — Bash):

# 1. Cài nginx và kiểm tra trạng thái ban đầu
sudo apt update && sudo apt install -y nginx
systemctl status nginx
systemctl is-enabled nginx    # expect: enabled

# 2. Tạo custom service cho một Python web app giả lập
sudo tee /opt/hello-app.py <<'EOF'
#!/usr/bin/env python3
import http.server, socketserver
PORT = 8080
Handler = http.server.SimpleHTTPRequestHandler
with socketserver.TCPServer(("", PORT), Handler) as httpd:
    print(f"Serving on port {PORT}")
    httpd.serve_forever()
EOF
sudo chmod +x /opt/hello-app.py

# 3. Tạo systemd unit file
sudo tee /etc/systemd/system/hello-app.service <<'EOF'
[Unit]
Description=Hello App - Python HTTP Demo
After=network.target

[Service]
Type=simple
User=www-data
ExecStart=/usr/bin/python3 /opt/hello-app.py
WorkingDirectory=/opt
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal
SyslogIdentifier=hello-app

[Install]
WantedBy=multi-user.target
EOF

# 4. Reload daemon và khởi động service
sudo systemctl daemon-reload
sudo systemctl enable --now hello-app
systemctl status hello-app

# 5. Kiểm tra connectivity và logs
curl -s http://localhost:8080 | head -5
journalctl -u hello-app -n 20 --no-pager

# 6. Mô phỏng crash và kiểm tra auto-restart
sudo systemctl kill -s SIGKILL hello-app
sleep 6
systemctl status hello-app     # expect: active (running) — đã restart

# 7. Xem timeline restart trong journal
journalctl -u hello-app --since "5 min ago" --no-pager

🖥️ Đối chiếu GUI (Windows Services):

Tương đương Windows: Services.msc → Properties → Recovery → "Restart the service" on first/second failure. Hoặc PowerShell: New-Service, Set-Service -StartupType Automatic.

✅ Kết quả mong đợi:

  • systemctl status hello-app hiển thị active (running), enabled.
  • curl http://localhost:8080 trả về HTML listing.
  • Sau khi kill, service tự restart trong ≤ 6 giây; journalctl ghi lại sự kiện restart.

🧹 Cleanup:

sudo systemctl disable --now hello-app
sudo rm /etc/systemd/system/hello-app.service /opt/hello-app.py
sudo systemctl daemon-reload
LAB-008

SSH key và hardening SSH

CLI · Linux Terminal · WSL2

🎯 Mục tiêu: Tạo SSH key pair Ed25519, cài đặt passwordless login, hardening /etc/ssh/sshd_config theo CIS Benchmark cơ bản.

🧰 Công cụ / nền tảng: Ubuntu 22.04 (2 terminal: local client + server giả lập localhost), OpenSSH.

📦 Chuẩn bị: SSH server đã cài: sudo apt install -y openssh-server && sudo systemctl enable --now ssh.

▶️ Các bước (CLI — Bash):

# === PHẦN 1: Tạo SSH key pair ===
# 1. Tạo Ed25519 key (an toàn hơn RSA 2048)
ssh-keygen -t ed25519 -C "devops-lab@hoatranlab" -f ~/.ssh/devops_lab_ed25519
# Nhập passphrase hoặc Enter để để trống (lab)
ls -la ~/.ssh/devops_lab_ed25519*
# Output: private key + public key (.pub)

# 2. Copy public key vào authorized_keys (mô phỏng server)
cat ~/.ssh/devops_lab_ed25519.pub >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

# 3. Test kết nối SSH với key
ssh -i ~/.ssh/devops_lab_ed25519 -o StrictHostKeyChecking=no [email protected] "whoami && hostname"

# === PHẦN 2: SSH Hardening (/etc/ssh/sshd_config) ===
# 4. Backup config gốc
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak

# 5. Áp dụng hardening settings
sudo tee /etc/ssh/sshd_config.d/99-hardening.conf <<'EOF'
# CIS Benchmark SSH Hardening - HoaTranLab
Protocol 2
PermitRootLogin no
PasswordAuthentication no
PermitEmptyPasswords no
MaxAuthTries 4
LoginGraceTime 30
ClientAliveInterval 300
ClientAliveCountMax 3
AllowTcpForwarding no
X11Forwarding no
IgnoreRhosts yes
HostbasedAuthentication no
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
EOF

# 6. Validate config và reload
sudo sshd -t    # test config syntax — expect: no output = OK
sudo systemctl reload ssh

# 7. Kiểm chứng: key login thành công, password login bị từ chối
ssh -i ~/.ssh/devops_lab_ed25519 [email protected] "echo 'Key login: OK'"
ssh -o PasswordAuthentication=yes -o PubkeyAuthentication=no [email protected] "echo test" 2>&1
# expect: "Permission denied (publickey)"

🖥️ Đối chiếu PowerShell/CMD (Windows):

# Tạo SSH key trên Windows (PowerShell)
ssh-keygen -t ed25519 -C "devops-lab@hoatranlab" -f "$env:USERPROFILE\.ssh\devops_lab_ed25519"
# Copy public key sang Linux server
type "$env:USERPROFILE\.ssh\devops_lab_ed25519.pub" | ssh user@server "cat >> ~/.ssh/authorized_keys"
# Test kết nối
ssh -i "$env:USERPROFILE\.ssh\devops_lab_ed25519" user@server

✅ Kết quả mong đợi:

  • ssh-keygen tạo 2 file: private (devops_lab_ed25519, mode 600) và public (.pub).
  • Kết nối bằng key thành công, in đúng username.
  • sshd -t không báo lỗi; kết nối password bị từ chối với thông báo Permission denied (publickey).

🧹 Cleanup:

sudo rm /etc/ssh/sshd_config.d/99-hardening.conf
sudo systemctl reload ssh
# Xóa key test nếu không dùng nữa:
rm ~/.ssh/devops_lab_ed25519 ~/.ssh/devops_lab_ed25519.pub
LAB-009

Troubleshoot Linux logs

CLI · Linux Terminal · WSL2

🎯 Mục tiêu: Dùng journalctl, tail, grep, awk để phân tích và tóm tắt log sự cố từ nginx và SSH.

🧰 Công cụ / nền tảng: Ubuntu 22.04, nginx đã cài (LAB-007), Bash.

📦 Chuẩn bị: nginx đang chạy; SSH server active. Cần tạo một số request lỗi để có log thú vị.

▶️ Các bước (CLI — Bash):

# === PHẦN 1: Tạo log test ===
# 1. Tạo HTTP requests — bình thường và lỗi 404
for i in $(seq 1 5); do curl -s http://localhost/ > /dev/null; done
for i in $(seq 1 3); do curl -s http://localhost/notfound-$i > /dev/null; done

# 2. Mô phỏng SSH brute-force (dùng sai password)
for i in $(seq 1 4); do
  ssh -o PasswordAuthentication=yes -o PubkeyAuthentication=no \
      -o BatchMode=no -o ConnectTimeout=2 [email protected] 2>&1 || true
done

# === PHẦN 2: Phân tích với journalctl ===
# 3. Xem log nginx realtime (dừng bằng Ctrl+C)
sudo journalctl -u nginx -f &
JOURNAL_PID=$!
sleep 2 && curl -s http://localhost/lab-test > /dev/null
kill $JOURNAL_PID 2>/dev/null

# 4. Filter log theo severity
sudo journalctl -u nginx -p err --since "1h ago" --no-pager

# 5. Đếm HTTP 404 trong access log nginx
sudo cat /var/log/nginx/access.log | awk '{print $9}' | sort | uniq -c | sort -rn
# Output: số lần xuất hiện mỗi HTTP status code

# 6. Tìm top IP truy cập nginx
sudo awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10

# === PHẦN 3: SSH auth failure analysis ===
# 7. Xem SSH authentication failures
sudo journalctl -u ssh --since "30 min ago" | grep -i "failed\|invalid\|disconnect" | head -20

# 8. Tóm tắt: đếm auth failures theo user
sudo journalctl -u ssh --since "30 min ago" --no-pager \
  | grep "Invalid user" \
  | awk '{print $8}' \
  | sort | uniq -c | sort -rn

# === PHẦN 4: Công cụ nhanh ===
# 9. Xem kernel messages gần đây (OOM killer, disk errors)
sudo journalctl -k --since "24h ago" | grep -v "audit\|NET\|acpi" | tail -20

# 10. Export log ra file để phân tích offline
sudo journalctl -u nginx --since "1h ago" --no-pager > /tmp/nginx-lab009.log
wc -l /tmp/nginx-lab009.log

✅ Kết quả mong đợi:

  • Output awk '{print $9}' trên access.log hiển thị dòng 3 404 (3 request 404) và 5 200+.
  • journalctl -u ssh | grep "Invalid user" in ra các dòng thử login sai.
  • File /tmp/nginx-lab009.log có dữ liệu, wc -l > 0.

🧹 Cleanup: rm /tmp/nginx-lab009.log

LAB-010

Viết script kiểm tra health server

CLI · Linux Terminal · WSL2

🎯 Mục tiêu: Viết Bash script server-health.sh kiểm tra CPU, RAM, disk, service — in báo cáo có màu sắc và exit code 0 (healthy) / 1 (critical).

🧰 Công cụ / nền tảng: Ubuntu 22.04, Bash, bc (cài sẵn), cron.

📦 Chuẩn bị: nginx hoặc bất kỳ service nào đang chạy.

▶️ Các bước (CLI — Bash):

# 1. Tạo script
cat > /opt/server-health.sh <<'SCRIPT'
#!/usr/bin/env bash
# server-health.sh — HoaTranLab Module 02 Lab 010
# Exit 0 = healthy, Exit 1 = critical threshold exceeded

set -euo pipefail

RED='\033[0;31m'; YELLOW='\033[1;33m'; GREEN='\033[0;32m'; NC='\033[0m'
CRITICAL=0
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')

echo "=================================================="
echo "  SERVER HEALTH REPORT — $TIMESTAMP"
echo "=================================================="

# --- CPU ---
CPU_IDLE=$(top -bn1 | grep "Cpu(s)" | awk '{print $8}' | tr -d '%id,')
CPU_USED=$(echo "100 - ${CPU_IDLE:-0}" | bc 2>/dev/null || echo "0")
if (( $(echo "$CPU_USED > 90" | bc -l) )); then
  echo -e "CPU  : ${RED}CRITICAL ${CPU_USED}%${NC}"; CRITICAL=1
elif (( $(echo "$CPU_USED > 70" | bc -l) )); then
  echo -e "CPU  : ${YELLOW}WARNING  ${CPU_USED}%${NC}"
else
  echo -e "CPU  : ${GREEN}OK       ${CPU_USED}%${NC}"
fi

# --- RAM ---
RAM_TOTAL=$(free -m | awk '/^Mem/{print $2}')
RAM_USED=$(free -m  | awk '/^Mem/{print $3}')
RAM_PCT=$(echo "scale=1; $RAM_USED * 100 / $RAM_TOTAL" | bc)
if (( $(echo "$RAM_PCT > 90" | bc -l) )); then
  echo -e "RAM  : ${RED}CRITICAL ${RAM_USED}/${RAM_TOTAL} MB (${RAM_PCT}%)${NC}"; CRITICAL=1
elif (( $(echo "$RAM_PCT > 75" | bc -l) )); then
  echo -e "RAM  : ${YELLOW}WARNING  ${RAM_USED}/${RAM_TOTAL} MB (${RAM_PCT}%)${NC}"
else
  echo -e "RAM  : ${GREEN}OK       ${RAM_USED}/${RAM_TOTAL} MB (${RAM_PCT}%)${NC}"
fi

# --- Disk ---
while IFS= read -r line; do
  USE=$(echo "$line" | awk '{print $5}' | tr -d '%')
  MNT=$(echo "$line" | awk '{print $6}')
  if [ "$USE" -gt 90 ]; then
    echo -e "DISK : ${RED}CRITICAL $MNT ${USE}%${NC}"; CRITICAL=1
  elif [ "$USE" -gt 80 ]; then
    echo -e "DISK : ${YELLOW}WARNING  $MNT ${USE}%${NC}"
  else
    echo -e "DISK : ${GREEN}OK       $MNT ${USE}%${NC}"
  fi
done < <(df -h --output=source,size,used,avail,pcent,target | tail -n +2 | grep -v tmpfs | grep -v udev)

# --- Services ---
SERVICES=("nginx" "ssh" "cron")
for svc in "${SERVICES[@]}"; do
  if systemctl is-active --quiet "$svc" 2>/dev/null; then
    echo -e "SVC  : ${GREEN}OK       $svc${NC}"
  else
    echo -e "SVC  : ${RED}CRITICAL $svc is DOWN${NC}"; CRITICAL=1
  fi
done

echo "=================================================="
[ "$CRITICAL" -eq 0 ] && echo -e "${GREEN}OVERALL: HEALTHY${NC}" || echo -e "${RED}OVERALL: CRITICAL — action required!${NC}"
exit $CRITICAL
SCRIPT

chmod +x /opt/server-health.sh

# 2. Chạy script
/opt/server-health.sh
echo "Exit code: $?"

# 3. Thêm vào cron — chạy mỗi 5 phút, ghi log
(crontab -l 2>/dev/null; echo "*/5 * * * * /opt/server-health.sh >> /var/log/health-check.log 2>&1") | crontab -
crontab -l    # kiểm tra cron entry đã thêm

# 4. Mô phỏng service down để kiểm tra CRITICAL exit code
sudo systemctl stop nginx
/opt/server-health.sh || echo "Script exited with code 1 — CRITICAL detected (correct!)"
sudo systemctl start nginx

🖥️ Đối chiếu PowerShell (Windows):

# Kiểm tra health tương đương trên Windows
$cpu  = (Get-CimInstance Win32_Processor | Measure-Object -Property LoadPercentage -Average).Average
$ram  = Get-CimInstance Win32_OperatingSystem
$disk = Get-PSDrive C | Select-Object Used,Free
Write-Host "CPU: $cpu% | RAM Free: $([math]::Round($ram.FreePhysicalMemory/1MB,0)) MB | Disk Free: $([math]::Round($disk.Free/1GB,1)) GB"
# Kiểm tra service
Get-Service -Name W32Time | Select-Object Name,Status

✅ Kết quả mong đợi:

  • Script in ra bảng màu với trạng thái từng metric; echo $? = 0 khi tất cả OK.
  • Khi nginx down: dòng SVC : CRITICAL nginx is DOWN in màu đỏ; exit code = 1.
  • crontab -l hiển thị entry health check mỗi 5 phút.

🧹 Cleanup:

crontab -l | grep -v "server-health" | crontab -
sudo rm /opt/server-health.sh

3. Tình huống doanh nghiệp thực tế

Bối cảnh

Một công ty SaaS nhận thấy server production bị tấn công brute-force SSH liên tục; đồng thời đội DevOps mất 2 giờ tìm nguyên nhân sau khi một service web API tự dưng down lúc 3 giờ sáng.

Giải pháp áp dụng kỹ năng Module 02

  • SSH Hardening (LAB-008): Chuyển toàn bộ server sang key-based auth, tắt password, deploy fail2ban ban IP sau 5 lần thử sai. Brute-force SSH giảm 100%.
  • systemd auto-restart (LAB-007): Cấu hình Restart=on-failure + RestartSec=5 cho web API. Service tự phục hồi trong 5 giây, MTTR giảm từ 2 giờ xuống còn 0 (người dùng không nhận thấy).
  • Health script + cron (LAB-010): Script chạy mỗi 5 phút, khi disk >85% gửi email cảnh báo qua mail. Phát hiện disk full trước khi service crash.
  • Log analysis (LAB-009): journalctl cung cấp timeline chính xác khi nào service crash và tại sao (OOM killer), rút ngắn postmortem từ 2 giờ xuống 15 phút.

📚 Nguồn tham khảo

Module 01: DevOps Mindset Module 03: Networking Fundamentals
Zalo