Menerapkan SELinux untuk web server dan layanan aplikasi: konteks file yang benar untuk konten, log, dan script, boolean untuk koneksi jaringan dan database, labeling port dengan semanage port, serta pola multi-instance untuk MySQL dan PostgreSQL.

Setelah memahami tools di episode 6 dan 7 serta identitas di episode 8, sekarang waktunya praktik nyata. Hampir tidak ada deployment yang tanpa web server dan database — dan hampir tidak ada sysadmin yang belum pernah bertemu denial SELinux di keduanya. Episode 9 ini mengajarkan pola-pola konteks, boolean, dan labeling port yang menyelesaikan mayoritas masalah tersebut.
Ingat urutan solusi dari episode 7: boolean dulu, konteks file kedua, modul policy terakhir. Episode ini hampir seluruhnya bergerak di dua lapisan pertama.
Nginx dan Apache berjalan dalam domain httpd_t. Untuk membaca atau menulis file, konteks file harus cocok dengan domain tersebut. Tabel berikut adalah peta label standar:
| Tipe konteks | Untuk | Contoh path bawaan |
|---|---|---|
httpd_sys_content_t | konten yang hanya dibaca | /usr/share/nginx/html, /var/www/html |
httpd_sys_rw_content_t | konten yang juga ditulis aplikasi | direktori upload, cache |
httpd_log_t | file log web server | /var/log/nginx, /var/log/httpd |
httpd_config_t | file konfigurasi | /etc/nginx, /etc/httpd |
httpd_sys_script_t | script CGI yang dieksekusi | /usr/lib/cgi-bin |
Masalah klasik muncul saat kalian meletakkan konten di path kustom, misalnya /srv/www. Di sana label defaultnya bukan httpd_sys_content_t, sehingga httpd_t menolak membaca — dan muncul denial httpd_t terhadap default_t. Solusinya adalah menambahkan aturan fcontext lalu menerapkan ulang label:
sudo semanage fcontext -a -t httpd_sys_content_t "/srv/www(/.*)?"
sudo restorecon -Rv /srv/wwwPola regex /srv/www(/.*)? mencakup direktori itu sendiri dan seluruh isinya, termasuk file yang akan dibuat nanti. Ingat: semanage fcontext hanya menulis aturan label; restorecon lah yang benar-benar menerapkan label itu ke file di disk. Jika lupa restorecon, aturan ada tapi label tetap lama.
Important
Jangan pernah memakai chcon untuk "memperbaiki" konteks di produksi. chcon mengubah label secara langsung tanpa menyimpan aturan, sehingga hilang saat relabel berikutnya (misalnya setelah restorecon -R seluruh filesystem). semanage fcontext + restorecon selalu lebih benar karena aturannya persisten.
Web server modern jarang berdiri sendiri: reverse proxy menghubungi backend, aplikasi memanggil API internal, dan framework menulis ke database. Semua koneksi keluar dari httpd_t ini diatur boolean:
sudo setsebool -P httpd_can_network_connect on
sudo setsebool -P httpd_can_network_connect_db onTabel gejala-ke-boolean untuk debugging cepat:
| Gejala | Boolean |
|---|---|
| Reverse proxy mengembalikan 502 ke backend internal | httpd_can_network_connect |
| Aplikasi gagal terhubung ke MySQL atau PostgreSQL | httpd_can_network_connect_db |
| Script CGI tidak mau dieksekusi | httpd_enable_cgi |
| Konten di direktori home tidak terbaca | httpd_enable_homedirs |
Tip
Urutan debug yang disiplin untuk denial web server: cek label file dengan ls -Z (apakah konteks konten benar), lalu cek boolean yang relevan dengan getsebool, baru terakhir cek label port. Mayoritas — sekitar sembilan dari sepuluh — denial web server selesai pada dua langkah pertama.
Tiga denial paling sering untuk layanan web dan bagaimana menyelesaikannya:
denied { read } pada tclass=file) — biasanya label konten salah. Terapkan fcontext dengan tipe yang tepat lalu restorecon.denied { name_bind } pada tclass=tcp_socket) — port yang dipakai belum berlabel untuk domain. Daftarkan port dengan semanage port.denied { name_connect }) — boolean koneksi belum aktif, atau port tujuan belum berlabel.Pola terakhir membawa kita ke topik berikutnya: labeling port.
Database punya pola konteks yang sama: data dir, socket, dan port.
Data dir standar sudah berlabel benar: /var/lib/mysql berlabel mysqld_db_t dan /var/lib/pgsql/data berlabel postgresql_db_t. Jika memindahkan data ke disk lain, misalnya /data/mysql, label harus diatur ulang:
sudo semanage fcontext -a -t mysqld_db_t "/data/mysql(/.*)?"
sudo restorecon -Rv /data/mysqlSocket dan port database juga punya label sendiri. Cek port yang dikenal policy:
semanage port -l | grep -E 'mysql|postgres'Kalian akan melihat mysqld_port_t di port 3306 dan postgresql_port_t di port 5432. Masalah muncul saat layanan berjalan di port non-standar — misalnya instance MySQL kedua di port 3307:
sudo semanage port -a -t mysqld_port_t -p tcp 3307Setelah ini, instance kedua di port 3307 bisa bind tanpa denial name_bind. Tanpa label, policy hanya tahu port 3306 milik mysqld — port lain dianggap milik domain lain.
Warning
Port labeling harus konsisten dengan konfigurasi aplikasi dan harus diulang di setiap host. Karena itu jangan pernah mencatatnya hanya di kepala — masukkan ke provisioning (Ansible, Terraform) agar instance baru tidak tiba-tiba gagal start dengan denial bind yang misterius. Ini juga alasan semanage port menjadi bahan episode khusus tentang network labeling nanti.
Pada episode 9 ini kalian sudah menerapkan SELinux ke dua layanan paling umum: web server dan database. Konteks file konten dengan httpd_sys_content_t dan httpd_sys_rw_content_t, boolean httpd_can_network_connect dan httpd_can_network_connect_db, serta labeling port multi-instance dengan semanage port — semuanya mengikuti satu prinsip: setiap resource diberi label, setiap domain diberi izin yang sempit.
Kunci yang harus dibawa pulang:
semanage fcontext menyimpan aturan, restorecon menerapkannya — keduanya wajib.Web server dan database tadi berjalan langsung di host. Di episode 10, kita masuk ke dunia yang lebih abstrak: Containers (Podman, Docker, CRI-O) — bagaimana SELinux membungkus proses container dalam domain container_t dan spc_t, relabeling bind mount dengan :Z dan :z, opsi keamanan label, hingga konfigurasi SELinux di Kubernetes dan integrasinya dengan seccomp.