FreeBSD: налаштування FEMP – NGINX, PHP-FPM, MariaDB
0 (0)

Автор |  30/03/2026
Click to rate this post!
[Total: 0 Average: 0]

Чергова частина  налаштування Home NAS на FreeBSD, хоча тут же не про NAS, а чисто про запуск веб-сервісів.

Вся серія постів по FreeBSD та NAS починається тут – FreeBSD: Home NAS, part 1 – налаштування ZFS mirror, там станом на зараз 15 частин, але FEMP вже винесу окремо.

На моєму хості з FreeBSD (вже є) запущений мій особистий щоденник, який, як і RTFM, працює на WordPress.

Отже, для нього треба підняти стандартний стек FEMP – FreeBSD + NGINX + PHP-FPM + MariaDB, а заодно налаштувати virtualhosts для сервісів типу Grafana, VictoriMetrics VM UI, Syncthing WebUI, Jellyfin тощо.

Робити будемо базовий сетап, без FreeBSD Jails – бо це чисто домашні внутрішні сервіси, але колись, у 2011-2013 роках, блог RTFM працював саме на такому сетапі, хіба що тоді ще була MySQL, а не MariaDB.

На цьому хості зараз FreeBSD v14.3, але принципової різниці з 15 нема.

Налаштування SSL буде окремим постом, із self-signed sertificate – тут всі віртуалхости на стандартному HTTP і порту 80.

Моніторинг NGINX/PHP описаний в VictoriaMetrics: базовий моніторинг AWS, Linux, NGINX та PHP.

Установка NGINX

Є в репозиторіях, встановлюємо з pkg:

root@setevoy-nas:~ # pkg install nginx

Додаємо в автостарт:

root@setevoy-nas:~ # sysrc nginx_enable="YES"

Запускаємо сервіс:

root@setevoy-nas:~ # service nginx start

Перевіряємо порт:

root@setevoy-nas:~ # sockstat -4 -l | grep nginx
www      nginx        455 6   tcp4   *:80                  *:*
root     nginx        454 6   tcp4   *:80                  *:*

Перевіряємо, що все працює:

root@setevoy-nas:~ # curl localhost:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...

Налаштування NGINX virtualhosts

Створюємо каталог для конфігів власних віртуалхостів:

root@setevoy-nas:~ # mkdir -p /usr/local/etc/nginx/conf.d

Додаємо include з цим каталогом в основний конфіг /usr/local/etc/nginx/nginx.conf:

FreeBSD: налаштування FEMP - NGINX, PHP-FPM, MariaDB

...
http {  

    # virtualhosts
    include /usr/local/etc/nginx/conf.d/*.conf;
...

Створення NGINX virtualhost для Grafana

Створюємо новий файл /usr/local/etc/nginx/conf.d/grafana.setevoy.conf.

В ньому задаємо ім’я хоста grafana.setevoy (.setevoy – моя локальна DNS-зона на MikroTik), і вказуємо proxy_pass – адреса, на якій запущена Grafana (про установку Grafana на FreeBSD див. FreeBSD: Home NAS, part 10 – моніторинг з VictoriaMetrics та Grafana):

server {
    listen 80;
    server_name grafana.setevoy;

    location / {
        proxy_pass         http://127.0.0.1:3000;
        proxy_http_version 1.1;

        proxy_set_header   Host              $host;
        proxy_set_header   X-Real-IP         $remote_addr;
        proxy_set_header   X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;

        proxy_set_header   Upgrade           $http_upgrade;
        proxy_set_header   Connection        "upgrade";
    }
}

Перевіряємо синтаксис конфігів, перезавантажуємо NGINX:

root@setevoy-nas:~ # nginx -t && service nginx reload

І відкриваємо в браузері http://grafana.setevoy:

FreeBSD: налаштування FEMP - NGINX, PHP-FPM, MariaDB

Створення NGINX virtualhost для VictoriaMetrics та редіректи

На відміну від Grafana, для доступу до VM UI у VictoriaMetrics нам треба URI /vmui/ – тому відразу налаштуємо редірект: якщо на NGINX приходить запит на victoria.setevoy – то відправляємо на victoria.setevoy/vmui/:

server {
    listen 80;
    server_name victoria.setevoy;

    location = / {
        return 301 /vmui/; 
    }   

    location / {
        proxy_pass         http://127.0.0.1:8428;
        proxy_http_version 1.1;

        proxy_set_header   Host              $host;
        proxy_set_header   X-Real-IP         $remote_addr;
        proxy_set_header   X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
    }
}

Установка PHP та PHP-FPM

Встановлюємо з pkg з репозиторію:

root@setevoy-nas:~ # pkg install -y php84 php84-extensions

Створюємо власний php.ini:

root@setevoy-nas:~ # cp /usr/local/etc/php.ini-production /usr/local/etc/php.ini

Створюємо файл налаштувань для PHP-FPM – /usr/local/etc/php-fpm.d/blog.setevoy.conf.

Задаємо параметри FPM (див. PHP-FPM: Process Manager – dynamic vs ondemand vs static – 2018 рік, але механізм той самий).

З важливого в конфігу:

  • user && group: власник процесів PHP
  • listen: використовуємо Unix socket замість TCP
  • listen.owner та listen.group: власник файлу сокета – www, бо до файлу треба доступ NGINX
  • pm = dynamic: динамічний пул FPM workers
  • pm.max_children: максимальна кількість процесів PHP для цього пула
  • pm.start_servers: скільки процесів створювати при старті/рестарті FPM
  • pm.min_spare_servers та pm.max_spare_servers – мінімум та максимум процесів в idle

В результаті файл для WordPress виглядає так:

[blog.setevoy]
user = setevoy
group = setevoy

listen = /var/run/php-fpm/blog.setevoy.sock
listen.owner = www
listen.group = www
listen.mode = 0660

pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3

slowlog = /var/log/nginx/blog.setevoy-slow.log
php_flag[display_errors] = off
php_admin_value[display_errors] = on
php_admin_value[error_log] = /var/log/nginx/blog.setevoy-php-error.log
php_admin_flag[log_errors] = on
php_admin_value[upload_max_filesize] = 128M
php_admin_value[post_max_size] = 128M

І для прикладу – поточний конфіг самого rtfm.co.ua – тільки він в AWS на EC2 з Amazon Linux:

[rtfm.co.ua]

; run workers as this user
user = rtfm
group = rtfm

; unix socket path for nginx upstream
listen = /var/run/rtfm.co.ua-php-fpm.sock

; socket owner - must match nginx user
listen.owner = nginx
listen.group = nginx

; process manage settings
pm = dynamic                   ; dynamic - spawn/kill workers based on load
pm.max_children = 8            ; max workers total
pm.start_servers = 2           ; workers on startup
pm.min_spare_servers = 2       ; min idle workers
pm.max_spare_servers = 4       ; max idle workers
pm.process_idle_timeout = 10s  ; kill idle workers after N seconds
pm.max_requests = 500          ; restart worker after N requests (prevents memory leaks)

; write worker stderr to main fpm log
catch_workers_output = yes
; worker startup directory
chdir = /
; endpoint for fpm status page (use in nginx location)
pm.status_path = /fpm-status

; fpm-level log for requests slower than request_slowlog_timeout
slowlog = /var/log/php/rtfm.co.ua/rtfm.co.ua-slow.log

; php ini overrides - php_admin_value cannot be overridden by app code
php_admin_value[display_errors] = off
php_admin_value[error_log] = /var/log/php/rtfm.co.ua/rtfm.co.ua-error.log
php_admin_flag[log_errors] = on

; sessions - make sure /var/lib/php/session/rtfm exists, owner rtfm:rtfm
php_admin_value[session.save_path] = /var/lib/php/session/rtfm
php_value[session.save_handler] = files

; max upload size
php_admin_value[upload_max_filesize] = 128M
php_admin_value[post_max_size] = 128M
php_admin_value[memory_limit] = 256M

Створюємо каталог для сокетів:

root@setevoy-nas:~ # mkdir -p /var/run/php-fpm

Додаємо PHP-FPM в автостарт:

root@setevoy-nas:~ # sysrc php_fpm_enable="YES"

Запускаємо:

root@setevoy-nas:~ # service php_fpm start
Performing sanity check on php-fpm configuration:
[18-Feb-2026 18:21:59] NOTICE: configuration file /usr/local/etc/php-fpm.conf test is successful
Starting php_fpm.

Перевіряємо файл сокету – що він є і має правильні права доступу:

root@setevoy-nas:~ # ls -la /var/run/php-fpm/php-fpm.sock
srw-rw----  1 www www 0 Feb 18 18:21 /var/run/php-fpm/php-fpm.sock

Створення NGINX virtualhost для перевірки PHP

Додаємо новий віртуалхост для NGINX – файл /usr/local/etc/nginx/conf.d/blog.setevoy.conf:

server {
    listen 80;
    server_name blog.setevoy;

    root /usr/local/www/blog.setevoy;
    index index.php index.html;

    access_log /var/log/nginx/blog.setevoy.access.log;
    error_log  /var/log/nginx/blog.setevoy.error.log;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        fastcgi_pass  unix:/var/run/php-fpm/blog.setevoy.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include       fastcgi_params;
    }

    location ~ /\.ht {
        deny all;
    }
}

Створюємо каталог для файлів майбутнього блогу:

root@setevoy-nas:~ # mkdir -p /usr/local/www/blog.setevoy

І там один файл з викликом phpinfo() для тесту:

root@setevoy-nas:~ # echo "<?php phpinfo();" > /usr/local/www/blog.setevoy/phpinfo.php

Задаємо власника:

root@setevoy-nas:~ # chown -R setevoy:setevoy /usr/local/www/blog.setevoy

Перевіряємо в браузері http://blog.setevoy/phpinfo.php:

FreeBSD: налаштування FEMP - NGINX, PHP-FPM, MariaDB

Установка MariaDB

Шукаємо останню доступну версію:

root@setevoy-nas:~ # pkg search mariadb | grep server
mariadb1011-server-10.11.15    Multithreaded SQL database (server)
mariadb106-server-10.6.24      Multithreaded SQL database (server)
mariadb114-server-11.4.9       Multithreaded SQL database (server)

Встановлюємо MariaDB 11.4:

root@setevoy-nas:~ # pkg install mariadb114-server

Додаємо в автостарт, запускаємо:

root@setevoy-nas:~ # sysrc mysql_enable="YES"
root@setevoy-nas:~ # service mysql-server start

Запускаємо скрипт mariadb-secure-installation для дефолтних налаштувань:

root@setevoy-nas:~ # mariadb-secure-installation

Проходимось по основним параметрам, тут можна всюди відповідати просто “yes” – хіба що задати пароль root:

root@setevoy-nas:~ # mariadb-secure-installation
/usr/local/bin/mysql_secure_installation: Deprecated program name. It will be removed in a future release, use 'mariadb-secure-installation' instead
...
Switch to unix_socket authentication [Y/n] 
Enabled successfully!
Reloading privilege tables..
 ... Success!

...
Change the root password? [Y/n] 
New password: 
Re-enter new password: 
Password updated successfully!
Reloading privilege tables..
 ... Success!

...
Remove anonymous users? [Y/n] 
 ... Success!

...
Disallow root login remotely? [Y/n] 
 ... Success!

...
Remove test database and access to it? [Y/n] 
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!

...
Reload privilege tables now? [Y/n] 
 ... Success!

Cleaning up...

All done!  If you've completed all of the above steps, your MariaDB
installation should now be secure.

Thanks for using MariaDB!

Створення MariaDB database та user

Підключаємось до сервера:

root@setevoy-nas:~ # mysql -u root -p
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 13
Server version: 11.4.9-MariaDB FreeBSD Ports

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

root@localhost [(none)]>

Створюємо базу, юзера з паролем, даємо юзеру доступ до цієї бази:

root@localhost [(none)]> CREATE DATABASE blog_test CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
Query OK, 1 row affected (0.003 sec)

root@localhost [(none)]> CREATE USER 'blog-test'@'localhost' IDENTIFIED BY 'localpass';
Query OK, 0 rows affected (0.001 sec)

root@localhost [(none)]> GRANT ALL PRIVILEGES ON blog_test.* TO 'blog-test'@'localhost';
Query OK, 0 rows affected (0.001 sec)

root@localhost [(none)]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.001 sec)

Виходимо, пробуємо підключитись з цим юзером:

root@setevoy-nas:~ # mysql -u blog-test -p blog_test
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 14
Server version: 11.4.9-MariaDB FreeBSD Ports

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

blog-test@localhost [blog_test]>

Установка WordPress

Завантажуємо архів з останнім релізом, розпаковуємо, переносимо файли в каталог /usr/local/www/blog.setevoy/:

root@setevoy-nas:~ # fetch https://wordpress.org/latest.tar.gz -o /tmp/latest.tar.gz
root@setevoy-nas:~ # tar -xzf /tmp/latest.tar.gz -C /tmp/

root@setevoy-nas:~ # cp -r /tmp/wordpress/* /usr/local/www/blog.setevoy/

root@setevoy-nas:~ # chown -R setevoy:setevoy /usr/local/www/blog.setevoy/

Відкриваємо в браузері – WordPress свариться на missing PHP extentions:

FreeBSD: налаштування FEMP - NGINX, PHP-FPM, MariaDB

Встановлюємо:

root@setevoy-nas:~ # pkg install php84-mysqli php84-pdo_mysql
root@setevoy-nas:~ # service php-fpm restart

Починаємо установку:

FreeBSD: налаштування FEMP - NGINX, PHP-FPM, MariaDB

Задаємо ім’я бази, юзера, пароль, хост MariaDB:

FreeBSD: налаштування FEMP - NGINX, PHP-FPM, MariaDB

Взагалі WordPress наче має сам створити файл wp-config.php, але ок – копіюємо зміст, створюємо файл вручну:

FreeBSD: налаштування FEMP - NGINX, PHP-FPM, MariaDB

Але знов помилка – “Call to undefined function WpOrg\Requests\gzinflate()“:

FreeBSD: налаштування FEMP - NGINX, PHP-FPM, MariaDB

Додаємо ще один пакет з PHP:

root@setevoy-nas:~ # pkg install php84-zlib

root@setevoy-nas:~ # service php_fpm restart

І тепер все працює – завершуємо налаштування:

FreeBSD: налаштування FEMP - NGINX, PHP-FPM, MariaDB

FreeBSD: налаштування FEMP - NGINX, PHP-FPM, MariaDB

Готово:

FreeBSD: налаштування FEMP - NGINX, PHP-FPM, MariaDB

І навіть прийшов лист на пошту, бо на FreeBSD налаштований DragonFly Mail Agent – див. FreeBSD: налаштування DragonFly Mail Agent для пошти root:

FreeBSD: налаштування FEMP - NGINX, PHP-FPM, MariaDB

Логінимось в адмінку блога:

FreeBSD: налаштування FEMP - NGINX, PHP-FPM, MariaDB

Все працює.

Готово.

Loading