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.comcon 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, Composer vendor directory, test, composer.json file, NPM node_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:9000O 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.socke 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/teste se esiste un file in test/index.phpCaddy 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.pnge 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/etco 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 Caddy match 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.

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.

Exit mobile version