Чергова частина налаштування 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:
...
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:
Створення 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: власник процесів PHPlisten: використовуємо Unix socket замість TCPlisten.ownerтаlisten.group: власник файлу сокета –www, бо до файлу треба доступ NGINXpm = dynamic: динамічний пул FPM workerspm.max_children: максимальна кількість процесів PHP для цього пулаpm.start_servers: скільки процесів створювати при старті/рестарті FPMpm.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:
Установка 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:
Встановлюємо:
root@setevoy-nas:~ # pkg install php84-mysqli php84-pdo_mysql root@setevoy-nas:~ # service php-fpm restart
Починаємо установку:
Задаємо ім’я бази, юзера, пароль, хост MariaDB:
Взагалі WordPress наче має сам створити файл wp-config.php, але ок – копіюємо зміст, створюємо файл вручну:
Але знов помилка – “Call to undefined function WpOrg\Requests\gzinflate()“:
Додаємо ще один пакет з PHP:
root@setevoy-nas:~ # pkg install php84-zlib root@setevoy-nas:~ # service php_fpm restart
І тепер все працює – завершуємо налаштування:
Готово:
І навіть прийшов лист на пошту, бо на FreeBSD налаштований DragonFly Mail Agent – див. FreeBSD: налаштування DragonFly Mail Agent для пошти root:
Логінимось в адмінку блога:
Все працює.
Готово.
![]()












