Destacada para Raspberry PiHoy vamos a ver cómo instalar un entorno LEMP. ¿Y qué diantres es eso? No es más que la plataforma compuesta por las siguientes tecnologías: Linux, Nginx, MySQL y PHP (en algunos casos suele referirse a Perl). Viene siendo un LAMP de toda la vida pero sustituyendo Apache por Nginx. Cada entorno LAMP y LEMP puede integrar el soporte para PHP y otros lenguajes de programación de distintas maneras, en ocasiones, de forma demasiado heterogénea.

En este manual veremos cómo integrar el soporte para PHP utilizando el servidor de aplicaciones uWSGI, que es un servidor que puede ejecutar cualquier aplicación web desarrollada en los lenguajes Python, Lua, Perl, Ruby, Erlang, PHP, Go, Java, Mono, JavaScript V8 y también con CGIs. He elegido uWSGI porque me ofrece una forma unificada y simple de instalar aplicaciones web basadas en distintas tecnologías.

Durante el manual simularemos la creación de un sitio web con la URL http://website.com, por eso esa es la dirección que aparecerá durante la configuración de Nginx y también veremos directorios llamados websitecom. Sólo es un convenio de nombres que utilizo para mantener la coherencia y facilitar la administración.

Instalación del entorno LEMP

Instalamos Nginx, uWSGI, PHP, MySQL y también Apache 2 utils, que es un conjunto de herramientas que facilitan la administración de cualquier servidor web, entre ellas la más conocida es htpasswd.

# apt-get install nginx uwsgi apache2-utils libphp5-embed php5-mysql mysql-server

uWSGI es compatible con una amplia variedad de lenguajes de programación a través de plugins que se encuentran en los repositorios. De momento sólo nos interesa el soporte para PHP, pero resulta que este plugin aún no está disponible para Wheezy. Para instalarlo, bajaremos las fuentes de uWSGI y compilaremos el plugin. No os angustiéis, es sencillo 🙂

Primero instalamos los paquetes necesarios para compilar:

# apt-get install php5-dev build-essential libxml2-dev libcurl3-gnutls-dev libonig-dev libdb-dev libqdbm-dev libbz2-dev libpcre3-dev

A continuación descargamos el código fuente de uWSGI (Si al intentar descargar el código recibimos el error E: You must put some ‘source’ URIs in your sources.list, aquí está la solución):

# apt-get source uwsgi

Junto con otros archivos, se habrá descargado el directorio uwsgi-1.2.3+dfsg, aquí encontramos el código fuente de uWSGI. Dentro del mismo, se encuentra el directorio debian/buildconf/, es donde se guardan los ficheros de configuración para la compilación. En ese directorio tenemos el archivo uwsgi-plugin.ini.in. Para que el proceso de compilación tenga en cuenta este fichero, hay que renombrarlo eliminándole la extensión .in. Pero en lugar renombrarlo, vamos a copiarlo, la experiencia en la administración de sistemas te enseña que siempre es mejor copiar y mantener los archivos originales lo más intactos posible:

# cd uwsgi-1.2.3+dfsg/debian/buildconf/
# cp uwsgi-plugin.ini.in uwsgi-plugin.ini

Ahora editamos el fichero con nuestro editor favorito, en mi caso, con vi:

# vi uwsgi-plugin.ini

Y sustituimos la palabra @@curdir@@ por la ruta del directorio que alberga el código fuente, o sea, /root/uwsgi-1.2.3+dfsg, quedando el fichero de forma similar a la siguiente:

[uwsgi]
inherit = /root/uwsgi-1.2.3+dfsg/debian/buildconf/uwsgi-core.ini
bin_name = uwsgi-core-local
plugin_dir = /root/uwsgi-1.2.3+dfsg

Compilamos el plugin:

# cd /root/uwsgi-1.2.3+dfsg/
# python uwsgiconfig.py --plugin plugins/php debian/buildconf/uwsgi-plugin.ini

Ahora instalamos el plugin, copiándolo en el directorio de plugins de uWSGI. El directorio no existe porque aún no hemos instalado ningún plugin con él, así que lo creamos nosotros mismos. Este directorio es /usr/lib/uwsgi/plugins/. ¿Que cómo lo sé? Porque miré qué directorio se creaba en el sistema al instalar un plugin de uWSGI a través de APT. Creamos el directorio, copiamos allí el plugin y le aplicamos los permisos correspondientes después:

# mkdir -p /usr/lib/uwsgi/plugins/
# cp php_plugin.so /usr/lib/uwsgi/plugins/
# chmod 644 /usr/lib/uwsgi/plugins/php_plugin.so

Ahora nos queda el detalle final. El plugin PHP de uWSGI utiliza los archivos del paquete libphp5-embed de los repositorios, pero al instalarlo, este no añade en /usr/lib/ un enlace a la librería libphp5, por lo que aún uWSGI no funcionaría. Creamos el enlace:

# ln -s /usr/lib/php5/libphp5-5.4.4-14+deb7u7.so /usr/lib/

Como apunte final de esta sección, comentar que siempre que se actualice la versión de uWSGI tendremos que recompilar el plugin y que siempre que se acualice la versión de libphp5-embed deberemos eliminar el enlace simbólico y apuntarlo hacia la nueva librería que se instalará.

Observaciones de seguridad

Configuraremos uWSGI para que cada aplicación web se ejecute con su propio usuario del sistema. Por lo que cada una de ellas tendrá su propio directorio al que los demás usuarios, incluídos los sitios web que se ejecutan con esos otros usuarios, no podrán acceder. De esta forma garantizamos la seguridad y el aislamiento de cada aplicación web en caso de que la seguridad se vea comprometida en cualquiera de ellas.

Cuando ejecutamos las aplicaciones web, el servidor de aplicaciones uWSGI es quién accede al directorio de la aplicación ejecutándola y después intercambia la información con el servidor web, quien a su vez interactúa con el navegador web del usuario. El servidor web ni siquiera puede acceder al directorio de la aplicación, limitándose su función al de capa web intermedia que se comunica con uWSGI a través de sockets UNIX o sockets TCP, por lo que el site carece de un root (DocumentRoot en Apache) en su Server Block (VirtualHost en Apache). Esta configuración se realiza para aplicaciones web programadas en Python o Ruby, entre otras. Pero debido a la arquitectura de las aplicaciones desarrolladas en PHP, donde el código HTML y PHP se entremezclan demasiado, es necesario que el servidor web pueda acceder al directorio de la aplicación para poder funcionar correctamente.

Los servidores web, al menos en el caso de Apache y de Nginx, no son capaces de ejecutar cada site con un usuario del sistema propio, todos los sites se ejecutan usando el mismo, que en el caso de Debian y derivados se llama www-data. Esto hace que la configuración arriba mencionada no sea adecuada, porque si el servidor web no puede acceder al directorio de la aplicación, esta no funcionará.

Solucionaremos este problema creando un grupo que llamaremos services, al que en el futuro también podríamos añadir usuarios de otros servicios, por ejemplo el de un servicio de backup. De momento sólo usaremos este grupo para el usuario del servidor web, así que añadiremos el usuario www-data en el mismo:

# groupadd services
# adduser www-data services

Creación de la estructura de directorios para el site

Creamos el server block que alojará la aplicación web. El directorio home del usuario será el habitual en sistemas GNU: /home/usuario. A continuación definiremos los permisos que el propietario, el grupo services y los demás tendrán en este directorio. Crearemos la siguiente estructura de directorios:

  • /home/usuario: Directorio home del usuario de la aplicación.
  • /home/usuario/www: Directorio root del Server Block de Nginx.
  • /home/usuario/logs: Directorio de logs para Nginx y uWSGI.

Como la versión de uWSGI de los repositorios no permite configurar el lugar donde se guardan los logs, crearemos un enlace simbólico hacia los mismos aunque aún no estén creados, pues sabemos cuál será su ubicación y su nombre de fichero. ¿Cómo lo sé? Pues mirando dónde se alojaban estos logs en instalaciones anteriores de uWSGI. De todas formas, sí que es posible modificar ciertos parámetros como el de los logs, pero como es algo tedioso y un proceso a repetir en cada actualización de uWSGI, mejor dejamos ese análisis para otra entrada de este blog. Vamos a crear esa estructura:

# useradd websitecom -s /bin/bash -m
# passwd websitecom
# su websitecom -c 'mkdir ~/www'
# chgrp services /home/websitecom/ /home/websitecom/www/
# chmod 770 /home/websitecom/ /home/websitecom/www
# mkdir /home/websitecom/log
# chmod 775 /home/websitecom/log
# ln -s /var/log/uwsgi/app/website.com.log /home/websitecom/log/uwsgi-website.com.log

Creación de la aplicación en uWSGI

Tal y como comentamos anteriormente, uWSGI se encarga de ejecutar la aplicación y de comunicarse con Nginx. Así que ahora crearemos el fichero de configuración para que uWSGI lo lea y ejecute la aplicación cuando arranque. Creamos el fichero, es muy importante que su extensión sea .ini, de lo contrario uWSGI la ignorará y no la lanzará:

# vi /etc/uwsgi/apps-available/website.com.ini

Le añadimos la configuración necesaria: el támaño máximo de subida de ficheros, el plugin y el usuario que ejecutarán la aplicación, etc. La configuración es muy sencilla y se explica muy claramente ella solita:

[uwsgi]
plugins = php
php-set = post_max_size = 10M
php-set = upload_max_filesize = 10M
uid = websitecom
gid = websitecom
chdir = /home/websitecom/www
chown-socket = www-data:www-data
logfile-chown = websitecom
logfile-chmod = 400
master = 1
cheaper = 1

uWSGI sólo ejecuta los archivos .ini, pero únicamente si se encuentran en el directorio apps-enabled, muy al estilo de los VirtualHost de Apache o los Server Block de Nginx. Haremos un enlace simbólico en el directorio apps-enabled que apuntará hacia el fichero que acabamos de crear en apps-available, finalmente reiniciamos el servicio uWSGI para que arranque la aplicación web:

# ln -s /etc/uwsgi/apps-available/website.com.ini /etc/uwsgi/apps-enabled/
# service uwsgi restart

Podemos comprobar que todo ha ido consultando los logs en /home/websitecom/log/uwsgi-website.com.log.

Creación del Server Block en Nginx

¡Ánimo! Ya entramos en el tramo final del manual 🙂 Ahora crearemos el Server Block en Nginx para que se comunique con la aplicación web a través del root y del socket. Creamos el fichero en /etc/nginx/sites-available/website.com:

# vi /etc/nginx/sites-available/website.com

Añadimos todos los parámetros, incluído el socket a través del que Nginx se comunicará con uWSGI:

server {
    server_name website.com;

    root /home/websitecom/www;
    index index.php;
    autoindex off;

    client_max_body_size 10M;

    error_page 403 /core/templates/403.php;
    error_page 404 /core/templates/404.php;

    location ~ ^(?<script_name>.+?\.php)(?<path_info>/.*)?$ {
        include uwsgi_params;
        uwsgi_intercept_errors on;
        uwsgi_modifier1 14;
        uwsgi_pass unix:/run/uwsgi/app/website.com/socket;
    }

    access_log /home/websitecom/log/nginx-website.com-access.log;
    error_log /home/websitecom/log/nginx-website.com-error.log;
}

De forma similar que con uWSGI, enlazamos el site de sites-available a sites-enabled y reiniciamos el servicio:

# ln -s /etc/nginx/sites-available/website.com /etc/nginx/sites-enabled/
# service nginx restart

Comprobación

Ahora realizaremos una sencilla comprobación. Crearemos un script que nos dirá bajo que usuario se ejecuta el site y nos mostrará la información de nuestra instalación de PHP.

# su websitecom -c "echo '<?php print exec(whoami); phpinfo(); ?>' > /home/websitecom/www/index.php"

Accedemos desde nuestro navegador favorito a la dirección http://website.com/ y veremos una primera línea que dice websitecom, ese es el usuario que está ejecutando el site, significa que lo hemos hecho bien. Debajo veremos las tablas que genera la función phpinfo() mostrándonos toda la configuración de nuestra instalación de PHP. Si no tienes un servidor DNS que resuelva ese nombre de dominio, recuerda que puedes contar con el siempre tan socorrido fichero /etc/hosts para que relaciones cualquier nombre de dominio con cualquier dirección IP en tu máquina local.

Una vez comprobado que el sistema está funcionando, lo limpiamos, eliminando el código fuente de uWSGI y el script PHP que acabamos de crear.

# rm -rf /root/uwsgi-1.2.3+dfsg*
# rm /home/docsotzarrilan/www/index.php

¡Felicidades! ¡El sistema ya está terminado!

Recuerda que esta es una instalación LEMP básica, por lo que probablemente te faltarán algunos módulos de PHP requeridos por las aplicaciones web que instales en este Server Block, como por ejemplo cURL, GD, Mcrypt o la mismísima herramienta PEAR. Mira las dependencias de cada aplicación web desarrollada en PHP que vayas a desplegar e instala los módulos necesarios.

Ahora podrás instalar aplicaciones como Drupal, Mediawiki, Moodle, OwnCloud, PrestaShop o WordPress. Ten en cuenta que Nginx no soporta los ficheros .htaccess de Apache y que muchas de estas aplicaciones PHP utilizan estos ficheros para su definir las URLs amigables y otras configuraciones. Estas redirecciones y configuraciones deberás definirlas en el Server Block de Nginx. Eso lo veremos en otra entrada, porque ya hemos tenido suficiente por hoy 🙂

Instalación de entorno web LEMP (PHP) en Debian y Raspbian Wheezy
Etiquetado en:                                                    

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.