Saya nak tanya anda satu soalan: berapa kali anda SSH ke server untuk buat benda yang sama? Update pakej, check disk space, restart service… Kalau jawapannya “banyak kali,” maka bab ini untuk anda.
Homelab yang baik tidak patut bergantung pada ingatan anda semata-mata. Anda tak sepatutnya kena “check sana sini” secara manual setiap hari. Bila automasi dan monitoring disusun dengan betul, homelab jadi lebih tenang untuk diurus, dan bila masalah berlaku, anda lebih cepat tahu puncanya.
Apa yang anda akan belajar:
Nota Beginner: Tujuan automasi bukan untuk nampak canggih atau impress orang. Tujuannya ialah kurangkan kerja berulang dan kurangkan risiko anda terlupa langkah penting. Kalau anda boleh automate backup dan update, itu dah cukup bagus untuk permulaan.
Bayangkan scenario ni: tengah malam, cakera salah satu server anda dah 95% penuh. Tanpa monitoring, anda hanya akan tahu bila service mula crash esok pagi. Dengan monitoring, anda dapat alert malam tadi dan boleh selesaikan sebelum jadi masalah besar.
Itulah kuasa automasi dan pemantauan — anda tidur lena, homelab jaga diri sendiri.
Ansible adalah alat automasi IT yang membolehkan anda mengurus banyak pelayan dari satu tempat. Yang best tentang Ansible:
# Pasang Ansible sudo apt install ansible -y # Atau menggunakan pip pip3 install ansible
Ini struktur folder yang saya cadangkan. Nampak banyak, tapi sebenarnya straightforward:
ansible/ ├── inventory/ │ └── hosts.yml ├── playbooks/ │ ├── setup-common.yml │ ├── setup-docker.yml │ ├── update-all.yml │ └── backup.yml ├── roles/ │ ├── common/ │ ├── docker/ │ └── monitoring/ └── ansible.cfg
Inventory ni macam “senarai telefon” server anda. Ansible perlu tahu server mana nak diuruskan:
# inventory/hosts.yml all: children: proxmox: hosts: pve: ansible_host: 10.0.20.10 ansible_user: root docker_hosts: hosts: docker1: ansible_host: 10.0.20.20 ansible_user: admin nas: hosts: truenas: ansible_host: 10.0.0.10 ansible_user: admin vars: ansible_python_interpreter: /usr/bin/python3
Playbook ni macam “resipi” — anda tulis sekali, jalankan berkali-kali. Ini contoh playbook untuk setup asas semua server:
# playbooks/setup-common.yml --- - name: Konfigurasi asas untuk semua pelayan hosts: all become: yes tasks: - name: Kemas kini senarai pakej apt: update_cache: yes cache_valid_time: 3600 - name: Naik taraf semua pakej apt: upgrade: dist - name: Pasang pakej asas apt: name: - curl - wget - git - htop - net-tools - ufw - fail2ban - unattended-upgrades state: present - name: Konfigurasi UFW - default deny ufw: direction: incoming policy: deny - name: Konfigurasi UFW - benarkan SSH ufw: rule: allow port: "22" proto: tcp - name: Aktifkan UFW ufw: state: enabled - name: Konfigurasi zon masa timezone: name: Asia/Kuala_Lumpur - name: Aktifkan kemas kini automatik apt: name: unattended-upgrades state: present
Nota Beginner: Perhatikan betapa mudahnya YAML dibaca. Setiap task ada name yang jelas. Kalau playbook ini gagal, anda boleh nampak terus task mana yang bermasalah.
name
Ini playbook yang saya paling kerap guna. Satu command, semua server dikemas kini:
# playbooks/update-all.yml --- - name: Kemas kini semua pelayan hosts: all become: yes serial: 1 # Kemas kini satu pelayan pada satu masa tasks: - name: Kemas kini senarai pakej apt: update_cache: yes - name: Naik taraf semua pakej apt: upgrade: dist register: upgrade_result - name: Periksa jika reboot diperlukan stat: path: /var/run/reboot-required register: reboot_required - name: Reboot jika perlu reboot: msg: "Reboot diperlukan selepas kemas kini" reboot_timeout: 300 when: reboot_required.stat.exists - name: Kemas kini kontena Docker shell: | cd /opt/docker && \ docker compose pull && \ docker compose up -d when: "'docker_hosts' in group_names"
Menjalankan playbook:
# Jalankan playbook ansible-playbook -i inventory/hosts.yml playbooks/update-all.yml # Dry run (uji tanpa melaksanakan) — saya SANGAT cadangkan buat ni dulu ansible-playbook -i inventory/hosts.yml playbooks/update-all.yml --check # Untuk host tertentu sahaja ansible-playbook -i inventory/hosts.yml playbooks/update-all.yml --limit docker1
Nak lagi automated? Schedule playbook dengan cron:
# Kemas kini mingguan automatik # crontab -e 0 3 * * 0 ansible-playbook -i /opt/ansible/inventory/hosts.yml \ /opt/ansible/playbooks/update-all.yml >> /var/log/ansible-update.log 2>&1
Okay, sekarang bahagian yang paling seronok — monitoring! Anda akan nampak graf-graf cantik tentang homelab anda.
Ini combo yang paling popular untuk homelab monitoring:
# docker-compose.yml - Stack Pemantauan services: prometheus: image: prom/prometheus:latest container_name: prometheus ports: - "9090:9090" volumes: - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml - prometheus-data:/prometheus command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.retention.time=30d' restart: unless-stopped grafana: image: grafana/grafana:latest container_name: grafana ports: - "3000:3000" volumes: - grafana-data:/var/lib/grafana environment: GF_SECURITY_ADMIN_PASSWORD: kata_laluan_admin GF_INSTALL_PLUGINS: grafana-clock-panel,grafana-piechart-panel restart: unless-stopped node-exporter: image: prom/node-exporter:latest container_name: node-exporter ports: - "9100:9100" volumes: - /proc:/host/proc:ro - /sys:/host/sys:ro - /:/rootfs:ro command: - '--path.procfs=/host/proc' - '--path.sysfs=/host/sys' - '--path.rootfs=/rootfs' restart: unless-stopped cadvisor: image: gcr.io/cadvisor/cadvisor:latest container_name: cadvisor ports: - "8082:8080" volumes: - /:/rootfs:ro - /var/run:/var/run:ro - /sys:/sys:ro - /var/lib/docker/:/var/lib/docker:ro restart: unless-stopped volumes: prometheus-data: grafana-data:
Konfigurasi Prometheus:
# prometheus/prometheus.yml global: scrape_interval: 15s evaluation_interval: 15s scrape_configs: - job_name: 'prometheus' static_configs: - targets: ['localhost:9090'] - job_name: 'node-exporter' static_configs: - targets: - 'node-exporter:9100' - '10.0.20.20:9100' - '10.0.20.21:9100' - job_name: 'cadvisor' static_configs: - targets: ['cadvisor:8080'] - job_name: 'proxmox' static_configs: - targets: ['10.0.20.10:9221']
Nota Beginner: Jangan risau kalau konfigurasi ni nampak banyak. Copy paste je dulu, tukar IP address kepada IP server anda, dan jalankan. Anda boleh fine-tune kemudian.
Setelah Grafana berjalan, anda tak perlu buat dashboard dari kosong. Import je yang dah sedia ada:
http://pelayan:3000
Percayalah, pertama kali anda nampak graf CPU, RAM, dan network usage homelab anda, memang satisfying!
Dashboard cantik tak berguna kalau anda tak tengok. Jadi, setup alerting supaya homelab beritahu anda bila ada masalah:
Alertmanager:
# Tambah ke docker-compose.yml alertmanager: image: prom/alertmanager:latest container_name: alertmanager ports: - "9093:9093" volumes: - ./alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml restart: unless-stopped
# alertmanager/alertmanager.yml global: resolve_timeout: 5m route: group_by: ['alertname'] group_wait: 10s group_interval: 10s repeat_interval: 1h receiver: 'telegram' receivers: - name: 'telegram' telegram_configs: - bot_token: 'TOKEN_BOT_ANDA' chat_id: 123456789 message: | {{ range .Alerts }} *{{ .Labels.alertname }}* {{ .Annotations.description }} {{ end }}
Peraturan amaran Prometheus — beritahu anda bila ada masalah:
# prometheus/alert-rules.yml groups: - name: homelab-alerts rules: - alert: HostHighCpuLoad expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80 for: 5m labels: severity: warning annotations: description: "CPU pada {{ $labels.instance }} melebihi 80% selama 5 minit" - alert: HostOutOfMemory expr: node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes * 100 < 10 for: 2m labels: severity: critical annotations: description: "RAM pada {{ $labels.instance }} kurang daripada 10%" - alert: HostOutOfDiskSpace expr: (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"} * 100) < 15 for: 5m labels: severity: warning annotations: description: "Storan pada {{ $labels.instance }} kurang daripada 15%" - alert: ContainerDown expr: absent(container_last_seen{name=~".+"}) for: 5m labels: severity: critical annotations: description: "Kontena {{ $labels.name }} telah berhenti"
Kalau anda tak mahu setup Telegram bot, Ntfy adalah alternatif yang super simple. Install app Ntfy pada telefon, subscribe ke topic, dan anda akan dapat push notification:
services: ntfy: image: binwiederhier/ntfy:latest container_name: ntfy ports: - "8084:80" volumes: - ./ntfy/cache:/var/cache/ntfy command: serve restart: unless-stopped
Menghantar pemberitahuan semudah satu baris curl:
# Dari skrip backup curl -d "Backup selesai pada $(date)" \ http://ntfy.lab.local/homelab-alerts
Nota Beginner: Saya cadangkan mulakan dengan Ntfy sebab ia paling mudah. Nanti bila anda dah selesa, boleh upgrade ke Alertmanager + Telegram untuk alert yang lebih structured.
Log adalah “black box” homelab anda. Bila ada masalah, log adalah tempat pertama anda cari jawapan.
Loki adalah sistem agregasi log yang ringan oleh Grafana Labs. Ia collect log dari semua server dan anda boleh cari/filter dari satu tempat — Grafana:
services: loki: image: grafana/loki:latest container_name: loki ports: - "3100:3100" volumes: - loki-data:/loki restart: unless-stopped promtail: image: grafana/promtail:latest container_name: promtail volumes: - ./promtail/config.yml:/etc/promtail/config.yml - /var/log:/var/log:ro - /var/lib/docker/containers:/var/lib/docker/containers:ro restart: unless-stopped volumes: loki-data:
# promtail/config.yml server: http_listen_port: 9080 grpc_listen_port: 0 positions: filename: /tmp/positions.yaml clients: - url: http://loki:3100/loki/api/v1/push scrape_configs: - job_name: system static_configs: - targets: - localhost labels: job: varlogs __path__: /var/log/*.log - job_name: docker static_configs: - targets: - localhost labels: job: docker __path__: /var/lib/docker/containers/*/*-json.log
Last but not least, Homepage. Ini adalah “landing page” cantik untuk homelab anda. Satu tempat untuk nampak semua service yang anda jalankan:
services: homepage: image: ghcr.io/gethomepage/homepage:latest container_name: homepage ports: - "3005:3000" volumes: - ./homepage/config:/app/config restart: unless-stopped
# homepage/config/services.yaml - Infrastruktur: - Proxmox: href: https://pve.lab.local:8006 icon: proxmox.png description: Hypervisor widget: type: proxmox url: https://10.0.20.10:8006 username: api@pam!homepage password: token-api - Pi-hole: href: http://pihole.lab.local icon: pi-hole.png description: DNS & Sekat Iklan widget: type: pihole url: http://10.0.0.2 - Aplikasi: - Nextcloud: href: https://cloud.lab.local icon: nextcloud.png description: Storan Awan - Jellyfin: href: http://media.lab.local icon: jellyfin.png description: Pelayan Media
Tahniah, anda dah habis bab automasi dan pemantauan! Bab ni memang banyak content, tapi setiap bahagian akan jimatkan masa anda dalam jangka panjang. Jom recap:
Ingat, anda tak perlu setup semua sekaligus. Mulakan dengan satu — mungkin Ansible untuk auto-update, atau Prometheus + Grafana untuk monitoring asas. Tambah satu-satu, dan sebelum anda sedar, homelab anda dah berjalan macam infrastruktur production!
Seterusnya, kita akan masuk ke automasi lanjutan dan CI/CD untuk anda yang nak bawa homelab ke level seterusnya.