How to Series - Caddy sebagai server alternative yang simple dan menyediakan HTTPS secara otomatis
Table of Content
Reference
Summary
Caddy adalah alternatif server seperti Apache, Nginx, atau Trafik yang simple dan mudah untuk disetting diawal.
Caddy sudah include HTTPS secara default, untuk local hostname akan menggunaka self-signed certificates dan untuk public site akan menggunakan Lets Encrypt / ZeroSSL
Caddy dapat digunakan sebagai alternatif dari server seperti Apache, Nginx, atau Traefik
Disini akan membahas:
- Installation
- Contoh konfigurasi Caddy untuk Static Respond, Static Site atau Reverse Proxy
Personal Opinion
Pilihan saya untuk Caddy:
- mUntuk local development, saya prefer caddy karena se-simple sederhananya Caddyfile
- Untuk self-contained docker image, saya prefer traefik atau caddy via
caddy-docker-proxy
karena kemudahkan konfigurasi via label - Untuk self-hosted (simple), saya prefer caddy karena mudahnya Caddyfile
- Untuk self-hosted (full dengan dashboard), saya prefer Nginx Proxy Manager (via nginx) atau Pangolin (via traefik)
- Untuk production, saya prefer nginx karena full customization dan sudah mature dengan berbabagi best practice yang sudah dimiliki termasuk cache dan security
Prerequisites
How to
Installation
- create folder "conf" dan "site" didalam colder "Caddy"
- buat file Caddyfile di
conf/Caddyfile
# filename: Caddyfile
localhost:80 {
respond "hello world"
}
- pasangkan docker-compose.yml dibawah ini:
# filename: docker-compose.yml
services:
caddy:
image: [](caddy:latest)
container_name: caddy
restart: unless-stopped
cap_add:
- NET_ADMIN
ports:
- "80:80"
- "443:443"
- "443:443/udp"
volumes:
- $PWD/[](conf:/etc/caddy)
- $PWD/[](site:/srv)
- [](caddy_data:/data)
- [](caddy_config:/config)
- $PWD/index.[](html:/usr/share/caddy/index.html)
networks:
- default
volumes:
caddy_data:
caddy_config:
networks:
caddy:
- test dengan
curl [](http://localhost)
- hot reload
docker exec caddy caddy reload --adapter caddyfile --config /etc/caddy/Caddyfile
Alternatively, create a script for easy HOT Reloading with file name hot-reload.sh
#!/bin/sh
docker exec caddy caddy reload --adapter caddyfile --config /etc/caddy/Caddyfile
make it executable chmod +x hot-reload.sh
and run with command ./hot-reload.sh
Examples
Static respond
[domain] {
respond "[string]"
}
contoh:
test.com {
respond "hello world"
}
Static Site
[domain] {
root * [path]
file_server
}
contoh :
[domain] {
root * /var/www/mysite
file_server
}
Jika digunakan sebagai file listing
[domain] {
root * /var/www/mydir
file_server browse
}
Reverse Proxy
[domain] {
reverse_proxy [domain]
}
contoh, untuk docker container mycontainer
di port 8080
(kalau docker, gunakan container name, bukan localhost)
subdomain.test.com {
redir /path /real_path # optional, for redirect
reverse_proxy [](http://mycontainer:8080)
}
PHP Laravel App
ref: https://github.com/Kamleshpaul/laravel-caddy?tab=readme-ov-file
buat snippet untuk security.conf
# filename: snippets/security.conf
header {
# keep referrer data off of HTTP connections
Referrer-Policy no-referrer-when-downgrade
# Referrer-Policy "strict-origin-when-cross-origin"
# enable HSTS
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
# Enable cross-site filter (XSS) and tell browser to block detected attacks
X-Xss-Protection "1; mode=block"
# disable clients from sniffing the media type
X-Content-Type-Options "nosniff"
# clickjacking protection
X-Frame-Options "SAMEORIGIN"
Content-Security-Policy "upgrade-insecure-requests"
# hide server name
-Server Caddy
}
buat snippet untuk laravel app laravel-snippet.conf
# filename: snippets/laravel-snippet.conf
# snippets/laravel-app
# {args[0]} represents the root url of the app. Example: "exmaple.com".
# {args[1]} represents the root path to the app. Example: "/var/www/html/laravel-app"
(laravel-app) {
{args[0]} {
# apply security header
import security.conf
# Resolve the root directory for the app
root * {args[1]}/public
# Provide Zstd and Gzip compression
encode zstd gzip
# Enable PHP-FPM
# Change this based on installed php version
php_fastcgi unix//run/php/php8.3-fpm.sock
# Allow caddy to serve static files
file_server
}
}
Kemudian, isi dari Caddyfile menjadi
# filename: Caddyfile
import snippets/*
import laravel-app example.com /var/www/html/example.com
Caddyfile
Struktur dari Caddyfile antara lain ![[./assets/how-to-series---caddy/caddyfile-visual.png]]
contoh lain untuk matchers https://caddyserver.com/docs/caddyfile/matchers
Metrics via Prometheus
ref: https://github.com/Kamleshpaul/laravel-caddy/tree/main Hidupkan metrics sebagai global options block di Caddyfile
{
metrics {
per_host
}
}
Maka metrics sudah di expose di /metrics
. URL ini dapat di konfigurasi lagi via Caddyfile, contoh
example.com {
# disable
metrics /metrics {
disable_openmetrics
}
# redirect ke path lain
metrics /foo/bar/path
}
Contoh config prometheus
# prometheus.yaml
global:
scrape_interval: 15s # default is 1 minute
scrape_configs:
- job_name: caddy
static_configs:
- targets: ['[](localhost:2019)']
dan jalankan config tersebut di prometheus via
$ prometheus --config.file=prometheus.yaml
Other Reading
- Cheatsheet : Caddy
- https://syntaxlexx.medium.com/migrating-from-nginx-to-caddy-and-setting-up-the-server-the-way-i-like-it-e44cf386d5ae
- Contoh Laravel via Caddy : https://github.com/Kamleshpaul/laravel-caddy?tab=readme-ov-file