A typical web server configuration is to have Nginx as HTTP server, MySQL as data storage, PHP as programming language, and Symfony as framework. In this occasion, I will explain everything necessary to make it work on FreeBSD.
We install mysql, nginx, and php:
We configure RC to start the services on boot:
sysrc nginx_enable="yes"
sysrc php_fpm_enable="yes"
We start mysql:
We perform the initial configuration of mysql:
We configure FPM to listen on a Unix socket and assign the user with which the php code will be executed:
;listen = 127.0.0.1:9000
listen = /var/run/php-fpm.sock
listen.owner = www
listen.group = www
listen.mode = 0660
We copy the php test configuration file:
We start FPM:
We get the number of cores:
hw.ncpu: 8
We configure the nginx workers according to the number of cores and perform a test using phpinfo():
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;
}
}
}
We create the log directory and files:
touch /var/log/nginx/access.log
touch /var/log/nginx/error.log
The docroot is a symbolic link to a directory that could be modified by some OS update, we remove the link and create a directory in its place:
mkdir /usr/local/www/nginx
We start nginx:
We check that the php code is executed through FPM, a phpinfo will serve us for this purpose:
Then we delete the file:
We configure the nginx workers according to the number of cores and perform the vhost config as indicated by Symfony
here
:
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;
}
}
}
To deploy our project we will install Symfony and all the dependencies on which our code depends:
We dump the content of the web by cloning the content of the git repository or restoring a backup:
cd BACKUP
We copy the code to the nginx directory and assign the user we are using to deploy the project as the owner:
cp -r /home/kr0m/BACKUP/DOCROOT /usr/local/www/nginx/
chown -R USER:USER /usr/local/www/nginx/DOCROOT/
The user (www) with which the php code will run will need to be able to write to certain paths under var, to allow these actions ACLs are usually assigned as indicated by Symfony in its documentation , but ACLs in ZFS are not POSIX but NFS ACLs, with UFS we would not have problems with POSIX ACLs.
NOTE: For caches it is necessary to create directories with mkdir, for this we assign the append permission: p
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
We adjusted the nginx docroot to the new path:
root /usr/local/www/nginx/DOCROOT/web;
Restart nginx:
Configure a default user and password to access the mysql CLI more comfortably:
[client]
user=root
password=DATABASE_PASSWORD
Create the necessary users for the application to work:
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';
Finally, install all the bundles our app needs and clear the symfony cache:
composer install
php bin/console cache:clear --no-warmup -e prod
To debug, we can always start the embedded server that symfony brings, which will give us a lot of information about the errors produced:
We can also change the php error_reporting:
error_reporting = E_ALL
display_errors = On
display_startup_errors = On
service nginx restart
I strongly recommend filtering network traffic to allow only the services offered, as well as binding services to the loopback address whenever possible.