Configurar suPHP y userdir en Ubuntu
Mientras configuraba mi laptop con Ubuntu 12.04 llegó el momento de instalar una copia local de WordPress para trabajar sin depender de un servidor remoto.
La instalación inicial fue la habitual: Apache2, PHP, MySQL y phpMyAdmin. Todo funcionaba correctamente hasta que decidí no utilizar el sitio por omisión (/var/www) y trabajar desde mi directorio personal utilizando una dirección como:
http://localhost/~javier
Este esquema resulta mucho más cómodo para desarrollo, ya que todos los archivos pertenecen a mi usuario y no necesito modificar continuamente permisos sobre el árbol del servidor web.
Sin embargo, apareció un inconveniente.
Apache ejecuta los procesos bajo el usuario especial www-data, mientras que PHP, cuando se utiliza mediante mod_php, también se ejecuta con ese mismo usuario.
Esta configuración ofrece un excelente rendimiento porque el intérprete de PHP permanece cargado en memoria junto con Apache. El precio es que todos los scripts se ejecutan con los permisos de www-data.
El problema se hace evidente desde la instalación de WordPress.
Al intentar crear automáticamente el archivo wp-config.php, PHP no tiene permisos suficientes para escribir dentro de mi directorio personal y la instalación se detiene. Incluso si el archivo se crea manualmente, siguen apareciendo limitaciones al instalar temas, plugins, actualizar el sistema o subir archivos multimedia.
Después de darle algunas vueltas decidí utilizar userdir junto con suPHP.
Para un servidor de producción probablemente elegiría otra solución, pero para una instalación de desarrollo local la pérdida de rendimiento resulta prácticamente imperceptible y, a cambio, cada script PHP se ejecuta utilizando los permisos de mi propio usuario.
Instalar userdir para Apache2
El primer paso consiste en habilitar el módulo userdir.
sudo a2enmod userdir
sudo service apache2 restart
El comando a2enmod habilita cualquiera de los módulos disponibles en:
/etc/apache2/mods-available
creando automáticamente un enlace simbólico dentro de:
/etc/apache2/mods-enabled
Si en algún momento necesitamos deshabilitar un módulo podemos utilizar el comando inverso:
sudo a2dismod nombre_del_modulo
El segundo comando simplemente reinicia Apache para que cargue la nueva configuración.
Configurar userdir
Habilitar el módulo no es suficiente.
También debemos indicarle cómo tratar los directorios personales.
Éste es el contenido de mi archivo:
/etc/apache2/mods-available/userdir.conf
<IfModule mod_userdir.c>
UserDir public_html
UserDir disabled root
<Directory /home/*/public_html>
AllowOverride FileInfo AuthConfig Limit Indexes
Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
<Limit GET POST OPTIONS>
Order allow,deny
Allow from all
</Limit>
<LimitExcept GET POST OPTIONS>
Order deny,allow
Deny from all
</LimitExcept>
</Directory>
</IfModule>
Con esta configuración Apache buscará automáticamente el contenido publicado dentro del directorio public_html de cada usuario.
Todavía falta un paso para poder ejecutar scripts PHP desde esa ubicación.
Instalar suPHP
El siguiente paso consiste en instalar suPHP.
La función de este módulo es ejecutar el intérprete PHP utilizando los permisos del propietario del sitio, en lugar de hacerlo como www-data.
Éste era el mecanismo utilizado por muchos proveedores de hospedaje compartido, ya que permitía aislar los sitios alojados dentro del mismo servidor.
Para instalar el módulo basta con instalar el paquete:
libapache2-mod-suphp
Posteriormente debemos revisar el archivo:
/etc/apache2/mods-available/suphp.conf
Mi configuración quedó así:
<IfModule mod_suphp.c>
AddType application/x-httpd-suphp .php .php3 .php4 .php5 .phtml
suPHP_AddHandler application/x-httpd-suphp
<Directory />
suPHP_Engine on
</Directory>
# By default, disable suPHP for debian packaged web applications as files
# are owned by root and cannot be executed by suPHP because of min_uid.
#<Directory /usr/share>
# suPHP_Engine off
#</Directory>
# # Use a specific php config file (a dir which contains a php.ini file)
# suPHP_ConfigPath /etc/php4/cgi/suphp/
# # Tells mod_suphp NOT to handle requests with the type <mime-type>.
# suPHP_RemoveHandler <mime-type>
</IfModule>
Observa que las líneas correspondientes al directorio /usr/share permanecen comentadas.
Ese detalle será importante para que phpMyAdmin funcione correctamente más adelante.
Configurar suPHP
También es necesario revisar el archivo:
/etc/suphp/suphp.conf
En particular, verifica que existan las siguientes opciones.
;Path all scripts have to be in
docroot=/var/www:${HOME}/public_html:/usr/share/phpmyadmin
;Path to chroot() to before executing script
;chroot=/mychroot
; Security options
allow_file_group_writeable=true
allow_file_others_writeable=true
allow_directory_group_writeable=true
allow_directory_others_writeable=true
;Check wheter script is within DOCUMENT_ROOT
check_vhost_docroot=false
Con estos cambios permitimos que suPHP ejecute scripts ubicados dentro de nuestro directorio personal y también dentro del directorio utilizado por phpMyAdmin.
Además, habilitamos la creación de archivos y directorios por parte de PHP y desactivamos la comprobación estricta del DOCUMENT_ROOT, necesaria para esta configuración.
Configurar phpMyAdmin
El último paso consiste en ajustar la configuración de phpMyAdmin.
Edita el archivo:
/etc/apache2/conf.d/phpmyadmin.conf
y agrega al inicio las siguientes líneas:
ServerAdmin webmaster@localhost
DocumentRoot /usr/share/phpmyadmin
Con ello suPHP reconocerá correctamente ese directorio como uno de los permitidos para ejecutar scripts PHP.
Finalmente reinicia nuevamente Apache.
sudo service apache2 restart
Si todo ha quedado correctamente configurado podrás trabajar con WordPress desde tu directorio personal utilizando userdir, manteniendo los permisos de tu propio usuario y sin los inconvenientes derivados de ejecutar PHP exclusivamente como www-data.
Y