Mengotomasi pengelolaan firewall: menggunakan module community.general. ufw di Ansible untuk provisioning aturan allow, deny, dan policy, menulis bash script setup firewall yang idempotent, serta menerapkan ruleset ke banyak server secara konsisten

Sepanjang series ini kalian mengetik perintah ufw satu per satu. Di dunia nyata, kalian tidak akan melakukannya di 50 server — dan bahkan di satu server, mengulang perintah manual adalah sumber inkonsistensi. Episode 20 membawa UFW ke ranah Infrastructure as Code (IaC): mengelola ruleset sebagai kode yang bisa di-review, di-version, dan diterapkan ulang kapan saja.
Mengapa ini penting? Karena aturan firewall yang diketik manual tidak bisa diaudit (apakah server 5 sudah update?), tidak bisa direplikasi, dan mudah "jauh dari yang diharapkan". Sebagai kode, ruleset bisa diuji, di-commit ke git, dan diterapkan identik di mana-mana — ini fondasi untuk episode 21.
Ansible punya module khusus UFW: community.general.ufw. Module ini menangani hampir semua operasi yang kita pelajari — allow, deny, limit, delete, hingga default policy.
Module ini membutuhkan paket community.general di koleksi Ansible:
ansible-galaxy collection install community.generalContoh playbook untuk server web produksi:
- name: Konfigurasi firewall UFW
hosts: webservers
become: true
tasks:
- name: Install ufw
ansible.builtin.apt:
name: ufw
state: present
- name: Default policy deny incoming
community.general.ufw:
default: deny
direction: incoming
- name: Default policy allow outgoing
community.general.ufw:
default: allow
direction: outgoing
- name: Izinkan SSH
community.general.ufw:
rule: allow
port: "22"
proto: tcp
- name: Izinkan HTTP dan HTTPS
community.general.ufw:
rule: allow
port: "{{ item.port }}"
proto: tcp
loop:
- port: "80"
- port: "443"
- name: Aktifkan UFW
community.general.ufw:
state: enabledPerhatikan struktur tugasnya — setiap blok community.general.ufw setara dengan satu perintah UFW yang sudah kita pelajari:
| Parameter Module | Perintah UFW Setara |
|---|---|
rule: allow, port: 22, proto: tcp | ufw allow 22/tcp |
rule: deny, from_ip: 203.0.113.66 | ufw deny from 203.0.113.66 |
rule: limit, port: 22 | ufw limit 22/tcp |
default: deny, direction: incoming | ufw default deny incoming |
state: enabled | ufw enable |
delete: yes | ufw delete ... |
IP/subnet spesifik (episode 6) juga didukung penuh:
- name: Izinkan subnet kantor ke SSH
community.general.ufw:
rule: allow
from_ip: 203.0.113.0/24
to_port: "22"
proto: tcp
- name: Deny IP mencurigakan
community.general.ufw:
rule: deny
from_ip: 198.51.100.99Note
Module community.general.ufw bersifat idempotent: menjalankan playbook dua kali menghasilkan state yang sama, tanpa mengubah apa pun di eksekusi kedua. Ini janji utama IaC — ruleset server selalu sama dengan definisi kode, apa pun yang terjadi di antara dua eksekusi.
Tanpa Ansible, kalian bisa menulis bash script yang juga idempotent. Triknya: selalu cek state sebelum menambah/mengubah:
#!/usr/bin/env bash
set -euo pipefail
echo "==> Memastikan SSH diizinkan"
if ! sudo ufw status | grep -q "22/tcp.*ALLOW"; then
sudo ufw allow 22/tcp
fi
echo "==> Default policies"
sudo ufw default deny incoming
sudo ufw default allow outgoing
echo "==> Layanan publik"
for port in 80/tcp 443/tcp; do
if ! sudo ufw status | grep -q "$port"; then
sudo ufw allow "$port"
fi
done
echo "==> Rate limit SSH"
if ! sudo ufw status | grep -q "22/tcp.*LIMIT"; then
sudo ufw limit 22/tcp
fi
echo "==> Aktifkan UFW"
sudo ufw enable
echo "==> Status akhir"
sudo ufw status verboseKunci idempotensinya: sebelum menambah aturan, periksa dengan ufw status; hanya tambah jika belum ada. Dengan set -euo pipefail, script berhenti segera saat ada error — tidak ada setup separuh jalan.
Jadikan executable dan jalankan:
chmod +x setup-ufw.sh
./setup-ufw.shMenjalankan script dua kali berturut-turut seharusnya menghasilkan output yang sama dan tanpa error — itulah uji idempotensi.
Application profiles (episode 7) juga bisa menjadi kode. Salin file profil ke repo kalian dan deploy dengan Ansible:
- name: Deploy application profiles
ansible.builtin.copy:
src: "files/ufw/applications.d/{{ item }}"
dest: "/etc/ufw/applications.d/{{ item }}"
mode: "0644"
loop:
- app-internal
notify: update ufw apps
handlers:
- name: update ufw apps
ansible.builtin.command: ufw app update AppInternal
changed_when: falseDengan pola ini, profil, aturan, dan kebijakan semuanya hidup di repo — satu sumber kebenaran.
Tip
Mulai sederhana: bahkan satu setup-ufw.sh di git sudah jauh lebih baik daripada nol dokumentasi. Naik ke Ansible saat kalian mengelola beberapa server. Prinsipnya sama — ruleset adalah kode, dan kode harus di-version.
state: enabled tanpa rule SSH: playbook yang salah urutan (enable sebelum allow SSH) = server terkunci setelah deploy.become: true: module UFW butuh root; tanpa privilege, semua tugas gagal.set -e yang tidak sengaja mati: guard setiap perintah yang berisiko gagal saat state sudah benar.Pada episode 20 ini, kalian telah mengotomasi UFW.
Inti yang harus dibawa pulang:
community.general.ufw memetakan semua operasi UFW ke YAML yang idempotent.ufw status sebelum menambah aturan.Di episode 21 selanjutnya, kita perbesar skala: Manajemen Banyak Server & Audit — policy rule terpusat berbasis inventory, mendeteksi drift antara server dan definisi kode, mengekspor ruleset untuk backup, serta menyusun compliance checklist. Sampai jumpa di episode 21!