Optimizing NGINX & PHP-FPM

Transcription

Optimizing NGINX & PHP-FPM— From Beginner to Expert to CrazyInternational PHP Conference Fall 2019 - Munich

Arne BlankertsCo-Founder, The PHP Consulting Company

Basics

location / {root/usr/share/nginx/html;index index.html index.htm;}location \.php {roothtml;fastcgi pass127.0.0.1:9000;fastcgi index index.php;includefastcgi params;fastcgi param SCRIPT FILENAME} document root fastcgi script name;

location / {root/usr/share/nginx/html;index index.html index.htm;}location \.php {roothtml;fastcgi pass127.0.0.1:9000;fastcgi index index.php;includefastcgi params;fastcgi param SCRIPT FILENAME}/var/www/php/ fastcgi script name;

location / {root/usr/share/nginx/html;index index.html index.htm;}location \.php {roothtml;fastcgi pass127.0.0.1:9000;fastcgi index index.php;includefastcgi params;fastcgi param SCRIPT FILENAME}/var/www/php/index.php;

location / {root/usr/share/nginx/html;index index.html index.htm;}location \.php {roothtml;fastcgi pass127.0.0.1:9000;fastcgi index index.php;includefastcgi params;fastcgi param SCRIPT FILENAME}/var/www/php/index.php;

location / {root/usr/share/nginx/html;index index.html index.htm;}location \.php {fastcgi pass127.0.0.1:9000;includefastcgi params;fastcgi param SCRIPT FILENAME}/var/www/php/index.php;

location / {root/usr/share/nginx/html;index index.html index.htm;try files uri uri/ @php;}location @php {fastcgi passincludefastcgi param}127.0.0.1:9000;fastcgi params;SCRIPT FILENAME/var/www/php/index.php;

root/usr/share/nginx/html;location / {try files uri uri/ @php;}location @php {fastcgi passincludefastcgi param}unix:/var/run/php-fpm.sock;fastcgi params;SCRIPT FILENAME /var/www/php/index.php;

Compress all the things!

root/usr/share/nginx/html;location / {gzip static on;try files uri uri/ @php;}location @php {gzip on;fastcgi passincludefastcgi param}unix:/var/run/php-fpm.sock;fastcgi params;SCRIPT FILENAME /var/www/php/index.php;

Content Security Policy

server {root/usr/share/nginx/html;add header Content-Security-Policy "default-src 'none'; img-src 'self'; \script-src 'self'; style-src 'self'; font-src 'self'; base-uri 'self'; \form-action 'self'; connect-src 'self'; frame-ancestors 'none'";}

server {root/usr/share/nginx/html;include content-security-policy;}

enerate

Additional Security Headers

server {root/usr/share/nginx/html;include content-security-policy;add header X-Frame-Options DENY;add header X-Content-Type-Options nosniff;add header X-Xss-Protection "1; mode block" always;}

Force Https

server {listen 80 default server;listen [::]:80 default server;return 301 https:// host request uri;}

Sane TLS

server {listen 443 ssl http2;listen [::]:443 ssl http2;ssl certificate /path/to/signed cert plus intermediates;ssl certificate key /path/to/private key;ssl session timeout 1d;ssl session cache shared:MozSSL:10m; # about 40000 sessionsssl session tickets off;ssl dhparam /path/to/dhparam.pem;ssl protocols TLSv1.2 TLSv1.3;ssl ciphers -SHA384;ssl prefer server ciphers off;add header Strict-Transport-Security "max-age 63072000" always;ssl stapling on;ssl stapling verify on;ssl trusted certificate /path/to/root CA cert plus intermediates;resolver 127.0.0.1;}

Paranoid TLS

server {listen 443 ssl http2;listen [::]:443 ssl http2;ssl certificate /path/to/signed cert plus intermediates;ssl certificate key /path/to/private key;ssl session timeout 1d;ssl session cache shared:MozSSL:10m; # about 40000 sessionsssl session tickets off;ssl protocols TLSv1.3;ssl prefer server ciphers off;add header Strict-Transport-Security "max-age 63072000" always;ssl stapling on;ssl stapling verify on;ssl trusted certificate /path/to/root CA cert plus intermediates;resolver 127.0.0.1;}

.mozilla.orghttps://securityheaders.com

More than one backend

location @php {fastcgi passincludefastcgi param}unix:/var/run/php-fpm.sock;fastcgi params;SCRIPT FILENAME /var/www/php/index.php;

upstream php-fpm {server unix:/var/run/php-fpm.sock;}location @php {fastcgi passincludefastcgi param}php-fpm;fastcgi params;SCRIPT FILENAME/var/www/php/index.php;

upstream php-fpm {server unix:/var/run/php-fpm.sock;server 192.168.1.1:9000 weigth 5;server 192.168.1.2:1345 max fails 3 fail timeout 30s;server 192.168.1.3:9000 down;server 192.168.1.4:9000 backup;}location @php {fastcgi passincludefastcgi param}php-fpm;fastcgi params;SCRIPT FILENAME/var/www/php/index.php;

Semi dynamic backends

upstream php-fpm {server unix:/var/run/php-fpm.sock;include upstreams/*.conf;}location @php {fastcgi passincludefastcgi param}php-fpm;fastcgi params;SCRIPT FILENAME/var/www/php/index.php;

Keep in touch

upstream php-fpm {server unix:/var/run/php-fpm.sock;include upstreams/*.conf;keepalive 10;}location @php {fastcgi passphp-fpm;fastcgi keep conn on;includefastcgi params;fastcgi param SCRIPT FILENAME}/var/www/php/index.php;

O oad Logging

location @php {fastcgi passphp-fpm;fastcgi keep conn on;includefastcgi params;fastcgi param SCRIPT FILENAME/var/www/php/index.php;mirror @logging;}location @logging {fastcgi passlogger-pool;fastcgi param SCRIPT FILENAME /var/www/php/log.php;includefastcgi params;fastcgi param X-Original-Url request uri;}

location @php {fastcgi passfastcgi paramincludephp-fpm;SCRIPT FILENAMEfastcgi params;/var/www/php/index.php;mirror @logging;mirror request body off;}location @logging {fastcgi passlogger-pool;includefastcgi params;fastcgi param SCRIPT FILENAME /var/www/php/log.php;fastcgi param X-Original-Url request uri;}

Who handles errors?

server {errorpage 404 /error/404.html;location @php {fastcgi passfastcgi paramincludephp-fpm;SCRIPT FILENAMEfastcgi params;fastcgi intercept errors on;}location /error/ {root /var/www/errors;}}/var/www/php/index.php;

map http accept language lang {default en; de de;# .}server {errorpage 404 /error/ lang/404.html;location @php {fastcgi passfastcgi paramincludephp-fpm;SCRIPT FILENAMEfastcgi params;fastcgi intercept errors on;}location /error/ {root /var/www/errors;}}/var/www/php/index.php;

More fun with maps

More fun with mapsAlso known as API versioning

map accept header backend {default ‘unix:/var/run/app v1.sock’;‘application/vnd.some-site.v2 json’ ‘unix:/var/run/app v2.sock’;‘application/vnd.some-site.v3 json’ ‘192.168.1.1:9000’;}server {location @php {fastcgi pass backend;}}

map accept header backend {default ‘unix:/var/run/app v1.sock’;include /var/www/versions/*.conf;}server {location @php {fastcgi pass backend;}}

server {location / {try files uri uri/ @new;}location @new {# .fastcgi intercept errors on;recursive error pages on;error page 404 @old;}location @old {# .}}

Sane Downloads

class DownloadQuery {// .public function execute(): Response {if (! this- acl- isAccessGranted( this- file) {return new AccessDeniedResponse();}return new DownloadResponse( this- path . '/' . this- file);}}

class DownloadQuery {// .public function execute(): Response {if (! this- acl- isAccessGranted( this- file) {return new AccessDeniedResponse();}return new DownloadResponse( this- path . '/' . this- file);}}class DownloadResponse implements Response {// .public function send() {header('X-Accel-Redirect: ' . this- file);}}

class DownloadQuery {// .public function execute(): Response {if (! this- acl- isAccessGranted( this- file) {return new AccessDeniedResponse();}return new DownloadResponse( this- path . '/' . this- file);}}class DownloadResponse implements Response {// .public function send() {header('X-Accel-Redirect: ' . this- file);}}

Sane large file uploads

server {location /upload {limit except POSTclient body temp pathclient body in file onlyclient body buffer sizeclient max body size{ deny all; }/var/www/data/uploads;on;1024K;10G;fastcgi pass request headersfastcgi pass request bodyfastcgi ignore client abortfastcgi param X-UPLOAD-FILE}}on;off;on; request body file;

// .let file formElement.querySelector('input[type file]').files[0];let xhr new XMLHttpRequest();xhr.open('POST', '/upload', true);xhr.setRequestHeader('X-Original', file.name);xhr.send(file);// .

Tweaking FPM defaults

[www]pm staticpm.max children 10pm.max requests 500

[www]pm staticpm.max children 10pm.max requests 500slowlog /var/log/php-fpm/ pool.log.slowrequest slowlog timeout 1s

Configure Opcache

opcache.max accelerated files 20000opcache.memory consumption 512

opcache.max accelerated files 20000opcache.memory consumption 512opcache.validate timestamps 0opcache.file update protection 0opcache.save comments 0

opcache.max accelerated files 20000opcache.memory consumption 512opcache.validate timestamps 0opcache.file update protection 0opcache.save comments 0opcache.preload /path/to/preload.php

Make Sessions fast

Make Sessions faster

session.probability 0

session.probability 0session.save handler redissession.save path unix://var/run/redis.sock?persistent 1

session.probability 0session.save handler redissession.save path unix://var/run/redis.sock?persistent 1session.save path tcp://10.0.0.1:6379?persistent 1

Filter all the things?

location /img-low/ {alias /var/www/public/img/;image filter resize 150 100;error page415 @empty;}location @empty {empty gif;}

location /feed/ {proxy pass http://feed-server/atom;xslt stylesheet /var/www/xsl/atom.xsl;}

JavaScript!

js include path/to/switch.js;js set current select pool;server {// [.]location @php {fastcgi passincludefastcgi paramfastcgi param}}unix:/var/run/php-fpm/ current.sock;fastcgi params;REQUEST URI document uri;SCRIPT FILENAME /var/www/php/bootstrap.php;

js include path/to/switch.js;js set current select pool;server {// [.]location @php {fastcgi passincludefastcgi paramfastcgi param}unix:/var/run/php-fpm/ current.sock;fastcgi params;REQUEST URI document uri;SCRIPT FILENAME /var/www/php/bootstrap.php;}function select pool() {return 'www';}

Or Lua!

server {location @php {access by lua file switch.lua;fastcgi passincludefastcgi paramfastcgi param}}unix:/var/run/php-fpm/ current.sock;fastcgi params;REQUEST URI document uri;SCRIPT FILENAME current/runtime/bootstrap.php;

ngx.var.current 'www';return

Single Sign On with Lua

local uuid ngx.var.cookie uuid;if not uuid thenngx.redirect('/login');endlocal redis require "resty.redis"local red redis:new()red:connect("127.0.0.1", 6379)local res, err red:get(uuid)if res ngx.null thenngx.redirect('/login');endngx.header["uuid"] nilngx.req.set header("X-UUID-INFO", uuid);ngx.req.set header("X-USER-INFO", res);return

Sticky session

local sid ngx.var.cookie PHPSESSID;local redis require "resty.redis"local red redis:new()local keys {'default'}if sid thenkeys[2] sidendred:set timeout(100)local ok, err red:connect("127.0.0.1", 6379)local res, err red:mget(unpack(keys))if (res[2] ngx.null) thenres[2] nilendif sid and not res[2] thenred:set(sid, res[1])endngx.var.current res[2] or res[1]return

Thank you https://thephp.cc arne@thephp.cc @arneblankerts

Optimizing NGINX & PHP-FPM — From Beginner to Expert to Crazy International PHP Conference Fall 2019 - Munich. Arne Blankerts Co-Founder, The PHP Consulting Company. Basics. location / {root /usr/share/nginx/html; index index.html index.htm;} location \.php {root html;