Caddy Web Server dengan PHP-FPM: Panduan Konfigurasi Lengkap
Tutorial Server PHP #caddy #php #php-fpm #web-server

Caddy Web Server dengan PHP-FPM: Panduan Konfigurasi Lengkap

A
Abd. Asis
6 min read
Bagikan:

Apache dan Nginx sudah lama menjadi pilihan default untuk menjalankan PHP di server. Keduanya terbukti, matang, dan punya ekosistem konfigurasi yang sangat luas. Tapi keduanya juga mewarisi satu beban yang sama: kompleksitas. Mengaktifkan HTTPS memerlukan Certbot, konfigurasi virtual host berulang, dan setup TLS yang harus dilakukan manual. Untuk banyak proyek, ini terasa berlebihan.

Caddy hadir dengan pendekatan yang berbeda. Web server modern berbasis Go ini menangani HTTPS secara otomatis — mulai dari permohonan sertifikat, validasi domain, hingga pembaruan otomatis — tanpa satu baris konfigurasi tambahan. Untuk menjalankan PHP, Caddy terhubung ke PHP-FPM melalui direktif php_fastcgi yang sederhana tapi fleksibel.

Artikel ini memandu konfigurasi Caddy dengan PHP-FPM secara lengkap, mulai dari struktur file konfigurasi, setup dasar untuk aplikasi PHP modern seperti Laravel, hingga konfigurasi production-ready dengan security headers dan optimasi performa.

Apa yang Membuat Caddy Berbeda dari Nginx

Sebelum masuk ke konfigurasi, ada baiknya memahami filosofi Caddy agar tidak terjebak memikirkannya seperti Nginx.

Caddy menggunakan Caddyfile sebagai format konfigurasi. Sintaksnya jauh lebih ringkas dibanding blok server {} di Nginx atau VirtualHost di Apache. Caddy juga opinionated dalam hal keamanan: TLS 1.2+, cipher suite modern, HTTP/2, dan HTTP/3 diaktifkan secara default tanpa perlu konfigurasi tambahan.

Yang paling signifikan: Caddy mendapatkan sertifikat TLS secara otomatis melalui ACME (protokol yang digunakan Let’s Encrypt dan ZeroSSL). Tidak perlu certbot, tidak perlu cron job untuk renewal. Selama domain sudah mengarah ke server, Caddy akan mengurus sertifikatnya sendiri.

Caddy membutuhkan akses ke port 80 dan 443 untuk proses validasi domain ACME. Pastikan firewall tidak memblokir kedua port ini sebelum menjalankan Caddy di mode production.

Struktur Direktori Konfigurasi Caddy

Konfigurasi Caddy yang bersih dimulai dari struktur direktori yang terorganisir. Alih-alih menumpuk semua konfigurasi dalam satu file, pisahkan berdasarkan fungsinya.

Buat struktur direktori berikut di /etc/caddy/:

/etc/caddy/
├── Caddyfile          # Konfigurasi global
├── config/
   └── php.conf       # Snippet reusable untuk PHP-FPM
└── sites/
    └── blog.conf      # Konfigurasi per site

Buat direktori yang diperlukan:

sudo mkdir -p /etc/caddy/config /etc/caddy/sites
sudo mkdir -p /var/log/caddy

Konfigurasi Global Caddyfile

File /etc/caddy/Caddyfile berisi konfigurasi global yang berlaku untuk semua site, termasuk logging dan import konfigurasi tambahan.

# /etc/caddy/Caddyfile
{
    log default {
        format console
        output file /var/log/caddy/system.log
        exclude http.log.access
    }
}

import config/*
import sites/*

Blok log default mengatur format log sistem ke console (lebih mudah dibaca manusia) dan menyimpannya di file terpisah. exclude http.log.access memisahkan access log dari system log — masing-masing site akan punya access log sendiri.

Snippet PHP-FPM yang Reusable

Jika menjalankan beberapa versi PHP atau beberapa site, mendefinisikan snippet PHP-FPM di file tersendiri menghemat banyak duplikasi. Buat file /etc/caddy/config/php.conf:

# /etc/caddy/config/php.conf
(php83) {
    php_fastcgi unix//run/php/php8.3-fpm.sock
}

(php84) {
    php_fastcgi unix//run/php/php8.4-fpm.sock
}

Sintaks (nama_snippet) { ... } mendefinisikan snippet yang bisa di-import di konfigurasi site mana pun.

Konfigurasi Site PHP dengan Caddy

Setup Dasar untuk Aplikasi Modern (Laravel, Slim, dll)

Aplikasi PHP modern seperti Laravel menggunakan pola front controller — semua request diarahkan ke public/index.php. Caddy menangani ini dengan sangat baik melalui direktif php_fastcgi yang sudah mengerti pola ini secara built-in.

Buat file /etc/caddy/sites/blog.conf:

# /etc/caddy/sites/blog.conf
blog.example.com {
    root * /var/www/blog/public

    log {
        output file /var/log/caddy/blog.access.log
        format console
    }

    encode zstd gzip

    import php84

    @dotFiles {
        path */.*
        not path /.well-known/*
    }
    respond @dotFiles 403
}

Penjelasan tiap direktif:

  • root * /var/www/blog/public — menetapkan direktori root ke folder public, sesuai struktur Laravel
  • encode zstd gzip — mengaktifkan kompresi Zstd dan Gzip secara otomatis; Caddy akan memilih yang didukung browser
  • import php84 — menggunakan snippet yang sudah didefinisikan di config/php.conf
  • @dotFiles — matcher yang menangkap semua path dimulai dengan titik, lalu merespons dengan 403 untuk mencegah akses ke file seperti .env

Blok @dotFiles sangat penting untuk keamanan. Tanpanya, file seperti .env bisa diakses publik jika berada di dalam direktori root.

Cara Kerja Direktif php_fastcgi

php_fastcgi bukan sekadar meneruskan request ke PHP-FPM. Direktif ini mengimplementasikan tiga perilaku otomatis yang biasanya harus dikonfigurasi manual di Nginx:

  1. Directory index rewriting — jika request ke example.com/dashboard/ dan file dashboard/index.php ada, request diarahkan ke file tersebut
  2. Front controller pattern — jika file yang diminta tidak ada di disk, request diteruskan ke index.php di root; ini setara dengan try_files $uri $uri/ /index.php?$query_string di Nginx
  3. FastCGI routing — file .php diteruskan ke PHP-FPM melalui socket Unix dengan parameter CGI yang tepat

Socket Unix (unix//run/php/php8.4-fpm.sock) lebih cepat dari TCP socket karena tidak melewati network stack. Gunakan TCP (127.0.0.1:9000) hanya jika PHP-FPM berjalan di server yang berbeda.

Optimasi Performa untuk Production

Cache Header untuk Aset Statis

Browser tidak perlu mengunduh ulang file CSS, JS, atau gambar yang sudah pernah diunduh. Tambahkan header Cache-Control untuk aset statis:

# /etc/caddy/sites/blog.conf
blog.example.com {
    root * /var/www/blog/public

    log {
        output file /var/log/caddy/blog.access.log
        format console
    }

    encode zstd gzip

    @staticAssets {
        path_regexp \.(jpg|jpeg|png|webp|gif|avif|ico|svg|css|js|woff|woff2|pdf)$
    }
    header @staticAssets Cache-Control "max-age=31536000,public,immutable"

    @missingStatic {
        path_regexp \.(jpg|jpeg|png|webp|gif|avif|ico|svg|css|js|woff|woff2|pdf)$
        not file
    }
    respond @missingStatic 404 {
        close
    }

    import php84

    @dotFiles {
        path */.*
        not path /.well-known/*
    }
    respond @dotFiles 403
}

@missingStatic berfungsi sebagai fast 404 — jika request untuk file statis tapi file tidak ada di disk, Caddy langsung merespons 404 tanpa meneruskan request ke PHP-FPM. Ini mengurangi beban PHP-FPM secara signifikan, terutama saat ada bot yang memindai path-path umum.

Membatasi Ukuran Request Body

Tanpa batasan, PHP-FPM akan menerima dan memproses upload berapapun ukurannya. Caddy bisa memblokir request yang terlalu besar sebelum mencapai PHP:

blog.example.com {
    request_body {
        max_size 20MB
    }

    # konfigurasi lainnya...
}

Untuk membandingkan strategi performa PHP lebih lanjut, termasuk kapan PHP-FPM sudah cukup dan kapan perlu mempertimbangkan Laravel Octane, baca artikel tentang perbedaan keduanya.

Security Headers untuk Perlindungan Standar

Header keamanan adalah lapisan perlindungan tambahan yang memberitahu browser bagaimana menangani konten dari situs. Caddy memudahkan penambahan header ini melalui direktif header:

blog.example.com {
    header {
        Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
        X-Frame-Options "SAMEORIGIN"
        X-Content-Type-Options "nosniff"
        Referrer-Policy "no-referrer-when-downgrade"
        X-XSS-Protection "1; mode=block"
        Permissions-Policy "camera=(), microphone=(), geolocation=()"
        -Server
    }

    # konfigurasi lainnya...
}

Direktif -Server (dengan tanda minus) menghapus header Server dari respons, sehingga tidak mengekspos informasi bahwa server menggunakan Caddy. Prefix ? sebaliknya — menambahkan header hanya jika belum ada.

Membatasi HTTP Method

Jika aplikasi hanya memerlukan GET, POST, HEAD, dan OPTIONS, tolak method lain sebelum sampai ke PHP:

@blockedMethods {
    not method GET HEAD POST OPTIONS
}
respond @blockedMethods 405 {
    close
}

Konfigurasi di Balik Load Balancer atau CDN

Jika Caddy berada di belakang load balancer, reverse proxy, atau CDN seperti Cloudflare, header X-Forwarded-For yang diterima perlu dipercaya agar Caddy bisa mendapatkan IP asli pengunjung:

blog.example.com {
    trusted_proxies static 10.0.0.1/24

    # konfigurasi lainnya...
}

Ganti 10.0.0.1/24 dengan rentang IP load balancer atau CDN yang digunakan. Tanpa konfigurasi ini, REMOTE_ADDR yang diterima PHP akan berisi IP load balancer, bukan IP pengunjung.

Mengelola Service Caddy

Caddy dijalankan sebagai systemd service. Perintah-perintah berikut untuk mengelola service-nya:

# Mulai service
sudo systemctl start caddy

# Aktifkan saat boot
sudo systemctl enable caddy

# Reload konfigurasi tanpa downtime
sudo systemctl reload caddy

# Cek status
sudo systemctl status caddy

Untuk validasi konfigurasi sebelum reload:

sudo caddy validate --config /etc/caddy/Caddyfile

Perintah ini akan melaporkan error sintaks tanpa harus merestart service yang sedang berjalan.

Kesimpulan

Caddy menghapus sebagian besar boilerplate yang biasanya menyertai setup web server PHP: tidak ada Certbot, tidak ada cron renewal, tidak ada konfigurasi TLS manual. Dengan php_fastcgi yang sudah mengerti front controller pattern, setup untuk Laravel atau framework PHP modern lainnya bisa selesai dalam beberapa baris. Untuk konfigurasi yang lebih kompleks — multi-site, multiple PHP version, atau arsitektur microservice — sistem snippet reusable dan import Caddy membuat semuanya tetap terorganisir tanpa duplikasi.

Referensi

  1. 1php_fastcgi Directive — Caddy Documentation
  2. 2Automatic HTTPS — Caddy Documentation
  3. 3Caddyfile Concepts — Caddy Documentation

Tentang Penulis

Abd. Asis

Abd. Asis

Software Developer dan Laravel Programmer dari Madura, Indonesia. Passionate tentang PHP, Laravel, dan teknologi web modern.

Komentar

Artikel Terkait

Artikel lain yang mungkin menarik untuk kamu