====== Configurazioni Apache ======
===== Cambiamenti tra Apache 2.2 e Apache 2.4 =====
Vedere questo HOWTO: [[https://httpd.apache.org/docs/2.4/upgrading.html|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 **[[https://httpd.apache.org/docs/2.4/mod/core.html#allowoverride|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:
AddLanguage ru .ru
AddLanguage zh .zh
AddCharset WINDOWS-1251 .cp-1251 .win-1251
AddCharset GB2312 .gb2312 .gb
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 ''''. 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 **<80><99>** rappresenta l'apostrofo rovesciato (backtik) in UTF-8, ma data in pasto ad ''htmlentities()'' viene convertita in **â<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 ^
| <80><99> | apostrofo | â<80><99> | ’ | <80><99> |
| | o-umlaut | ö | | ö |
**NOTA** E' sbagliato codificare la o-umlaut in , quella sarebbe la codifica in Unicode puro, non la codifica UTF-8 che è invece ! 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.
IndexOptions NameWidth=45
===== 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:
AllowOverride AuthConfig Limit Options=Indexes
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):
Order allow,deny
Deny from all
Require all denied
È 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:
BrowserMatch "MSIE" AuthDigestEnableQueryStringHack=On
AllowOverride AuthConfig
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.gz|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 **[[http://sourceforge.net/projects/mod-auth-shadow/|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 **{{libapache2-mod-auth-shadow_2.1-2etch.deb.tgz|backport per Etch}}** della versione 2.1, qui invece la **{{libapache2-mod-auth-shadow_2.1-2lenny.deb.tgz|versione per Lenny}}**.
Il file di configurazione di Apache deve essere qualcosa di simile:
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
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 **[[http://httpd.apache.org/docs/2.4/mod/mod_authz_core.html|Apache Module mod_authz_core]]**. Un esempio base:
Require ip 185.32.54.97 185.12.76.143
Per delegare completamente il controllo di accesso ad un file **.htaccess** è necessario mettere la direttiva **AllowOverride All** nella configurazione di Apache, qualcosa del genere:
Options -Indexes
AllowOverride All
Quindi il file **.htaccess** potrà includere direttive del tipo:
Require host host.rigacci.org
Require ip 111.111.222.222
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:
Order deny,allow
Deny from all
Allow from 88.57.16.27 87.241.56.133
La notazione supportata da **''[[http://httpd.apache.org/docs/2.2/mod/mod_authz_host.html#allow|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 **%%%%** se si desidera che siano vere entrambe. Il **SSLRequireSSL** evita che la pagina sia richiesta via HTTP con possibilità di sniffing della password:
SSLRequireSSL
# Athenticate on htpasswd file.
AuthType Basic
AuthName "Area privata"
AuthBasicProvider file
AuthUserFile /etc/apache2/htpasswd
Require user niccolo
Require ip 127.0.0.0/8 ::1 192.168.3.2
Se si opta per la configurazione tramite file **.htaccess**, la sintassi da utilizzare è la stessa, ma si deve dare l'opportuno **AllowOverride**:
AllowOverride AuthConfig Limit
===== 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 **''[[http://httpd.apache.org/docs/2.2/mod/core.html#directory|]]''** e **''[[http://httpd.apache.org/docs/2.2/mod/core.html#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:
SSLEngine on
SSLCertificateFile ssl/www.example1.com.pem
...
quindi si dichiara l'uso dei NameVirtualHost anche sul protocollo HTTPS:
NameVirtualHost *:443
Listen 443
===== Apache 2.4 VirtualHost con php-fpm 7.0 =====
Questa è la configurazione consigliata con **Debian 9 Stretch** per avere quanto segue:
* **VirtualHost** basato su nome
* Esecuzione dei file .php con **utente diverso** per ogni VirtualHost
Installare i seguenti pacchetti:
* **apache2**
* **php-fpm**
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:
- Apache utilizza il **modulo proxy_fcgi** per processare i file PHP, tramite questo chiama l'istanza opportuna di **php-fpm** via Unix socket.
- 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:
* **''/etc/php/7.0/fpm/php.ini''**
* **''/etc/php/7.0/fpm/pool.d/''**
* **''/etc/apache2/conf-available/php7.0-fpm.conf''**
* **''/etc/apache2/sites-available/''**
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:
SetHandler "proxy:unix:/run/php/php7.0-fpm.www.virtualhost.it.sock|fcgi://localhost"
Con **''phpinfo()''** si può verificare:
* Environment -> USER
* PHP Variables -> $_SERVER['USER']
===== 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:
* VirtualHost basato su nome
* Esecuzione a nome dell'utente proprietario dei file .php
* Certificato SSL basato su nome
* File di log separati per VirtualHost
Anzitutto si deve scegliere l'implementazione FastCGI: in Debian abbiamo **[[http://qa.debian.org/popcon.php?package=libapache-mod-fastcgi|libapache2-mod-fastcgi]]** e **[[http://qa.debian.org/popcon.php?package=libapache2-mod-fcgid|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:
* **[[http://x10hosting.com/forums/vps-tutorials/148894-debian-apache-2-2-fastcgi-php-5-suexec-easy-way.html|Debian + Apache 2.2 + FastCGI + PHP 5 + suEXEC the easy way]]**
* **[[http://www.howtoforge.com/how-to-set-up-apache2-with-mod_fcgid-and-php5-on-debian-squeeze|To Set Up Apache2 With mod_fcgid And PHP5 On Debian Squeeze]]**
* **[[http://undefinederror.org/tutorials/apache2-mpm-worker-fastcgi-php5-fpm-on-debian/|Apache2 mpm worker + fastcgi + php5-fpm on debian]]** (No: usa libapache2-mod-fastcgi e php5-fpm)
* **[[http://serverfault.com/questions/344171/apache2-fcgid-not-fastcgi-with-php-fpm|Apache2 fcgid (not FastCGI) with PHP FPM]]** (fcgid not compatibile with php-fpm).
Pacchetti da installare:
* **apache2-mpm-worker**
* **apache2-suexec-custom**
* **libapache2-mod-fcgid**
* **php5-cgi**
* **libapache2-mod-fastcgi** (necessario per php5-fpm, ma non-free e obsoleto)
* **php5-fpm**
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/
#---------------------------------------------------------------
ServerName www.example1.com
ServerAlias example1.com
ServerAdmin webmaster@example1.com
DocumentRoot /var/www/www.example1.com/
SuexecUserGroup filippo filippo
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
ErrorLog ${APACHE_LOG_DIR}/www.example1.com/error.log
CustomLog ${APACHE_LOG_DIR}/www.example1.com/access.log combined
ServerSignature Off
#---------------------------------------------------------------
# https://www.example1.com/
#---------------------------------------------------------------
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/
SuexecUserGroup filippo filippo
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
ErrorLog ${APACHE_LOG_DIR}/www.example1.com/error.log
CustomLog ${APACHE_LOG_DIR}/www.example1.com/access.log combined
ServerSignature Off
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
NameVirtualHost *:443
Listen 443
Listen 443
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);
}
}
}