Esta pagina se ve mejor con JavaScript habilitado

Nginx, Php-FPM, MySQL, Symfony en FreeBSD

 ·  🎃 kr0m

Una configuración típica en servidores web es tener Nginx como servidor HTTP, MySQL como almacenamiento de datos, PHP como lenguaje de programación y Symfony como framework, en esta ocasión explicaré todo lo necesario para hacerlo andar sobre FreeBSD.

Instalamos mysql, nginx y php:

pkg install mysql80-server nginx php73 php73-mysqli

Configuramos RC para que los servicios arranquen en el boot:

sysrc mysql_enable="yes"
sysrc nginx_enable="yes"
sysrc php_fpm_enable="yes"

Arrancamos mysql:

service mysql-server start

Realizamos la configuración inicial de mysql:

mysql_secure_installation

Configuramos el FPM para que escuche en un socket Unix y asignamos el usuario con el que se ejecutará el código php:

vi /usr/local/etc/php-fpm.d/www.conf

;listen = 127.0.0.1:9000
listen = /var/run/php-fpm.sock
listen.owner = www
listen.group = www
listen.mode = 0660

Copiamos el fichero de configuración de prueba de php:

cp /usr/local/etc/php.ini-production /usr/local/etc/php.ini

Arrancamos el FPM:

service php-fpm start

Sacamos el número de cores:

sysctl hw.ncpu

hw.ncpu: 8

Configuramos los workers de nginx según el número de cores y realizamos una prueba mediante phpinfo():

vi /usr/local/etc/nginx/nginx.conf

user  www;
worker_processes  8;
error_log /var/log/nginx/error.log info;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    access_log /var/log/nginx/access.log;

    sendfile        on;
    keepalive_timeout  65;

    server {
        listen       80 default_server;
        root /usr/local/www/nginx;

        location / {
            try_files $uri /app.php$is_args$args;
        }

    location ~ \.php(/|$) {
        fastcgi_pass unix:/var/run/php-fpm.sock;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        fastcgi_param DOCUMENT_ROOT $realpath_root;
    }
    location ~ \.php$ {
        return 404;
    }

    }
}

Creamos el directorio y los ficheros de log:

mkdir -p /var/log/nginx
touch /var/log/nginx/access.log
touch /var/log/nginx/error.log

El docroot es un enlace simbólico a un directorio que podría ser modificado por alguna actualización del SO, eliminamos el enlace y creamos un directorio en su lugar:

rm /usr/local/www/nginx
mkdir /usr/local/www/nginx

Arrancamos nginx:

service nginx start

Comprobamos que se ejecuta el código php mediante FPM, un phpinfo nos servirá para tal propósito:

echo "<?php phpinfo(); ?>" > /usr/local/www/nginx/info.php

Acto seguido eliminamos el fichero:

rm /usr/local/www/nginx/info.php

Configuramos los workers de nginx según el número de cores y realizamos la config del vhost según indica Symfony aquí :

vi /usr/local/etc/nginx/nginx.conf

user  www;
worker_processes  8;
error_log /var/log/nginx/error.log info;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    access_log /var/log/nginx/access.log;

    sendfile        on;
    keepalive_timeout  65;

    server {
        listen       80 default_server;
        root /usr/local/www/nginx;

        location / {
            try_files $uri /app.php$is_args$args;
        }

    location ~ ^/app\.php(/|$) {
        fastcgi_pass unix:/var/run/php-fpm.sock;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        fastcgi_param DOCUMENT_ROOT $realpath_root;
    }
    location ~ \.php$ {
        return 404;
    }

    }
}

Para desplegar nuestro proyecto instalaremos symfony y todas las dependencias de las que dependa nuestro código:

pkg install php73-composer php73-ctype php73-curl php73-dom php73-filter php73-hash php73-intl php73-json php73-mbstring php73-mysqli php73-openssl php73-pdo php73-pdo_mysql php73-pecl-memcached php73-phar php73-session php73-tokenizer php73-xml php73-simplexml php73-iconv

Volcamos el contenido de la web clonando el contenido del repositorio git o restaurando un backup:

tar xvzf BACKUP
cd BACKUP

Copiamos el código al directorio de nginx y le asignamos como propietario el usuario que estemos utilizando para desplegar el proyecto:

su -l
cp -r /home/kr0m/BACKUP/DOCROOT /usr/local/www/nginx/
chown -R USER:USER /usr/local/www/nginx/DOCROOT/

El usuario(www) con el que correrá el código php necesitará poder escribir en ciertos paths bajo var, para permitirle estas acciones se suelen asignar ACLs como indica symfony en su documentación , pero las ACLs en ZFS no son POSIX si no ACLs NFS , con UFS no tendríamos problemas con las ACLs POSIX.

NOTA: Para las caches es necesario crear directorios con mkdir para ello asignamos el permiso append: p

find var -type f -exec setfacl -m u:www:rwx:allow {} ;
find var -type d -exec setfacl -m u:www:rwxp:fd:allow {} ;
find var -type f -exec setfacl -m u:USER:rwx:allow {} ;
find var -type d -exec setfacl -m u:USER:rwxp:fd:allow {} ;
exit

Reajustamos el docroot de nginx al nuevo path:

vim /usr/local/etc/nginx/nginx.conf

        root /usr/local/www/nginx/DOCROOT/web;

Reiniciamos nginx:

service nginx restart

Configuramos un usuario y password por defecto con el que poder acceder a la CLI de mysql de forma mas cómoda:

vim .my.cnf

[client]
user=root
password=DATABASE_PASSWORD

Creamos los usuarios necesarios para que la aplicación funcione:

root@localhost [mysql]> create user DBUSERNAME@'localhost' identified with mysql_native_password by 'XXXXXXXXXXXXXX';
root@localhost [mysql]> grant all privileges on DB.* to DBUSERNAME@'localhost';

Finalmente instalamos todos los bundles que necesita nuestra app y limpiamos la caché de symfony:

cd /usr/local/www/nginx/DOCROOT
composer install
php bin/console cache:clear --no-warmup -e prod

Para debugear siempre podemos arrancar el servidor empotrado que trae symfony, el cual nos dará mucha información sobre los errores producidos:

php bin/console server:run

También podemos cambiar el error_reporting de php:

vi /usr/local/etc/php.ini

error_reporting = E_ALL
display_errors = On
display_startup_errors = On
service php-fpm restart
service nginx restart

Recomiendo encarecidamente filtrar el tráfico de red para permitir únicamente los servicios ofrecidos además de bindear a la dirección de loopback los servicios siempre que sea posible.

Si te ha gustado el artículo puedes invitarme a un RedBull aquí