The Ultimate DevOps Playbook: Tuning Nginx, Gunicorn/FPM, and MongoDB on DigitalOcean for Magento 2
Nginx Configuration for Magento 2 Performance
Optimizing Nginx is crucial for serving Magento 2 efficiently. We’ll focus on key directives that impact request handling, caching, and resource utilization. This assumes a standard DigitalOcean droplet setup with Nginx installed.
Worker Processes and Connections
The worker_processes directive dictates how many worker processes Nginx will spawn. Setting this to auto is generally recommended, allowing Nginx to determine the optimal number based on available CPU cores. worker_connections defines the maximum number of simultaneous connections a worker process can handle. A common starting point is 1024, but this can be increased based on anticipated traffic.
Edit your main Nginx configuration file, typically located at /etc/nginx/nginx.conf:
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 4096; # Increased from default 1024
multi_accept on;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# ... other http configurations
}
Gzip Compression
Enabling Gzip compression significantly reduces the size of static and dynamic content sent to the client, improving load times. Configure it within the http block.
http {
# ... other http configurations
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6; # Compression level (1-9)
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;
}
Browser Caching
Leverage browser caching for static assets to reduce server load and improve perceived performance for repeat visitors. This is typically configured within your Magento 2 site’s server block.
server {
# ... other server configurations
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|eot|otf|ttf|woff|woff2)$ {
expires 30d; # Cache for 30 days
add_header Cache-Control "public, no-transform";
access_log off;
}
# ... other location blocks
}
PHP-FPM Configuration (for PHP-FPM setup)
If you’re using PHP-FPM to serve your Magento 2 application, tuning its process manager is critical. We’ll focus on the pm.max_children, pm.start_servers, pm.min_spare_servers, and pm.max_spare_servers directives. These control how PHP-FPM manages its worker processes.
Locate your PHP-FPM pool configuration file. For PHP 8.1, this is often /etc/php/8.1/fpm/pool.d/www.conf. Adjust the values based on your server’s RAM. A common rule of thumb is to set pm.max_children such that the total memory usage of all child processes does not exceed 70-80% of your server’s available RAM.
[global]
pid = /run/php/php8.1-fpm.pid
error_log = /var/log/php8.1-fpm.log
log_level = notice
[www]
user = www-data
group = www-data
listen = /run/php/php8.1-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
pm = dynamic
pm.max_children = 100 ; Adjust based on RAM. Example: 100 processes * ~30MB/process = ~3GB RAM usage.
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.process_idle_timeout = 10s
pm.max_requests = 500 ; Restart child processes after this many requests to prevent memory leaks.
access.log = /var/log/php8.1-fpm.access.log
access.format = "%R - %u %t \"%m %r%q%Q\" %s %O \"%{Referer}i\" \"%{User-Agent}i\""
slowlog = /var/log/php8.1-fpm.slow.log
request_slowlog_timeout = 10s
catch_workers_output = yes
After modifying the PHP-FPM configuration, restart the service:
sudo systemctl restart php8.1-fpm
Gunicorn Configuration (for Gunicorn setup)
If you’re using Gunicorn as your Python WSGI HTTP Server, tuning its worker count and type is essential. For Magento 2, which is PHP-based, Gunicorn is not typically used directly. However, if you have a microservice or a separate Python component that interacts with Magento, here’s a typical Gunicorn tuning example.
The number of workers is often calculated as (2 * number_of_cores) + 1. The worker class can be sync (default, blocking) or gevent/eventlet (asynchronous, non-blocking) for I/O-bound tasks.
# Example command line for starting Gunicorn # Assuming 4 CPU cores gunicorn --workers 9 --worker-class gevent --bind 0.0.0.0:8000 myapp.wsgi:application
For a production deployment, you’d typically manage Gunicorn with a process manager like systemd.
[Unit] Description=Gunicorn instance to serve myapp After=network.target [Service] User=myappuser Group=www-data WorkingDirectory=/path/to/your/myapp ExecStart=/path/to/your/venv/bin/gunicorn --workers 9 --worker-class gevent --bind unix:/run/gunicorn.sock myapp.wsgi:application [Install] WantedBy=multi-user.target
MongoDB Performance Tuning
MongoDB’s performance is heavily influenced by its configuration, indexing, and hardware. For Magento 2, MongoDB is often used for session storage, caching, and sometimes for specific features like the Page Builder. We’ll focus on server configuration and basic indexing strategies.
MongoDB Configuration File
The primary configuration file is mongod.conf, typically located at /etc/mongod.conf. Key parameters include:
storage.engine: For modern MongoDB versions,wiredTigeris the default and recommended engine.storage.wiredTiger.engineConfig.cacheSizeGB: This is critical. Allocate a significant portion of your server’s RAM to the WiredTiger cache. A common recommendation is 50-75% of available RAM, leaving enough for the OS and other processes.operationProfiling.mode: Set toslowOporallfor profiling slow queries.net.bindIp: Ensure it’s set to bind to the correct network interface (e.g.,0.0.0.0for all interfaces, or a specific private IP).
storage:
dbPath: /var/lib/mongodb
journal:
enabled: true
engine: wiredTiger
wiredTiger:
engineConfig:
cacheSizeGB: 4 # Example: For an 8GB RAM server, leave 4GB for OS/other services.
operationProfiling:
mode: slowOp # Or 'all' for more detailed profiling
slowOpThresholdMs: 100
net:
port: 27017
bindIp: 0.0.0.0 # Or your specific private IP
After modifying mongod.conf, restart MongoDB:
sudo systemctl restart mongod
Indexing Strategies
Proper indexing is paramount for MongoDB performance. Magento 2’s session and cache collections can become bottlenecks if not indexed correctly. Use the MongoDB shell to inspect and create indexes.
Connect to your MongoDB instance:
mongo
Example: Indexing the Magento session collection (assuming your database is named magento_db):
use magento_db;
db.sessions.createIndex( { "id": 1 }, { unique: true, expireAfterSeconds: 1800 } ); // Index for session ID with TTL
db.sessions.createIndex( { "modified": 1 } ); // Index for session modification time
For cache collections, the specific fields to index depend on your Magento configuration (e.g., cache type, tags). Inspect your application’s usage patterns.
Monitoring and Diagnostics
Continuous monitoring is key to identifying performance regressions. Utilize tools like:
- Nginx: Access logs, error logs,
nginx -s reloadfor configuration reloads,htopfor process monitoring. - PHP-FPM: Slow log, error log,
php-fpm -tfor configuration test,systemctl status phpX.Y-fpm. - Gunicorn: Application logs,
systemctl status gunicorn. - MongoDB:
mongostat,mongotop, slow query logs,db.serverStatus(),db.stats(). - System:
htop,iotop,vmstat,dmesg.
For Nginx, consider enabling the stub_status module for real-time connection metrics:
http {
# ... other http configurations
server {
listen 80;
server_name your_domain.com;
location /nginx_status {
stub_status;
allow 127.0.0.1; # Restrict access to localhost
deny all;
}
# ... other Magento configurations
}
}
Access http://your_domain.com/nginx_status to see metrics like active connections, accepted connections, handled connections, and requests.