Come utilizzare Caddy Server basandoci su PHP
Caddy Server è una piattaforma server web modulare e moderna che supporta certificati HTTPS automatici, QUIC e HTTP/2, compressione Zstd e Brotli e varie funzionalità moderne oltre alle funzionalità classiche del server web come host virtuali configurabili, riscrittura e reindirizzamenti URL, reverse proxy e altro ancora. Caddy 2, la versione attuale rilasciata a maggio 2020, ha introdotto miglioramenti significativi alla sintassi di configurazione, all’automazione, ai plug-in e altro ancora.
Questo articolo spiega come integrare PHP con il server web Caddy versione 2 serie e la configurazione avanzata. Confronta inoltre configurazioni simili con configurazioni Apache e Nginx per facilitare la migrazione da Apache e Nginx a Caddy.
Configurazione iniziale del server
Caddy è disponibile su molti sistemi operativi e distribuzioni basate su Linux. La documentazione di Caddy spiega come installare Caddy e configurarlo come servizio/demone che viene eseguito automaticamente all’avvio del server.
Una volta installato Caddy, Caddy può essere configurato con una configurazione minima che serve file statici se sono presenti e passa altre richieste a PHP-FPM.
example.com
è il nome di dominio dell’esempio utilizzato nel resto di questo articolo e in cui vengono inseriti i relativi file di origine/var/www/example.com
con un/var/www/example.com/public/index.php
fungendo da punto di ingresso dell’applicazione web. Tutte le risorse dell’applicazione Web sono archiviate in/var/www/example.com/public
directory, ma il resto dell’applicazione (inclusi i file sorgente, Composervendor
directory, test,composer.json
file, NPMnode_modules
directory, ecc.) si trova in/var/www/example.com
.
Caddy Server viene fornito con una configurazione predefinita sicura e performante, che semplifica la configurazione con una configurazione minima.
Quando Caddy è installato e configurato come servizio di sistema, viene utilizzato il file predefinito /etc/caddy/Caddyfile
può essere utilizzato come file di configurazione globale e come sottodirectory con un nome suggerito /etc/caddy/sites
per contenere i file di configurazione per i singoli siti, simile alla configurazione di Apache e Nginx.
/etc/caddy ├── Caddyfile ├── config/ │ └── php-fpm.conf └── sites/ └── example.com.conf
Il globale Caddyfile
può specificare la configurazione globale e includere config/*
E sites/*
directory per includere la configurazione aggiuntiva.
Caddyfile
{ log default { format console output file /var/log/caddy/system.log exclude http.log.access } } import config/* import sites/*
Ciò configura Caddy per scrivere i log di sistema /var/log/caddy/system.log
file (ma non i registri delle richieste HTTP), oltre a caricare file di configurazione aggiuntivi da config
E sites
directory.
Esegui, avvia, arresta e ricarica Caddy Server
Se Caddy è installato come a systemd
servizio, systemctl
il comando può essere utilizzato per avviare, arrestare, ricaricare e riavviare il server Caddy.
Per la configurazione ad hoc, il server può essere controllato con i comandi:
systemctl start caddy caddy start caddy run # Starts server and blocks indefinitely systemctl stop caddy caddy stop systemctl reload caddy caddy reload systemctl restart caddy caddy stop && caddy start
Similmente al modo in cui il server web Apache e Nginx si integrano con PHP, anche Caddy è integrato con PHP utilizzando il proxy inverso FastCGI di Caddy.
L’idea di base è che quando Caddy riceve una richiesta che dovrebbe essere elaborata con PHP (ad esempio, una richiesta ad un nome di file con un .php
estensione), la richiesta viene inviata a PHP-FPM, dove viene eseguita l’applicazione PHP, e la risposta viene rimandata a Caddy per essere restituita all’utente.
Nella sua forma più semplice, quella che segue è una definizione del sito Caddy completamente funzionale:
/etc/caddy/sites/example.com.conf
example.com { root * /var/www/example.com/public log { output file /var/log/caddy/example.access.log format console } # Encode responses in zstd or gzip, depending on the # availability indicated by the browser. encode zstd gzip # Configures multiple PHP-related settings php_fastcgi unix//run/php/php-fpm.sock # Prevent access to dot-files, except .well-known @dotFiles { path */.* not path /.well-known/* } }
Il file di configurazione riportato sopra è un file di configurazione minimo e completo che si occupa di diversi aspetti di sicurezza e prestazioni.
Per una spiegazione completa dell’elenco completo delle direttive nonché informazioni dettagliate sulle direttive utilizzate qui, fare riferimento all’eccellente documentazione di Caddy.
Caddy fa uno sforzo in più per facilitare l’integrazione di Caddy con PHP. Il pratico php_fastcgi
la direttiva è una scorciatoia per più opzioni di configurazione che passa le richieste a PHP-FPM, tenta di caricare un file index.php
dalla directory immediata e infine riscrive tutte le richieste nella root index.php
. Questo pattern è comunemente chiamato “pattern front controller” e può essere utilizzato per la stragrande maggioranza dei framework PHP e CMS tra cui Laravel, Drupal, WordPress, Slim PHP, ecc.
Nella sua forma più semplice, php_fastcgi
accetta un argomento per il server PHP-FPM. Può essere l’indirizzo di un server e una porta (ad esempio 127.0.0.1:9000
) O un indirizzo socket di dominio Unix. Su Debian/Ubuntu/derivatives e RHEL/Fedora/derivatives, questo è quasi sempre disponibile come socket Unix, spesso adottando il modello di percorso /run/php/php[VERSION]-fpm.sock
. Ad esempio, per PHP 8.2, l’indirizzo del socket sarebbe /run/php/php8.2-fpm.sock
e PHP 8.3 a /run/php/php8.3-fpm.sock
.
Se non è possibile utilizzare un socket di dominio Unix, utilizzare l’indirizzo IP e il nome della porta.
L’indirizzo del socket del dominio Unix o l’IP/porta su cui PHP-FPM è in ascolto è configurabile dai file di configurazione PHP-FPM.
Riscrittura dell’URL in index.php
Per impostazione predefinita, il php_fastcgi
implica tre importanti riscritture degli URL:
1. Riscrivere le richieste al ./index.php
file se esiste
Se arriva una richiesta a example.com/test
e se esiste un file in test/index.php
Caddy riscrive questa richiesta nel file test/index.php
file. Questo risolve il “problema della barra finale”, dove esiste un’applicazione PHP all’interno di una sottodirectory della radice del documento.
2. Riscrivi a index.php
se un file non esiste
La seconda cosa configurata con il php_fastcgi
è che Caddy tenta di servire la richiesta con un file se esiste. Ad esempio, se l’utente richiede example.com/image.png
e se un file denominato image.png
esiste nella root del documento, Caddy lo serve come file senza invocare affatto PHP.
Quindi, se un file lo fa non esiste, cerca di cercare un index.php
file nel percorso come directory, seguito da un tentativo di riscriverlo nella radice index.php
.
Questo passaggio è simile alla seguente configurazione di Apache:
RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^ index.php [QSA,L]
… e la seguente configurazione Nginx:
try_files $uri $uri/ /index.php?$query_string;
3. Passa .php
file in PHP-FPM
Infine, il php_fastcgi
la direttiva instrada il .php
file all’indirizzo del server FPM specificato. Caddy sa come impostare correttamente i parametri FPM, dividere il percorso ed eseguire diverse altre “attività di passaggio” con impostazioni predefinite ben ponderate.
IL
php_fastcgi
La direttiva è una scorciatoia per diverse opzioni di configurazione. È possibile sovrascrivere determinati parametri o, se non è adatto a un caso d’uso particolare, utilizzare il modulo espanso per la configurazione granulare.
Se si riscrivono tutte le richieste al root index.php
il file non è necessario o non desiderabile, Caddy può essere configurato per passarlo tutto .php
file in PHP-FPM senza riscritture:
route { # Add trailing slash for directory requests @canonicalPath { file {path}/index.php not path */ } redir @canonicalPath {http.request.orig_uri.path}/ 308 # If the requested file does not exist, try index files @indexFiles file { try_files {path} {path}/index.php split_path .php } rewrite @indexFiles {file_match.relative} # Proxy PHP files to the FastCGI responder @phpFiles path *.php reverse_proxy @phpFiles <php-fpm_gateway> { transport fastcgi { split .php } } }
Questa configurazione è quasi identica alla forma estesa, ma lo fa non riscrivere alla base index.php
file:
# If the requested file does not exist, try index files @indexFiles file { - try_files {path} {path}/index.php index.php + try_files {path} {path}/index.php split_path .php } rewrite @indexFiles {file_match.relative}
Caddy viene fornito con diversi miglioramenti delle prestazioni integrati e ottimizzati per impostazione predefinita.
Ad esempio, il encode zstd gzip
La direttiva fa sì che Caddy codifichi le risposte zstd
O gzip
se il browser indica nell’intestazione della richiesta che il browser può gestirli. Caddy invia anche il file Vary: Accept-encoding
per impostazione predefinita, in modo che i CDN e le altre cache sappiano di non segmentare la cache in base al file Accept-encoding
valore. Sono piccole cose come queste che rendono Caddy un server moderno e supponente con impostazioni predefinite piacevoli.
Inoltre, Caddy v2.7 ha diverse ottime funzionalità di sicurezza e prestazioni abilitate per impostazione predefinita, incluso il supporto HTTP/3 e TLS 1.3, supporto di pinzatura OCSP (in modo che i browser non debbano interrogare un server OCSP per verificare la validità del certificato), Alt-Svc automatico intestazioni, certificati doppi RSA+ECC e altro ancora.
Effettua richieste HTTP/3 con l’estensione PHP Curl
Come effettuare richieste HTTP HTTP/3 utilizzando l’estensione PHP Curl, oltre a come compilare Curl con il supporto HTTP/3 per PHP.
Per PHP, è possibile utilizzare alcune modifiche aggiuntive alle prestazioni, se applicabili:
Veloce 404 pagine
Invece di riscrivere Tutto richieste al index.php
file, a volte ha senso cortocircuitare e terminare immediatamente la risposta se l’URI della richiesta riguarda un file statico che l’applicazione PHP non gestisce.
Di seguito è riportato uno snippet di esempio che corrisponde alle richieste in arrivo per determinate estensioni (come .jpg
, .png
, .woff2
, ecc.) e restituisce immediatamente una risposta di pagina non trovata se tale file non esiste. Ciò impedisce di richiamare inutilmente PHP (potenzialmente più costoso e spesso richiede anche una connessione al database) solo per generare un errore di pagina non trovata dall’applicazione.
@static_404 { path_regexp .(jpg|jpeg|png|webp|gif|avif|ico|svg|css|js|gz|eot|ttf|otf|woff|woff2|pdf)$ not file } respond @static_404 "Not Found" 404 { close }
Il server web Apache viene fornito con un modulo denominato Expires (mod_expires
) che fornisce diverse direttive da servire facilmente Cache-Control
E Expires
intestazioni. Expires
l’intestazione è obsoleta, il che lascia Cache-Control
l’intestazione che decide l’intestazione utilizzata dai browser per controllare la cache per la richiesta.
Sebbene Caddy non fornisca un modulo dedicato o una serie di direttive a questo scopo, è possibile utilizzare il file esistente header
direttiva da inviare Cache-Control
intestazioni:
@static { path_regexp .(jpg|jpeg|png|webp|gif|avif|ico|svg|css|js|gz|eot|ttf|otf|woff|woff2|pdf)$ } header @static Cache-Control "max-age=31536000,public,immutable"
Questo frammento viene inviato Cache-Control: max-age=31536000,public,immutable
a tutte le richieste che terminano con jpg/jpeg/png/etc
o tipi di file altrimenti statici. Combinati con Fast 404, queste modifiche possono fare in modo che Caddy serva file statici in modo rapido ed efficiente utilizzando anche le cache del browser/CDN.
IL
match
direttiva
Quello di Caddymatch
La direttiva può essere utilizzata per impostare le intestazioni in base alle intestazioni della risposta.
Una delle caratteristiche principali di Caddy è che supporta HTTPS automatico. Ciò include l’ottenimento di un certificato valido (utilizzando il protocollo ACME) da autorità di certificazione come LetsEncrypt e ZeroSSL, nonché reindirizzamenti HTTPS automatici.
Imposta inoltre un insieme altamente bilanciato e sicuro di valori di configurazione per le curve di scambio TLS e le tute di crittografia, continuando a garantire che la configurazione predefinita sia sempre sicura.
È possibile disattivare il certificato TLS automatico e i reindirizzamenti se si desidera ottenere, convalidare e rinnovare i certificati con altri mezzi. Poiché Caddy è sempre configurato con impostazioni predefinite ragionevoli e sicure, PHP.Watch non consiglia di modificare le opzioni di configurazione predefinite relative a TLS/HTTPS.
Una delle modifiche di sicurezza più semplici ed efficaci che un sito Web può apportare è l’invio di intestazioni di sicurezza aggiuntive lungo l’applicazione. Questo può variare da intestazioni potenti e dettagliate come CSP e Permissions-Policy a intestazioni come HSTS e X-Content-Type-Options
.
Quanto segue mostra un insieme supponente di intestazioni di sicurezza impostate da un file di configurazione Caddy. È molto probabile che l’esempio seguente non si applichi a nessun sito web reale, ma sia semplicemente un punto di partenza:
header { Strict-Transport-Security "max-age=31536000;includeSubDomains;preload" X-Frame-Options "SAMEORIGIN" X-Xss-Protection "1;mode=block" Referrer-Policy "no-referrer-when-downgrade" X-Content-Type-Options "nosniff" Permissions-Policy "autoplay=(self),camera=(),geolocation=(),microphone=(),payment=(),usb=()" ?Content-Security-Policy "default-src 'self';script-src 'self';style-src 'self'" }
Caddy supporta prefissi di intestazione come
?
che dice a Caddy di inviare l’intestazione solo se non è già impostata, oppure-
per eliminare l’intestazione se presente.
Flag dei cookie sullo stesso sito
Utilizzando le potenti funzionalità di modifica dell’intestazione di Caddy, è possibile migliorare la sicurezza dei cookie HTTP impostati dall’applicazione modificando il file Set-Cookie
intestazione:
header >Set-Cookie (.*) "$1; SameSite=Lax;"
Tieni presente che per le applicazioni PHP che utilizzano sessioni PHP, è consigliabile utilizzare l’impostazione PHP INI incorporata per i cookie SameSite.
Metodi di richiesta dei limiti
Se l’applicazione PHP non è progettata per gestire determinati metodi di richiesta HTTP, o se semplicemente non è tenuta a gestire determinati metodi HTTP, è possibile consentire l’elenco dei metodi di richiesta HTTP, facendo in modo che il Caddy rifiuti tutti gli altri tipi di richiesta:
@requestMethodsList { not method GET HEAD POST OPTIONS } respond @requestMethodsList "Not Allowed" 405 { close }
Questo è simile a quello di Apache AllowMethods
direttiva:
<Location /> AllowMethods GET HEAD POST OPTIONS </Location>
… e quello di Nginx limit_except
:
limit_except GET HEAD POST OPTIONS { deny all; }
Alcune modifiche aggiuntive possono assistere PHP e organizzare le direttive Caddy per allinearle con l’applicazione PHP.
Proxy affidabili
Quando Caddy è dietro un proxy, un bilanciatore di carico o un CDN, l’indirizzo IP del client osservato dall’applicazione PHP e dal Caddy stesso verrà impostato sull’indirizzo IP del livello superiore e non sul client reale.
Questo viene risolto impostando gli indirizzi IP statici del proxy/bilanciatore/CDN, facendo in modo che Caddy convalidi l’indirizzo IP di origine affinché sia nell’elenco dei proxy attendibili e utilizzi l’indirizzo IP del client dal (configurabile) X-Forwarded-For
intestazione.
Ad esempio, se è presente un bilanciatore del carico con indirizzo IP 192.168.1.16:
trusted_proxies static 192.168.1.16
Poiché Caddy si occupa della validazione vera e propria, l’applicazione PHP può fare affidamento sull’indirizzo IP del client senza doverlo verificare nuovamente.
Richiedi dimensioni corpo e limiti di caricamento PHP {#request-body}
Caddy supporta facoltativamente l’applicazione di un limite massimo di dimensioni del corpo per le richieste HTTP. Se questo valore è inferiore a quello di PHP post_max_size
(che a sua volta oscura il upload_max_filesize
), Caddy terminerà la richiesta prima che venga consegnata a PHP.
request_body { max_size 20MB }
Impostazione a request_body
max_size
può aiutare ad alleviare i comportamenti a volte imprevedibili di PHP su richieste che superano i limiti post_max_size
.
Configurazione modulare e riutilizzabile
Quando una singola istanza di Caddy serve più siti Web e ovunque abbia senso, Caddy supporta non solo l’importazione di file di configurazione (come mostrato nell’immagine principale Caddyfile
esempio sopra), ma singole sezioni.
/etc/caddy/config/php.conf
(php83) { php_fastcgi unix//run/php/php8.3-fpm.sock } (php82) { php_fastcgi unix//run/php/php8.2-fpm.sock }
Le singole sezioni ((php83)
E (php82)
da questo esempio) può ora essere utilizzato in qualsiasi altro file di configurazione:
/etc/caddy/sites/example.com.conf
example.com { root * /var/www/example.com/public import php83 # ... }
Riepilogo
Caddy è un server web moderno con una configurazione predefinita sensata, veloce e sicura. Supporta HTTP/3 e TLS 1.3 immediatamente, HTTPS automatico e gestione della durata dei certificati e si integra bene con PHP.
Caddy può essere integrato con PHP utilizzando la più comune riscrittura del “front controller” o per servire singoli file PHP tramite PHP-FPM.
Se ottimizzato con ulteriori modifiche alle prestazioni e alla sicurezza, Caddy può fornire contenuti dinamici e statici con intestazioni di sicurezza e memorizzazione nella cache aggiuntive, pagine Fast 404 e altre best practice. Inoltre, i limiti di richiesta e i proxy affidabili in Caddy possono essere configurati per corrispondere all’applicazione PHP per alleviare alcuni comportamenti imprevedibili con PHP, nonché per semplificare alcune attività come l’applicazione di indirizzi IP proxy affidabili.