The Ultimate DevOps Playbook: Tuning Nginx, Gunicorn/FPM, and MongoDB on OVH for Magento 2
Nginx Configuration for Magento 2 on OVH
Optimizing Nginx for a high-traffic Magento 2 instance on OVH requires a multi-faceted approach, focusing on efficient static file serving, robust caching, and secure proxying to your application server. We’ll start with core directives and then delve into specific Magento 2 considerations.
Core Nginx Performance Tuning
These settings form the bedrock of a performant Nginx setup. They should be placed in your main nginx.conf file, typically within the http block.
worker_processes: Set this to the number of CPU cores available on your OVH instance. This allows Nginx to utilize all available processing power for handling requests.worker_connections: This defines the maximum number of simultaneous connections that each worker process can handle. A common starting point is1024or2048, but this can be tuned based on your server’s RAM and expected load. Ensure your OS limits (ulimit -n) are set higher.multi_accept: Set toonto allow workers to accept multiple connections at once, improving responsiveness under heavy load.keepalive_timeout: Controls how long an idle HTTP connection will remain open. A value between60and120seconds is usually a good balance between resource usage and client responsiveness.sendfile: Set toonto enable efficient transfer of files from disk to network socket, bypassing user space.tcp_nopushandtcp_nodelay: Set both toonfor improved network performance, especially with HTTP/1.1.
Here’s an example snippet for your nginx.conf:
worker_processes auto;
worker_connections 4096;
multi_accept on;
events {
worker_connections 4096;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 120;
keepalive_requests 1000;
# Gzip compression for text-based assets
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
# Buffering and timeouts for proxying
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
proxy_buffer_size 16k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
# ... other http configurations ...
}
Magento 2 Specific Nginx Optimizations
Magento 2 has specific requirements and benefits greatly from tailored Nginx configurations. This includes caching static assets, optimizing for PHP-FPM (or Gunicorn), and handling static file delivery.
Static File Serving and Caching
Magento 2 serves a significant amount of static content. Efficiently caching these assets at the Nginx level reduces load on your application server and speeds up page delivery. We’ll leverage expires and location blocks.
server {
# ... other server directives ...
# Magento 2 static content cache
location ~ ^/static/version[0-9]+/frontend/Magento/<theme>/en_US/css/styles-m.css$ {
expires 1y;
add_header Cache-Control "public";
}
location ~ ^/static/version[0-9]+/frontend/Magento/<theme>/en_US/js/(.+\.js)$ {
expires 1y;
add_header Cache-Control "public";
}
location ~ ^/static/version[0-9]+/frontend/Magento/<theme>/en_US/css/(.+\.css)$ {
expires 1y;
add_header Cache-Control "public";
}
location ~ ^/static/version[0-9]+/frontend/Magento/<theme>/en_US/images/(.+\.(jpg|jpeg|png|gif|svg|webp))$ {
expires 1y;
add_header Cache-Control "public";
}
location ~ ^/static/version[0-9]+/frontend/Magento/<theme>/en_US/fonts/(.+\.(eot|ttf|woff|woff2|svg))$ {
expires 1y;
add_header Cache-Control "public";
}
# Magento 2 media files
location /media/ {
expires 30d;
add_header Cache-Control "public";
}
# Magento 2 robots.txt
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
# Magento 2 favicon.ico
location = /favicon.ico {
log_not_found off;
access_log off;
}
# ... rest of your Magento 2 server block ...
}
Note: Replace <theme> with your actual Magento 2 theme name (e.g., luma, porto). The version[0-9]+ part is crucial as Magento appends a version hash to static files for cache busting. You might need to adjust these regex patterns based on your specific Magento setup and theme structure. For a more robust solution, consider using Nginx’s alias or root directives to point directly to the pub/static and pub/media directories, and then apply caching rules.
Proxying to PHP-FPM (or Gunicorn)
This is where Nginx acts as a reverse proxy to your application server. For Magento 2, this is typically PHP-FPM. Ensure your location / block correctly proxies requests.
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ ^/index.php(/|$) {
# Ensure fastcgi_split_path_info is correctly configured if using PHP-FPM
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; # Adjust to your PHP-FPM version and socket path
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param MAGE_RUN_CODE "your_store_code"; # Set your Magento store code
fastcgi_param MAGE_RUN_TYPE "store"; # Or "website" if applicable
}
Important:
- Adjust
fastcgi_passto match your PHP-FPM configuration. Common paths includeunix:/var/run/php/php7.4-fpm.sockor a TCP socket like127.0.0.1:9000. - Set
MAGE_RUN_CODEandMAGE_RUN_TYPEcorrectly for your Magento 2 multi-store setup. - The
try_filesdirective is crucial for Magento’s routing.
PHP-FPM Tuning for Magento 2
PHP-FPM (FastCGI Process Manager) is the engine that runs your PHP code. Tuning its process management and memory limits is critical for Magento 2’s performance.
Process Management
The pm (process manager) setting determines how PHP-FPM manages worker processes. For Magento 2, a dynamic or ondemand approach is often preferred to conserve resources when idle, but static can offer more consistent performance under heavy load.
[global] pid = /run/php/php7.4-fpm.pid error_log = /var/log/php7.4-fpm.log log_level = notice [www] user = www-data group = www-data listen = /var/run/php/php7.4-fpm.sock # Or 127.0.0.1:9000 ; Process Manager settings pm = dynamic pm.max_children = 50 pm.start_servers = 5 pm.min_spare_servers = 2 pm.max_spare_servers = 10 pm.process_idle_timeout = 10s pm.max_requests = 500 ; Memory limit - adjust based on your server's RAM and Magento's needs memory_limit = 512M max_execution_time = 180 upload_max_filesize = 64M post_max_size = 64M ; OPcache settings (highly recommended) opcache.enable=1 opcache.memory_consumption=128 opcache.interned_strings_buffer=16 opcache.max_accelerated_files=10000 opcache.revalidate_freq=60 opcache.validate_timestamps=1 opcache.enable_cli=1
Explanation of key settings:
pm:dynamicis a good starting point.ondemandcan save memory but might introduce slight latency on the first request after an idle period.staticprovides consistent performance but uses more memory.pm.max_children: This is the most critical setting. It defines the maximum number of PHP-FPM processes that can run concurrently. Too low, and you’ll get request queues. Too high, and you’ll exhaust server memory. Monitor your server’s RAM usage and adjust accordingly. A common starting point for a medium-sized instance might be 50-100.pm.start_servers,pm.min_spare_servers,pm.max_spare_servers: These control how PHP-FPM scales dynamically.pm.max_requests: Reusing processes can help prevent memory leaks. Set this to a reasonable number.memory_limit: Magento 2 is memory-intensive.512Mis a common minimum, but1024Mor more might be necessary for complex sites or during heavy operations like indexing.max_execution_time: Increase this for long-running Magento tasks.- OPcache: Essential for PHP performance. Ensure it’s enabled and configured with sufficient memory.
MongoDB Tuning for Magento 2
Magento 2 uses MongoDB for session storage and potentially other features. Optimizing MongoDB involves configuration tuning and proper indexing.
MongoDB Configuration (`mongod.conf`)
Key parameters in /etc/mongod.conf (or similar path) to consider:
storage:
dbPath: /var/lib/mongodb
journal:
enabled: true
engine: wiredTiger
# network interfaces
net:
port: 27017
bindIp: 127.0.0.1 # Or your server's IP if accessed remotely
# security:
# authorization: enabled
# logging:
# quiet: false
# traceAllExceptions: false
# verbosity: 0
# logAppend: true
# path: /var/log/mongodb/mongod.log
# operation profiling
# operationProfiling:
# mode: "off" # or "slowOp" or "all"
# Sharding (if applicable)
# sharding:
# clusterRole: configsvr
# # other sharding settings...
# WiredTiger specific settings
# wiredTiger:
# collectionConfig:
# cacheSizeGB: 0.5 # Example: 50% of RAM for WiredTiger cache
# engineConfig:
# cacheSizeGB: 0.5 # Example: 50% of RAM for WiredTiger cache
Tuning Considerations:
storage.engine:wiredTigeris the default and recommended engine.storage.journal.enabled: Keep this enabled for durability.net.bindIp: For security, bind MongoDB to127.0.0.1if it’s only accessed by the local Magento instance.- WiredTiger Cache: The
wiredTiger.collectionConfig.cacheSizeGBandwiredTiger.engineConfig.cacheSizeGBare crucial. Allocate a significant portion of your server’s RAM to the WiredTiger cache (e.g., 50-75% of available RAM, leaving enough for the OS and other services). Monitor cache hit rates usingdb.serverStatus(). - Profiling: Uncomment and set
operationProfiling.modetoslowOpduring tuning to identify slow queries.
Indexing for Magento 2 Sessions
Magento 2 typically uses MongoDB for session storage. Ensure the session collection is properly indexed for fast lookups.
Connect to your MongoDB instance and run:
mongo
use <your_magento_db_name> # e.g., use magento_prod
db.session.createIndex( { "session_id": 1 }, { unique: true } )
db.session.createIndex( { "modified_at": 1 }, { expireAfterSeconds: 1800 } ) # Example: auto-delete sessions older than 30 minutes
Explanation:
session_id: A unique index for fast retrieval of a specific session.modified_at: An index with an expiration time. This is crucial for automatically cleaning up old session data, preventing the collection from growing indefinitely. AdjustexpireAfterSecondsbased on your session timeout configuration.
OVH Specific Considerations
OVH’s infrastructure, particularly their Public Cloud instances, often comes with specific networking and storage configurations. Always check your instance’s allocated resources (CPU, RAM, I/O) and adjust tuning parameters accordingly. For storage, ensure your disk I/O is not a bottleneck, especially for MongoDB. Consider using SSD-based storage for your MongoDB data directory.
Monitoring and Iteration
Performance tuning is an ongoing process. Regularly monitor your server’s resource utilization (CPU, RAM, I/O, network), Nginx access logs, PHP-FPM logs, and MongoDB logs. Use tools like htop, iotop, netstat, Nginx’s stub_status module, and MongoDB’s serverStatus command. Analyze slow query logs for both Nginx and MongoDB. Iterate on these configurations based on observed performance and load.