QNAP jako hosting strony WWW - nginx, php-fpm, mariadb

QNAP jako hosting strony WWW - nginx, php-fpm, mariadb

Jak wiadomo jestem od dawna zwolennikiem nginx. Niestety QNAP podaje strony z wykorzystaniem Apache. Jednak tutaj z pomocą przychodzi nam docker oraz Container Station (który uprzednio musimy mieć zainstalowany).

Docker został stworzony do „separacji”/uruchamiania tylko aplikacji, nie cały systemów, jednak można je linkować. Dzięki temu tworzymy aplikację która składa się z kilku osobnych kontenerów.

Zatem w pierwszej kolejności trzeba przygotować strukturę:

Czyli całość (pliki strony, bazy, konfiguracyjne oraz logi) będą trzymane na QNAP w /share/Web. Tworzę katalog 8px.pl jako domenę a w nim katalogi:

  • app – pliki strony
  • database – pliki MariaDB
  • fpm – pliki konfiguracyjne PHP-FPM
  • logs – logi nginx
  • nginx – konfiguracja serwera www

Teraz musimy przygotować wspomniane pliki konfiguracyjne, i tak PHP-FPM /share/Web/8px.pl/fpm/pool.conf

[www.8px.pl]
user = www-data
group = www-data
listen 127.0.0.1:9000
listen.owner = www-data
listen.group = www-data
listen.mode = 0666
listen.allowed_clients = 127.0.0.1

pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 2
pm.max_spare_servers = 4
pm.max_requests = 200
;pm.status_path = /status
;ping.path = /ping
;ping.response = pong

;access.log = /web/www.8px.pl/log/php-access.log
;access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%"
;slowlog = log/$pool.log.slow
;request_slowlog_timeout = 0

request_terminate_timeout = 120s
rlimit_files = 131072
rlimit_core = 2

chdir = /web/www.8px.pl/app

security.limit_extensions = .php

env[HOSTNAME] = www.8px.pl
env[PATH] = /usr/local/bin:/usr/bin:/bin
env[HOME] = /web/www.8px.pl/app
env[USER] = www.8px.pl


php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f admin@8px.pl
php_flag[display_errors] = off
php_admin_value[error_log] = /web/www.8px.pl/log/php-error.log
php_admin_flag[log_errors] = on
php_admin_value[memory_limit] = 64M
php_admin_value[disable_functions] = dl,exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source
php_admin_flag[opcache.enable] = on

Jak widać instancja nazywa się www.8px.pl, będzie działać  na porcie 9000 z wykorzystaniem usera www-data. Sama konfiguracja nie jest domyślną.

Teraz serwer WWW i tak /share/Web/8px.pl/nginx/nginx.conf

user www-data;
worker_processes auto;
pid /var/run/nginx.pid;
worker_rlimit_nofile 100000;
working_directory   /tmp/;
include /etc/nginx/modules-enabled/*.conf;

events {
	worker_connections 4000;
	multi_accept on;
	use epoll;
}

http {
	sendfile on;
	tcp_nopush on;
	tcp_nodelay on;
	keepalive_timeout 30;
	keepalive_requests 100000;
	types_hash_max_size 2048;
	server_tokens off;
	client_max_body_size 40m;
	client_body_timeout 10;
    client_header_timeout 10;
    client_body_buffer_size  256k;
    client_header_buffer_size 8k; 

    large_client_header_buffers 4 16k;
    send_timeout 2; 
    reset_timedout_connection on;
	charset utf-8;
	server_names_hash_max_size 8192;

	add_header X-Frame-Options SAMEORIGIN;
	add_header X-Content-Type-Options nosniff;
	add_header X-XSS-Protection "1; mode=block";
	
	resolver 8.8.8.8 ipv6=off;

	include /etc/nginx/mime.types;
	default_type application/octet-stream;

	access_log off;
	error_log /var/log/nginx/error.log;

	gzip  on;
	gzip_http_version 1.1;
	gzip_comp_level 6;
	gzip_proxied expired no-cache no-store private auth;
	gzip_static on;
	gzip_min_length  1100;
	gzip_buffers 16 8k;
	gzip_disable "MSIE [1-6]\.";
	gzip_vary on;
	gzip_types text/css text/javascript text/xml text/plain text/x-component application/javascript application/x-javascript application/json application/xml application/rss+xml font/truetype application/x-font-ttf font/opentype application/vnd.ms-fontobject image/svg+xml;

    fastcgi_send_timeout 10;
    fastcgi_read_timeout 10;

	fastcgi_buffer_size 16k;
	fastcgi_buffers 4 16k;

	add_header X-Hoster "8px.pl";

	limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;

	log_format postlog $request_body;

    index index.php index.htm index.html;
    include /etc/nginx/conf.d/*.conf;
}

To też nie jest konfiguracja domyślna, proszę też pamiętać  aby wykonać modyfikację pod swoje wymagania. Jeszcze ostatni plik z deklaracjami vhost /share/Web/8px.pl/nginx/default.conf

server {
    index index.php index.html;
    server_name www.8px.pl;
    error_log  /web/www.8px.pl/logs/error.log;
    access_log /web/www.8px.pl/logs/access.log;
    root /web/www.8px.pl/app;

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}

Teraz pozostaje nam uruchomić całe środowisko. Zatem wybieramy tworzenie nowego kontenera w CS na QNAP i tym razem nic nie szukamy, a klikamy tworzenie aplikacji:

Teraz w oknie dodajemy plik dla docker-compose który wykona zadanie:

version: '3'
services:
  php:
    image: php:7.2-fpm
    restart: always
    volumes:
      - /share/Web/8px.pl/fpm/pool.conf:/etc/php/7.2/fpm/pool.d/pool.conf
      - /share/Web/8px.pl/app/:/web/www.8px.pl/app
    ports:
      - "9000:9000"
    links:
      - db 
    hostname: www.8px.pl
  
  web:
    image: nginx
    restart: always
    volumes:
      - /share/Web/8px.pl/nginx/nginx.conf:/etc/nginx/nginx.conf
      - /share/Web/8px.pl/nginx/default.conf:/etc/nginx/conf.d/default.conf
      - /share/Web/8px.pl/logs/:/web/www.8px.pl/logs
      - /share/Web/8px.pl/app/:/web/www.8px.pl/app
    ports:
      - "88:80"
      - "4443:443"
    links:
      - php

  db:
    image: mariadb
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=yourpassword
    volumes:
    -   /share/Web/8px.pl/database:/var/lib/mysql

Jaka widać mamy zdefiniowane usługi które mają być zainstalowane, voluminy do zamontowania oraz na końcu hasło do bazy SQL – proszę podać swoje, należy też ustawić porty serwera WWW.

Gotowa aplikacja:

Wynik phpinfo dla takiej aplikacji.


Tutaj tylko dodam, iż to jest dobry początek do dalszych prac, warto w przyszłości bliskiej pomyśleć o SSL/HTTP2 z wykorzystaniem nginx jako revers proxy dla kontenerów, letsencrypt