Table of Contents

Configurazioni Apache

Cambiamenti tra Apache 2.2 e Apache 2.4

Vedere questo HOWTO: Upgrading to 2.4 from 2.2.

In Debian Jessie è stato introdotto Apache 2.4 al posto del 2.2, anche il sistema di configurazione è cambiato leggermente.

Invece della directory /etc/apache2/conf.d/ abbiamo /etc/apache2/conf-enabled/ che contiene dei link a /etc/apache2/conf-available/.

I file di configurazione in /etc/apache2/sites-enabled/ devono terminare con l'estensione .conf.

La direttiva NameVirtualHost *:80 e analoga per la porta 443 non serve più.

Una directory pubblicata tramite Alias deve avere l'opzione Require all granted altrimenti ogni tentativo di accedere al suo contenuto risulta in un errore AH01630: client denied by server configuration.

Una delle modifiche classiche da fare è la seguente:

# Configuration for Apache 2.2
Order allow,deny
Allow from all
# Configuration for Apache 2.4 with mod_authz_host.
Require all granted

In maniera analoga per negare ogni richiesta:

# Configuration for Apache 2.2
Order deny,allow
Deny from all
# Configuration for Apache 2.4 with mod_authz_host.
Require all denied

Un controllo di accesso basato sull'indirizzo IP è fatto in questo modo:

Require local
Require ip 127.0.0.0/8 ::1 185.21.73.97 10.0.1.0/24

Un'altro cambiamento non da poco è la direttiva AllowOverride, che adesso ha valore predefinito None. Questo significa ad esempio che tutti i file .htaccess smettono di funzionare!

Character set e language

Per default ogni pagina pubblicata da Apache viene annunciata come charset ISO-8859-1 (direttiva AddDefaultCharset on). Per servire delle specifiche pagine in altro set di caratteri (esempio cirillico con il set WINDOWS-1251 o cinese semplificato con il set GB2312), si aggiungono le seguenti direttive nel file di configurazione di Apache:

<Directory /home/vill-ftp/www/>
    AddLanguage ru .ru
    AddLanguage zh .zh
    AddCharset WINDOWS-1251 .cp-1251 .win-1251
    AddCharset GB2312 .gb2312 .gb
</Directory>

Questo significa che rinominando i file .html con il suffisso .win-1251 oppure .gb2312 si forza il relativo set di caratteri. Con la doppia estensione si imposta lingua e set di caratteri; ad esempio index.html.zh.gb verrà annunciato come un file in lingua cinese e set di caratteri cinese semplificato.

Per i file PHP si possono aggiungere degli header in questo modo:

header("Content-Type: text/html; charset=gb2312");
header("Content-Language: zh");

oppure

header("Content-Type: text/html; charset=windows-1251");
header("Content-Language: ru");

Usare Unicode invece di ISO-8859-1

Per impostare il charset di default su Apache2 si mette la seguente riga dentro la sezione relativa al VirtualHost:

AddDefaultCharset utf-8

La direttiva può altrimenti essere specificata solo per una sezione <Directory>. Ovviamente si devono creare pagine in codifica UTF-8.

Bisogna stare attenti alla funzione htmlentities() del PHP, ad esempio la seguente sequenza di byte esadecimali <E2><80><99> rappresenta l'apostrofo rovesciato (backtik) in UTF-8, ma data in pasto ad htmlentities() viene convertita in &acirc;<80><99>.

Per fortuna la funzione htmlentities() accetta un terzo parametro, il charset. Purtroppo non si trova una combinazione per far funzionare tutto e sempre. Ad esempio htmlentities(UTF-8) non converte la o-umlaut in modo adatto all'Apache con DefaultCharset UTF-8:

Codifica Intenzione htmlentities(ISO-8859-1) htmlentities(UTF-8) Buono per Apache UTF-8
<E2><80><99> apostrofo &acirc;<80><99> &rsquo; <E2><80><99>
<F6> o-umlaut &ouml; <F6> &#246;

NOTA E' sbagliato codificare la o-umlaut in <F6>, quella sarebbe la codifica in Unicode puro, non la codifica UTF-8 che è invece <C3><B6>! Vedere codifica UTF-8 su http://www1.tip.nl/~t876506/utf8tbl.html.

NOTA Per convertire in/da UTF-8 in Perl vedere http://userpage.fu-berlin.de/~ram/pub/pub_jf47hxhHHt/perl_unicode_en.

Per la codifica UTF-8 in PHP si suggerisce:

echo htmlentities($string, ENT_COMPAT, 'UTF-8');

Configurare un modulo

Come specificare alcune opzioni valide per il modulo mod_autoindex. In una sezione Directory o VirtualHost, oppure al top level del file di configurazione di Apache:

# Allow more room for file names in auto indexes.
<IfModule mod_autoindex.c>
    IndexOptions NameWidth=45
</IfModule>

Autenticazione Base

Supportata da quasi tutti i browser, però la password transita in chiaro sulla rete (a meno che non si stia usando https). Nella directory da proteggere si mette un file di nome .htaccess con qualcosa del tipo:

AuthType Basic
AuthName "Area protetta"
AuthBasicProvider file
AuthUserFile /etc/apache2/htpasswd
#Require user username1 username2
Require valid-user

Il file con le password va indicato con percorso assoluto oppure relativo alla directory di configurazione di Apache. Per gestire le password si usa il comando htpasswd, possibilmente con l'opzione -m. Il file .htpasswd può essere messo anche direttamente nella directory da proteggere, leggibile ad Apache ma possibilmente non a tutti gli altri:

-rw-r--r--  1 root root     143 Feb 23 12:02 .htaccess
-rw-r-----  1 root www-data  50 Feb 23 12:00 .htpasswd

Nella configurazione generale verificare che la directory da proteggere abbia il giusto AllowOverride. In questo esempio (Apache 2.2 e 2.4) si consente - nel file .htaccess - anche l'utilizzo dell'opzione Options +Indexes , non strettamente necessaria ai fini dell'autenticazione:

<Directory /var/www/riservata/>
    AllowOverride AuthConfig Limit Options=Indexes
</Directory>

Per sicurezza conviene inibire l'accesso ai file .ht, ecco la ricetta per Apache 2.2 e per Apache 2.4 (per Debian dovrebbe essere inclusa nella configurazione predefinita):

<Files ~ "^\.ht">
    Order allow,deny
    Deny from all
</Files>
<FilesMatch "^\.ht">
    Require all denied
</FilesMatch>

È possibile creare una eccezione all'autenticazione in una sottodirectory, creando un file .htaccess del tipo:

# Allows any user to see this directory without authentication.
Require all granted

# For Apache < 2.4
#Satisfy any

Autenticazione Digest

Rispetto all'autenticazione base c'è una maggiore sicurezza in quanto la password non transita in chiaro sulla rete, viene trasmesso un digest della password invece del clear text. Per attivare l'autenticazione di tipo Digest su una directory si aggiunge questa sezione al file di configurazione di Apache:

<Directory /var/www/niccolo/>
    BrowserMatch "MSIE" AuthDigestEnableQueryStringHack=On
    AllowOverride AuthConfig
</Directory>

Notare l'hack che Apache deve fare in modo che l'autenticazione Digest funzioni anche con il difetto di Internet Explorer. Nella directory da proteggere si salva questo file .htaccess e il relativo file .htpasswd:

Per Apache 2.2

# Per aggiungere un utente al file delle password:
# htdigest [-c] .htpasswd realm_name user1
AuthType Digest
AuthName "private area"
AuthDigestDomain /private/ http://mirror.my.dom/private/
AuthDigestProvider file
AuthUserFile /var/www/niccolo/.htpasswd
Require valid-user

Per Apache 2.0 e precedenti

# Per aggiungere un utente al file delle password:
# htdigest [-c] .htpasswd realm_name user1
AuthType Digest
AuthName "private area"
AuthDigestFile /var/www/niccolo/.htpasswd
Require user user1 user2

Il file con le password si gestisce con htdigest e contiene righe del tipo:

username:realm:0762ba1444823379febd9e3f9eb7c0aa

Autenticazione MySQL

Per Debian 4.0 (Sarge) non c'è il pacchetto libapache2-mod-auth-mysql, per fortuna si riesce ad installare quello per Debian Testing, almeno per ora. Giusto per sicurezza lo salvo anche qui: libapache2-mod-auth-mysql_4.3.9-3_i386.deb.

Nella configurazione globale di Apache ci vuole:

#--------------------------------------------------------------------------
# MySQL authentication: default access to the database.
#--------------------------------------------------------------------------
AuthMySQL_DefaultHost localhost
AuthMySQL_DefaultUser guest
AuthMySQL_DefaultPassword guest
AuthMySQL_AllowOverride On

Poi nella directory da proteggere si crea il file .htaccess con:

AuthName "Accesso riservato"
AuthType Basic
AuthBasicAuthoritative Off
Auth_MYSQL on

AuthMySQL_Host localhost
AuthMySQL_User username
AuthMySQL_Password secret

Auth_MySQL_DB dbname
Auth_MySQL_Password_Table user_auth
Auth_MySQL_Username_Field user_name
Auth_MySQL_Password_Field user_passwd

Auth_MySQL_Encrypted_Passwords Off
Auth_MySQL_Scrambled_Passwords Off
Auth_MySQL_Empty_Passwords Off

Auth_MySQL_Group_Table user_group
Auth_MySQL_Group_Field user_group

require valid-user

Importante è la direttiva AuthBasicAuthoritative Off, che non si trova documentata (forse non serviva con Apache 2.0?). In pratica senza questa direttiva viene comunque tentata l'autenticazione su file che fallisce e quindi quella su MySQL non viene neanche provata.

Autenticazione su /etc/shadow

Per autenticare gli utenti su /etc/passwd e /etc/shadow si potrebbe usare il modulo Apache di autenticazione PAM, però sarebbe necessario che apache avesse i permessi di lettura su /etc/shadow, il che non è il massimo del godimento.

Per fortuna esiste il modulo Apache mod-auth-shadow, che deve essere espressamente compilato per Apache oppure per Apache2.

In Debian il pacchetto ha subito varie vicissitudini, entrando ed uscendo dalla distribuzione ufficiale. Il risultato purtroppo è che non esiste per Apache2 né in Etch né in Lenny. Per forunta è facile ricompilarlo dai sorgenti Debian o Ubuntu.

Qui trovate un backport per Etch della versione 2.1, qui invece la versione per Lenny.

Il file di configurazione di Apache deve essere qualcosa di simile:

<Directory /var/www/admin/>
     AuthType Basic
     AuthName "Area riservata di amministrazione"
     AuthShadow on
     # AuthAuthoritative for Apache 2.0
     # AuthBasicAuthoritative for Apache 2.2
     AuthBasicAuthoritative Off
     AuthUserFile /dev/null
     Require user niccolo mario
</Directory>

Attenzione, la direttiva AuthUserFile /dev/null serve perché Apache comunque tenta l'autenticazione Basic (sebbene non autoritativa) aprendo un file password, se non lo specifichiamo si ottengono continui messaggi di errore nel log di Apache:

[Fri Sep 07 16:14:46 2007] [error] Internal error: pcfg_openfile() called with NULL filename

Controllo di accesso su indirizzo IP

Apache 2.4

La sintassi per Apache 2.4 con il modulo mod_authz_core è cambiata! Vedere Apache Module mod_authz_core. Un esempio base:

<Directory /var/www/private_dir>
Require ip 185.32.54.97 185.12.76.143
</Directory>

Per delegare completamente il controllo di accesso ad un file .htaccess è necessario mettere la direttiva AllowOverride All nella configurazione di Apache, qualcosa del genere:

<Directory /var/www/html/private>
    Options -Indexes
    AllowOverride All
</Directory>

Quindi il file .htaccess potrà includere direttive del tipo:

<IfModule authz_core_module>
    <RequireAny>
        Require host host.rigacci.org
        Require ip 111.111.222.222
    </RequireAny>
</IfModule>

Oltre alla direttiva RequireAny che richiede che sia soddisfatta almeno una delle condizioni (operatore OR), esiste la direttiva RequireAll che implica l'operatore AND per tutte le condizioni.

Apache 2.2

Per consentire l'accesso ad una directory solo a determinati indirizzi IP:

<Directory /var/www/private_dir>
    Order deny,allow
    Deny from all
    Allow from 88.57.16.27 87.241.56.133
</Directory>

La notazione supportata da Allow è molteplice:

Allow from .net example.edu A (partial) domain-name
Allow from 192.168.1.104 192.168.1.205 Full IP address
Allow from 10 172.20 192.168.2 Partial IP address
Allow from 10.1.0.0/255.255.0.0 Network/netmask pair
Allow from 10.1.0.0/16 Network/nnn CIDR specification

Verifica combinata username o indirizzo IP

Con questa configurazione di Apache 2.4 si consente l'accesso a determinati indirizzi IP oppure con autenticazione su htpasswd. Le clausole Require possono essere combinate anche in altro modo, ad esempio <RequireAll> se si desidera che siano vere entrambe. Il SSLRequireSSL evita che la pagina sia richiesta via HTTP con possibilità di sniffing della password:

<Directory "/privatedir">
    SSLRequireSSL
    # Athenticate on htpasswd file.
    AuthType Basic
    AuthName "Area privata"
    AuthBasicProvider file
    AuthUserFile /etc/apache2/htpasswd
    <RequireAny>
        Require user niccolo
        Require ip 127.0.0.0/8 ::1 192.168.3.2
    </RequireAny>
</Directory>

Se si opta per la configurazione tramite file .htaccess, la sintassi da utilizzare è la stessa, ma si deve dare l'opportuno AllowOverride:

<Directory "/var/www/html/privatedi">
    AllowOverride AuthConfig Limit
</Directory>

Logging degli errori PHP

In un sito pubblico conviene nascondere gli errori PHP (non farli vedere nella pagina web), ma piuttosto loggarli in un file apposito, questa non è la configurazione predefinita Debian Lenny. Per attivare questo:

mkdir /var/log/php
touch /var/log/php/error.log
chown www-data:adm /var/log/php/error.log
chmod 640 /var/log/php/error.log

mentre nel file /etc/php5/apache2/php.ini ci deve essere:

display_errors = Off
log_errors = On
error_log = /var/log/php/error.log

Ricordarsi di ruotare il file di log con un opportuno /etc/logrotate.d/.

Per un sito in fase di sviluppo è comodo visualizzare gli errori direttamente nella pagina web, se questo è disabilitato a livello globale, è possibile abilitarlo localmente con delle direttive in un file .htaccess:

php_flag display_errors on
php_flag display_startup_errors on
# See http://www.php.net/manual/en/errorfunc.constants.php
# 1     E_ERROR
# 2     E_WARNING
# ...
# 32767 E_ALL
php_value error_reporting 32767

Mittente mail PHP

Le mail generate da PHP hanno generalmente come mittente www-data@mailname dove mailname è il contenuto di /etc/mailname. Il mittente può essere personalizzato a livello di VirtualHost con la seguente direttiva:

php_admin_value sendmail_path "/usr/sbin/sendmail -t -i -f user@domain"

Directory e Location

Le direttive <Directory> e <Location> si assomigliano molto, la differenza sostanziale è che Directory è intesa per lavorare a livello di filesystem, mentre Location è intesa a livello di URL.

Rewrite

Esempio di rewrite da impostare in un file .htaccess per ridirigere tutte le richieste example.com verso www.example.com o viceversa:

RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^/(.*)$ http://www.example.com/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteRule ^/(.*)$ http://example.com/$1 [L,R=301]

Il flag [NC] significa no case sensitive, il flag [L] significa last rule (non se ne applicano altre), il flag [R] indica di effettuare un redirect con status code 301 Moved Permanently.

Per vedere quali regole di rewrite vengono applicate si deve abilitare nella sezione VirtualHost (per Apache 2.2):

RewriteLog "/tmp/rewrite.log"
RewriteLogLevel 2

con Apache 2.4 la sintassi è diversa:

LogLevel info rewrite:trace2

Certificato SSL

Per creare una chiave RSA e il certificato autofirmato si crea un file di configurazione /etc/apache2/ssl/www.rigacci.org.cnf:

#----------------------------------------------------------------
# Create an RSA key and a self-signed Certificate with the
# following command:
#
# openssl req -config /etc/apache2/ssl/file.cnf \
#     -new -x509 -days 1095 -nodes \
#     -keyout /etc/apache2/ssl/file.pem \
#     -out /etc/apache2/ssl/file.pem
#
# The resulting file (unencrypted otherwise Apache can't start
# automatically) will contains the RSA private key, so be sure
# to set its mode to 0400.
#----------------------------------------------------------------

[ req ]
prompt                          = no
default_bits                    = 1024
distinguished_name              = www.rigacci.org_distinguished_name

[ www.rigacci.org_distinguished_name ]
countryName                     = IT
stateOrProvinceName             = Italy
localityName                    = Firenze
organizationName                = Niccolo Rigacci
organizationalUnitName          = computer consultant
commonName                      = www.rigacci.org
emailAddress                    = webmaster@rigacci.org

Poi si esegue il comando openssl come scritto nel commento sopra. Invece nel file di configurazione di Apache (in default o in qualche VirtualHost) si mette:

SSLCertificateFile ssl/www.rigacci.org.pem

Certificato SSL per NameVirtualHost

Fino a qualche tempo fa non esisteva un meccanismo per negoziare un certificato SSL in base al nome del VirtualHost richiesto, questo significava che il certificato SSL doveva essere unico per la coppia (indirizzo IP, porta).

Con i moderni browser invece è possibile creare un certificato SSL per ogni VirtualHost e questo verrà servito opportunamente al cliente senza generare il warning dovuto alla diversità tra il nome del server richiesto e il nome dichiarato all'interno del certificato stesso.

Per ogni VirtualHost si dichiara un diverso certificato:

<VirtualHost *:443>
    SSLEngine on
    SSLCertificateFile ssl/www.example1.com.pem
    ...
</VirtualHost>

quindi si dichiara l'uso dei NameVirtualHost anche sul protocollo HTTPS:

<IfModule mod_ssl.c>
    NameVirtualHost *:443
    Listen 443
</IfModule>

Apache 2.4 VirtualHost con php-fpm 7.0

Questa è la configurazione consigliata con Debian 9 Stretch per avere quanto segue:

Installare i seguenti pacchetti:

Non sono necessari (vanno rimossi) tutti i pacchetti utilizzati per soluzioni analoghe nelle vecchie distribuzioni: libapache2-mod-fastcgi, libapache2-mod-fcgid, libapache2-mod-php, libapache2-mod-php7.0, apache2-suexec-custom.

Assicurarsi di aver abilitato il modulo proxy_fcgi e aver attivato la configurazione di php7.0-fpm:

a2enmod proxy_fcgi
a2enconf php7.0-fpm

Il funzionamento è il seguente:

  1. Apache utilizza il modulo proxy_fcgi per processare i file PHP, tramite questo chiama l'istanza opportuna di php-fpm via Unix socket.
  2. Il demone php-fpm mantiene un pool separato per ogni VirtualHost. In ciascun pool l'interprete PHP viene eseguito con un utente diverso.

I file di configurazione importanti sono:

Creando un file (ad esempio /etc/php/7.0/fpm/pool.d/www.virtualhost.it.conf) e riavviando php-fpm si crea un nuovo pool:

[www.virtualhost.it]
user = vh-user
group = vh-group
listen = /run/php/php7.0-fpm.www.virtualhost.it.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3

;php_admin_flag[display_errors] = off
;php_admin_flag[log_errors] = on
;php_admin_value[error_log] = /var/log/php/www.virtualhost.it/php_error.log

Nell'esempio sopra ci sono tre righe (commentate) con impostazioni PHP specifiche solo per questo VirtualHost. Attenzione che la directory dove creare il file di log deve essere scrivibile dall'utente e/o dal gruppo con cui viene eseguito il pool (nell'esempio sopra sono vh-user e vh-group rispettivamente).

Nella configurazione del VirtualHost si dichiara quale pool sarà usato:

<IfModule proxy_fcgi_module>
    <FilesMatch ".+\.ph(p[3457]?|t|tml)$">
        SetHandler "proxy:unix:/run/php/php7.0-fpm.www.virtualhost.it.sock|fcgi://localhost"
    </FilesMatch>
</IfModule>

Con phpinfo() si può verificare:

Apache 2.2 VirtualHost con PHP5 FastCGI e suEXEC

FIXME Questa configurazione è obsoleta per Debian 9 Stretch, dove conviene usare il pacchetto php-fpm (vedi sopra).

Caratteristiche richieste:

Anzitutto si deve scegliere l'implementazione FastCGI: in Debian abbiamo libapache2-mod-fastcgi e libapache2-mod-fcgid. La prima è non-free e considerata obsoleta, quindi si sceglie la seconda (fcgid), sebbene questa non abbia la funzione FastCgiExternalServer. Tale funzione è necessaria a connettersi all'interprete php5-fpm, quindi è necessario utilizzare l'interprete php5-cgi.

Vedere questi howto:

Pacchetti da installare:

Verificare che i moduli Apache siano attivi:

a2enmod fcgid suexec actions

Definizione di un VirtualHost

Creare un file, ad esempio /etc/apache2/sites-available/www.example1.com:

#---------------------------------------------------------------
# http://www.example1.com/
#---------------------------------------------------------------
<VirtualHost *:80>
  ServerName www.example1.com
  ServerAlias example1.com
  ServerAdmin webmaster@example1.com
  DocumentRoot /var/www/www.example1.com/
  <IfModule mod_fcgid.c>
    SuexecUserGroup filippo filippo
    <Directory /var/www/www.example1.com/>
      Options +ExecCGI
      AllowOverride All
      AddHandler fcgid-script .php
      FCGIWrapper /var/www/www.example1.com/cgi-bin/php-fcgi .php
      Order allow,deny
      Allow from all
    </Directory>
  </IfModule>
  ErrorLog ${APACHE_LOG_DIR}/www.example1.com/error.log
  CustomLog ${APACHE_LOG_DIR}/www.example1.com/access.log combined
  ServerSignature Off
</VirtualHost>
#---------------------------------------------------------------
# https://www.example1.com/
#---------------------------------------------------------------
<VirtualHost *:443>
  SSLEngine on
  SSLCertificateFile ssl/www.example1.com.pem
  ServerName www.example1.com
  ServerAlias example1.com
  ServerAdmin webmaster@example1.com
  DocumentRoot /var/www/www.example1.com/
  <IfModule mod_fcgid.c>
    SuexecUserGroup filippo filippo
    <Directory /var/www/www.example1.com/>
      Options +ExecCGI
      AllowOverride All
      AddHandler fcgid-script .php
      FCGIWrapper /var/www/www.example1.com/cgi-bin/php-fcgi .php
      Order allow,deny
      Allow from all
    </Directory>
  </IfModule>
  ErrorLog ${APACHE_LOG_DIR}/www.example1.com/error.log
  CustomLog ${APACHE_LOG_DIR}/www.example1.com/access.log combined
  ServerSignature Off
</VirtualHost>

Preparare anche la DocumentRoot e la directory con i file di log:

mkdir /var/log/apache2/www.example1.com/
touch /var/log/apache2/www.example1.com/access.log
touch /var/log/apache2/www.example1.com/error.log
chown -R root:adm /var/log/apache2/www.example1.com/
chmod 0750 /var/log/apache2/www.example1.com/
chmod 0640 /var/log/apache2/www.example1.com/*
mkdir /var/www/www.example1.com/
chown -R filippo:filippo /var/www/www.example1.com/

Nel file /etc/apache2/ports.conf si indica che vogliamo i VirtualHost anche sulla porta HTTPS:

NameVirtualHost *:80
Listen 80

<IfModule mod_ssl.c>
    NameVirtualHost *:443
    Listen 443
</IfModule>

<IfModule mod_gnutls.c>
    Listen 443
</IfModule>

Per ogni VirtualHost è possibile avere un certificato SSL separato, si parte da un file di configurazione /etc/apache2/ssl/www.example1.com.cnf:

#
# openssl req -config www.example1.com.cnf -new -x509 -days 1095 \
#     -nodes -keyout www.example1.com.pem -out www.example1.com.pem
# Set the resulting .pem file to mode 0400.
#

[ req ]
prompt                          = no
default_bits                    = 2048
distinguished_name              = www.example1.com_distinguished_name

[ www.example1.com_distinguished_name ]
countryName                     = IT
stateOrProvinceName             = Italy
localityName                    = Firenze
organizationName                = Niccolo Rigacci
organizationalUnitName          = www.example1.com
commonName                      = www.example1.com
emailAddress                    = webmaster@rigacci.org

che va compilato nel corrispondente file .pem e impostato con mode 0400.

Questo è il wrapper /var/www/www.example1.com/cgi-bin/php-fcgi che manda in esecuzione l'interprete. Nota bene: nella direttiva FCGIWrapper del VirtualHost è obbligatorio indicare un wrapper che stia nella DocumentRoot, non è possibile indicare direttamente l'interprete php cgi-bin:

#!/bin/sh
PHPRC=/etc/php5/cgi/
export PHPRC
export PHP_FCGI_MAX_REQUESTS=1000
exec /usr/lib/cgi-bin/php

ATTENZIONE Non definire la variabile PHP_FCGI_CHILDREN! Un valore maggiore di zero può causare gravi problemi di prestazioni. In alcuni howto si trova l'indicazione di impostarlo ad esempio ad 8, questo comporta che per ogni processo PHP lanciato Apache, vengono creati 8 children inutili, perchè uno solo è quello che risponde. In pratica è il modulo Apache libapache2-mod-fcgid che crea i processi PHP, non lo deve fare a sua volta il php.

Troubleshooting

Per vedere la configurazione di suEXEC (file di log, ecc.):

/usr/lib/apache2/suexec -V
 -D SUEXEC_CONFIG_DIR=/etc/apache2/suexec/
 -D AP_GID_MIN=100
 -D AP_LOG_EXEC="/var/log/apache2/suexec.log"
 -D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin"
 -D AP_UID_MIN=100

Ad esempio se si sbaglia owner del file cgi-bin in /var/log/apache2/suexec.log si legge:

[2013-03-08 11:56:47]: target uid/gid (1001/1001) mismatch with directory (0/0) or program (0/0)

Autenticazione base, variabili PHP_AUTH_USER e PHP_AUTH_PW

PHP con php7.0-fpm

Nella configurazione Debian 9 con PHP fornito dal pacchetto php-fpm (PHP via proxy FastCGI), le variabili dell'autenticazione base vengono inizializzate senza ricorrere a particolari accorgimenti.

PHP 5 con libapache2-mod-fcgid

In un ambiente FastCGI le variabili $_SERVER['PHP_AUTH_USER'] e $_SERVER['PHP_AUTH_PW'] non vengono inizializzate, per simulare il comportamento tradizionale è necessario abilitare una RewriteRule e modificare il codice PHP:

Questa la RewriteRule:

RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

Questo un esempio di codice PHP:

// Simulate PHP_AUTH_USER and PHP_AUTH_PW in a FastCGI environment.
// Requires the following rewrite rules in .htaccess:
//   RewriteEngine on
//   RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) =
    explode(':', base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));

Un esempio più complesso che evita messaggi di warning, etc.:

unset($_SERVER['PHP_AUTH_USER']);
unset($_SERVER['PHP_AUTH_PW']);
if (isset($_SERVER['HTTP_AUTHORIZATION'])) {
    $auth = $_SERVER['HTTP_AUTHORIZATION'];
    if (strtolower(substr($auth, 0, 6)) == "basic ") {
        $auth = base64_decode(substr($auth, 6));
        if (strpos($auth, ':')) {
            list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) =
                explode(':', $auth, 2);
        }
    }
}