Improve performance on a dedicated server to WordPress – NGINX, PHP 7.4, Redis, MariaDB

I have a dedicated server with this hardware configs:

CPU: Intel(R) Xeon(R) Gold 6226R CPU @ 2.90GHz 
Disk: SSD 512GB

My stack is:

SO: Ubuntu latest LTS
Web Server: Nginx 1.18.0
Language: PHP 7.4
Database: MariaDB 10.3.25

Currently, the TTFB is around 400ms and I have some problems with slow requests on Wordpress dashboard and site performance.

I know about the optimizations in site side but, I tested some stuffs to get the real problem: Server Side.

I have more than 200 sites, all in Wordpress and "Tiedye", using just the best plugins. All of this is connected to Cloudflare with the best options and with cache plugin (WP Rocket).

About the configs of the software, follow:


user www-data;

worker_processes auto;
worker_rlimit_nofile 100000;
error_log /var/log/nginx/error.log crit;

pid /run/;

include /etc/nginx/modules-enabled/*;

events {
        worker_connections 4096;
        multi_accept on;
        use epoll;

http {
        #BASIC CACHE
        open_file_cache max=200000 inactive=20s;
        open_file_cache_valid 30s;
        open_file_cache_min_uses 2;
        open_file_cache_errors on;

        access_log off;
        server_tokens off;
        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 30;
        send_timeout 2;
        keepalive_requests 100000;
        reset_timedout_connection on;
        types_hash_max_size 2048;
        large_client_header_buffers 4 256k;
        client_max_body_size 500M;
        client_header_buffer_size 3M;
        client_body_buffer_size 128k;
        client_body_timeout   30m;
        client_header_timeout 30m;
        proxy_send_timeout 6000;
        proxy_read_timeout 6000;
        fastcgi_read_timeout 3600;
        fastcgi_send_timeout 3600;
        server_names_hash_bucket_size 512;

        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_prefer_server_ciphers on;
        ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
        ssl_ecdh_curve secp384r1;
        ssl_session_tickets off;
        ssl_buffer_size 4k;
        ssl_session_cache shared:SSL:1m;
        ssl_session_timeout 1h;

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

        limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;        limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=5r/s;

        gzip on;
        gzip_disable "msie6";
        gzip_vary on;
        gzip_proxied any;
        gzip_comp_level 6;
        gzip_buffers 16 8k;
        gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/ application/x-font-ttf font/opentype image/svg+xml image/x-icon image/jpeg image/png image/jpg;

        fastcgi_buffers 8 16k;
        fastcgi_buffer_size 32k;
        fastcgi_cache_use_stale error timeout invalid_header http_500;
        fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
        fastcgi_cache_path /var/cache/nginx/fastcgi levels=1:2 keys_zone=WORDPRESS:100m inactive=60m;
        fastcgi_cache_key "$scheme$request_method$host$request_uri";

        proxy_cache_path /var/cache/nginx/proxy levels=1:2 keys_zone=PROXY:10m max_size=10g inactive=60m use_temp_path=off;
        proxy_cache_revalidate on;
        proxy_buffering off;
        proxy_request_buffering off;


### SERVER ###

index index.php index.html index.htm index.nginx-debian.html;


set $skip_cache 0;

if ($request_method = POST) {
    set $skip_cache 1;

if ($query_string != "") {
    set $skip_cache 1;

if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
    set $skip_cache 1;

if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
    set $skip_cache 1;


location ~ ([^/]*)sitemap(.*)\.x(m|s)l$ {
  rewrite ^/sitemap\.xml$ /sitemap_index.xml permanent;
  rewrite ^/([a-z]+)?-?sitemap\.xsl$ /index.php?xsl=$1 last;
  rewrite ^.*/sitemap_index\.xml$ /index.php?sitemap=1 last;
  rewrite ^.*/([^/]+?)-sitemap([0-9]+)?\.xml$ /index.php?sitemap=$1&sitemap_n=$2 last;
  rewrite ^/news_sitemap\.xml$ /index.php?sitemap=wpseo_news last;
  rewrite ^/locations\.kml$ /index.php?sitemap=wpseo_local_kml last;
  rewrite ^/geo_sitemap\.xml$ /index.php?sitemap=wpseo_local last;
  rewrite ^/video-sitemap\.xsl$ /index.php?xsl=video last;

  access_log off;

location ~* /(?:uploads|files|wp-content|wp-includes|akismet)/.*.php$ {    deny all;
    access_log off;
    log_not_found off;

rewrite /wp-admin$ $scheme://$host$uri/ permanent;

location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
        access_log off;
        log_not_found off;
        expires max;
        add_header Cache-Control "max-age=2592000";

location ~* \.(?:manifest|appcache|html?|xml|json)$ {
        add_header Cache-Control "max-age=0";

location ~* \.(?:rss|atom)$ {
        add_header Cache-Control "max-age=3600";

location ~* \.svgz$ {
        access_log off;
        gzip off;
        expires 360d;
        add_header Cache-Control "max-age=2592000";

location ~* \.(?:css|js)$ {
        access_log off;
        log_not_found off;
        expires 360d;
        add_header Cache-Control "max-age=31536000";

location = /robots.txt {
        access_log off;
        log_not_found off;

location ~ /\.ht {
        deny all;
        access_log off;
        log_not_found off;

location ~ /\.user.ini {
        deny all;
        access_log off;
        log_not_found off;

location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        try_files $fastcgi_script_name = 404;
        set $path_info $fastcgi_path_info;
        fastcgi_param PATH_INFO $path_info;
        fastcgi_index index.php;
        fastcgi_cache WORDPRESS;
        fastcgi_cache_valid 200 30m;
        fastcgi_cache_methods GET HEAD;
        fastcgi_cache_bypass $skip_cache;
        fastcgi_no_cache $skip_cache;

        proxy_cache PROXY;

        # Hide PHP Version

        fastcgi_hide_header X-Powered-By;
        proxy_hide_header X-Powered-By;

        add_header X-Fastcgi-Cache $upstream_cache_status;
        add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";

        include fastcgi.conf;

        fastcgi_pass unix:/run/php/php7.4-fpm.sock;

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


memory_limit = 512M
max_input_time = 50000
max_execution_time = 50000
expose_php = Off
post_max_size = 20M

--- POOL ---

pm = static
pm.max_children = 220
pm.max_requests = 0
request_terminate_timeout = 20000


innodb_buffer_pool_size = 18G
innodb_buffer_pool_instances = 18
innodb_log_file_size = 6G
innodb_log_buffer_size = 512M
innodb_write_io_threads = 8
innodb_read_io_threads = 8
max_allowed_packet = 512M
max_connections = 500
table_open_cache = 6000
table_open_cache_instances = 8
table_definition_cache = 2000
tmp_table_size = 64M
max_heap_table_size = 64M
thread_cache_size = 100
key_buffer_size = 128M
query_cache_type = 0
query_cache_size = 0
log_warnings = 2

About this lot of info and configs, some DIRECTLY tips to improve the TTFB and speed of my sites?

PS: If did you a specialist in this and wants to help me, I will consider "pay a coffee" comparing the after results.

Read more here:

Content Attribution

This content was originally published by Stenio Anibal at Recent Questions - Stack Overflow, and is syndicated here via their RSS feed. You can read the original post over there.

%d bloggers like this: