My Nginx configuration for OroCRM (it features PHP-FPM, Ratchet Websocket server, SSL/TLS, Lets'Encrypt)

1. /usr/local/nginx/conf/nginx.conf

user www-data;
worker_processes 4;
error_log /var/log/_my/nginx.log error;
events {worker_connections  1024;}
http {
	access_log off;
	client_max_body_size 64m;
	# It prevents Magento 2 failure while paying with PayPal:
	# «upstream sent too big header while reading response header from upstream»
	# "GET /store/paypal/express/return/?token=<...>&PayerID=<...>
	# http://stackoverflow.com/a/23845727
	fastcgi_buffer_size 32k;
	# 2017-05-03
	# This value is recommended by the official sample Nginx config for Magento 2:
	# https://github.com/magento/magento2/blob/2.1.6/nginx.conf.sample#L161
	fastcgi_buffers 1024 4k;
	fastcgi_connect_timeout 3600;
	fastcgi_read_timeout 3600;
	fastcgi_send_timeout 3600;
	# 2015-08-18
	# http://nginx.org/en/docs/http/ngx_http_gzip_module.html
	# http://magento-forum.ru/topic/5187/
	gzip on;
	gzip_disable "msie6";
	gzip_comp_level 6;
	gzip_min_length 1100;
	gzip_buffers 16 8k;
	# By default only the text/html responses are gzipped.
	# I want to gzip other static content too: http://stackoverflow.com/a/12644530
	# http://nginx.org/en/docs/http/ngx_http_gzip_module.html#gzip_types
	gzip_types text/plain text/css text/js text/xml text/javascript application/javascript application/x-javascript application/json application/xml application/xml+rss;
	keepalive_timeout 10;
	log_format websocket '$time_iso8601 $remote_addr $scheme $request_uri $status';
	# 2017-05-22 For Websockets, used by OroCRM.
    map $http_upgrade $connection_upgrade {
        default upgrade;
        '' close;
    }
    # 2017-05-21
    # It fixes the warning for OroCRM: «[warn] could not build optimal proxy_headers_hash,
    # you should increase either proxy_headers_hash_max_size: 512
    # or proxy_headers_hash_bucket_size: 64».
    proxy_headers_hash_bucket_size 256;
	proxy_read_timeout 3600;
	send_timeout 3600;
    default_type application/octet-stream;
    include mime.types;
    sendfile on;
	include sites/*.conf;
}

2. /usr/local/nginx/conf/sites/crm.mage2.pro.conf

server {
	listen 80;
	server_name crm.mage2.pro;
	return 301 https://$server_name$request_uri;
}
server {
	listen 443 ssl;
	server_name crm.mage2.pro;
    ssl_certificate /etc/letsencrypt/live/crm.mage2.pro/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/crm.mage2.pro/privkey.pem;
	ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
	proxy_set_header X-Forwarded-Proto $scheme;
	proxy_set_header Host $http_host;
	proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
	proxy_set_header X-Forwarded-Proto https;
	proxy_set_header X-Real-IP $remote_addr;
	error_page 420 = @websocket;
    if ($http_upgrade = "websocket") {
        return 420;
    }
	root /var/www/crm/web;
	# 2017-04-29 For Let's Encrypt: https://serverfault.com/a/755665
	location ~ /.well-known {
		root /var/www/lets-encrypt/crm.mage2.pro;
		access_log off;
		expires max;
		break;
	}
	location ~ /\. {deny all;}
	location / {try_files $uri /app.php$is_args$args;}
	location ~ ^/(app|app_dev|config|install|phpinfo)\.php(/|$) {
		fastcgi_pass 127.0.0.1:9000;
		fastcgi_split_path_info ^(.+\.php)(/.*)$;
		include fastcgi_params;
		fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
	}
	location @websocket {
		access_log /var/log/_my/nginx-websocket-access.log websocket;
		error_log /var/log/_my/nginx-websocket-error.log notice;
		proxy_http_version 1.1;
		proxy_redirect off;
		proxy_set_header Connection $connection_upgrade;
		proxy_set_header Upgrade $http_upgrade;
		proxy_pass http://127.0.0.1:5868;
	}
}

3. /usr/local/nginx/conf/fastcgi_params

fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;

fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;
fastcgi_param  HTTPS              $https if_not_empty;

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param  REDIRECT_STATUS    200;

fastcgi_param DF_DEVELOPER 1;
fastcgi_param MAGE_IS_DEVELOPER_MODE 1;
fastcgi_param MAGE_MODE developer;

# 2017-05-20
# It separates the FastCGI (PHP-FPM) failures from the Nginx failures.
# I have noticed that sometimes fpm.log and php.log do not contain a record
# about PHP fatal errors like «Uncaught Error: Function name must be a string»,
# but the Nginx log contains: «PHP message: PHP Fatal error:  Uncaught Error: Function name must be a string».
# So I decided to use the separate log for such records.
error_log /var/log/_my/fastcgi.log notice;