• Skip to secondary menu
  • Skip to main content
  • Skip to primary sidebar
  • Home
  • Projects
  • Products
  • Themes
  • Tools
  • Request for Quote

Vengala Vinay

Having 9+ Years of Experience in Software Development

  • Home
  • WordPress
  • PHP
    • Codeigniter
  • Django
  • Magento
  • Selenium
  • Server
Home » The Ultimate DevOps Playbook: Tuning Nginx, Gunicorn/FPM, and MongoDB on Linode for Magento 2

The Ultimate DevOps Playbook: Tuning Nginx, Gunicorn/FPM, and MongoDB on Linode for Magento 2

Nginx Configuration for Magento 2 Performance

Optimizing Nginx is crucial for serving static assets efficiently and proxying dynamic requests to your Magento 2 application. We’ll focus on key directives that impact performance and security.

Worker Processes and Connections

The worker_processes directive determines how many worker processes Nginx will spawn. A common recommendation is to set it to the number of CPU cores available. worker_connections defines the maximum number of simultaneous connections that each worker process can handle. The total number of connections is limited by worker_processes * worker_connections.

Tuning nginx.conf

Locate your main Nginx configuration file, typically /etc/nginx/nginx.conf. Adjust the events block as follows:

user www-data;
worker_processes auto; # Or set to the number of CPU cores, e.g., 4
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
    worker_connections 4096; # Adjust based on expected load and system limits
    multi_accept on;
}

After modifying, test the configuration and reload Nginx:

sudo nginx -t
sudo systemctl reload nginx

Caching Strategies

Leveraging Nginx’s built-in caching for static assets and even full page caching (though Magento’s Varnish or built-in cache is preferred for dynamic content) can significantly reduce server load. We’ll configure browser caching and potentially a proxy cache.

Browser Caching for Static Assets

In your Magento 2 site’s server block (e.g., /etc/nginx/sites-available/your-magento-site), add directives to control browser caching for static files. This tells the client’s browser how long to cache these resources.

location ~* ^/(media|static)/ {
    expires 365d;
    add_header Cache-Control "public";
    access_log off;
    log_not_found off;
}

Proxy Caching (Optional, for static files only)

For static assets that are not served directly by Magento’s `pub/static` or `pub/media` directories (e.g., custom themes, third-party extensions), you might consider Nginx’s proxy cache. This is less common for Magento due to its complex caching mechanisms but can be useful for specific scenarios.

# Define cache path in http block
http {
    # ... other http directives ...
    proxy_cache_path /var/cache/nginx/static levels=1:2 keys_zone=STATIC_CACHE:10m max_size=10g inactive=60m use_temp_path=off;

    # ... server blocks ...
}

# Inside your Magento server block
location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$ {
    proxy_pass http://your_backend_app; # Or directly serve if files are local
    proxy_cache STATIC_CACHE;
    proxy_cache_valid 200 302 10m;
    proxy_cache_valid 404 1m;
    proxy_cache_key "$scheme$request_method$host$request_uri";
    add_header X-Cache-Status $upstream_cache_status;
}

Gzip Compression

Enabling Gzip compression significantly reduces the size of text-based assets (HTML, CSS, JavaScript), leading to faster load times. Ensure it’s enabled in your nginx.conf or site-specific configuration.

# In http or server block
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
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;
gzip_disable "msie6"; # Disable for older IE versions if necessary

SSL/TLS Optimization

For secure connections, optimize SSL/TLS settings to improve handshake times and reduce CPU overhead. This includes enabling HTTP/2 and configuring strong ciphers.

# In server block for HTTPS
listen 443 ssl http2;
listen [::]:443 ssl http2;

ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off; # Consider security implications if enabled
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s; # Use your preferred DNS resolvers
resolver_timeout 5s;

Gunicorn/PHP-FPM Tuning for Magento 2

The application server (Gunicorn for Python-based frameworks, or PHP-FPM for PHP) is where your Magento 2 code executes. Tuning its worker processes and resource allocation is critical.

Gunicorn Tuning (if applicable)

If you’re using a Python framework with Gunicorn as the WSGI server for Magento (less common, typically Magento uses PHP), tuning involves adjusting the number of worker processes and threads. The optimal configuration depends heavily on your server’s CPU and RAM.

Worker Processes and Threads

A common starting point for Gunicorn is to use the sync worker class with a number of workers equal to (2 * CPU_CORES) + 1. For I/O-bound applications, consider the gevent or event worker classes, which support asynchronous I/O and can handle more concurrent connections with fewer processes.

# Example Gunicorn command line
gunicorn --workers 4 --threads 2 --bind 0.0.0.0:8000 your_app.wsgi:application

The --threads option is only applicable to certain worker classes like gthread or gevent. For sync workers, threads are not used.

PHP-FPM Tuning

For standard Magento 2 installations, PHP-FPM is the workhorse. Tuning PHP-FPM involves configuring its process manager (pm) and related directives. The most common process managers are static, dynamic, and ondemand.

Process Manager (pm) Configuration

Locate your PHP-FPM pool configuration file (e.g., /etc/php/8.1/fpm/pool.d/www.conf). The choice of pm significantly impacts performance and resource usage.

  • pm = dynamic: This is often a good balance. PHP-FPM will spawn children as needed, up to pm.max_children, and kill idle children to save memory.
  • pm = static: PHP-FPM spawns a fixed number of children (pm.max_children) at startup. This can be faster if you have consistent high traffic but can waste memory if traffic is low.
  • pm = ondemand: PHP-FPM spawns children only when a request comes in and kills them after a timeout. This saves memory but can introduce latency for the first request after a period of inactivity.

Here’s a sample configuration for dynamic, assuming a server with 4 CPU cores and 16GB RAM. Adjust these values based on your specific server resources and Magento’s memory footprint.

; /etc/php/8.1/fpm/pool.d/www.conf

[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       ; Max number of child processes to spawn.
pm.start_servers = 10       ; Number of child processes to start when pm = dynamic.
pm.min_spare_servers = 5    ; Number of child processes to keep idle.
pm.max_spare_servers = 20   ; Number of child processes to keep idle.
pm.process_idle_timeout = 10s ; The timeout for killing idle processes.

; For static pm, you'd set:
; pm = static
; pm.max_children = 150

; For ondemand pm, you'd set:
; pm = ondemand
; pm.max_children = 50
; pm.process_idle_timeout = 10s

request_terminate_timeout = 120s ; Timeout for script execution. Crucial for long Magento tasks.
request_slowlog_timeout = 30s    ; Log scripts that take longer than this.
slowlog = /var/log/php/php8.1-fpm.slow.log

catch_workers_output = yes
catch_workers_output_level = notice
decorate_user = no

; Memory limit for PHP scripts. Magento typically needs a good amount.
; This is also set in php.ini, but FPM pool can override.
; php_admin_value[memory_limit] = 512M
; php_admin_value[max_execution_time] = 180
; php_admin_value[upload_max_filesize] = 64M
; php_admin_value[post_max_size] = 64M

Important Considerations for PHP-FPM:

  • pm.max_children: This is the most critical setting. Too low, and you’ll get 502 errors under load. Too high, and you’ll run out of RAM. A good starting point is to monitor your server’s RAM usage and the number of active PHP-FPM processes. A common formula is (Total RAM - RAM for OS/DB/Nginx) / Average RAM per PHP-FPM process.
  • memory_limit: Ensure this is set high enough for Magento’s operations (e.g., 512M or 1GB).
  • max_execution_time: Magento tasks like indexing or cron jobs can take a long time. Set this appropriately (e.g., 180s or more).
  • request_slowlog_timeout: Use this to identify slow-running scripts.

After changes, restart PHP-FPM:

sudo systemctl restart php8.1-fpm

MongoDB Tuning for Magento 2

Magento 2 uses MongoDB for session storage and potentially other features (like catalog search if configured). Optimizing MongoDB involves memory usage, indexing, and query performance.

Memory Management (WiredTiger)

MongoDB’s default storage engine, WiredTiger, uses a buffer pool for caching data and indexes in RAM. The storage.wiredTiger.engineConfig.cacheSizeGB setting is crucial. A common recommendation is to allocate 50% of the system’s RAM to the WiredTiger cache, up to a maximum of around 30-50GB on systems with very large amounts of RAM.

Tuning mongod.conf

Edit your MongoDB configuration file, typically /etc/mongod.conf.

# /etc/mongod.conf
storage:
  dbPath: /var/lib/mongodb
  journal:
    enabled: true
  wiredTiger:
    engineConfig:
      cacheSizeGB: 2 # Adjust this value based on your server's RAM. E.g., 4 for 8GB RAM, 8 for 16GB RAM.
      # Ensure cacheSizeGB does not exceed ~50% of system RAM or ~30-50GB.

# network interfaces
net:
  port: 27017
  bindIp: 127.0.0.1 # Or your server's IP if accessed remotely, but restrict access.

# security:
#   authorization: enabled # Highly recommended for production

# logging:
#   quiet: false
#   path: /var/log/mongodb/mongod.log
#   logAppend: true
#   verbosity: 0

# operationProfiling:
#   slowOpThresholdMs: 100 # Log slow operations (e.g., > 100ms)
#   mode: slowOp

After modifying, restart MongoDB:

sudo systemctl restart mongod

Indexing for Magento Sessions

Magento uses MongoDB for sessions. Ensure that the necessary indexes are present for efficient session lookup. MongoDB typically creates indexes automatically, but it’s good practice to verify.

# Connect to MongoDB
mongo

# Switch to the Magento session database (usually 'magento_sessions' or similar)
use magento_sessions

# List existing indexes on the 'sessions' collection
db.sessions.getIndexes()

# If indexes are missing, create them. Magento usually handles this, but for manual creation:
# db.sessions.createIndex( { sess_id: 1 }, { unique: true } )
# db.sessions.createIndex( { sess_lifetime: 1 }, { expireAfterSeconds: 1800 } ) # Example for session expiration

The sess_lifetime index with an expiration is crucial for automatically cleaning up old sessions. Magento’s session handler should manage this, but verify its configuration.

Query Optimization and Monitoring

Enable slow query logging in MongoDB to identify queries that are impacting performance. Magento’s session operations are typically simple lookups, but complex search queries or custom module integrations can lead to slow MongoDB operations.

# In mongod.conf
operationProfiling:
  slowOpThresholdMs: 100 # Log operations taking longer than 100ms
  mode: slowOp

After restarting MongoDB, slow queries will be logged to the configured log file (e.g., /var/log/mongodb/mongod.log). Analyze these logs to identify problematic queries and consider adding appropriate indexes or optimizing the application code that generates them.

Connection Pooling

Ensure your Magento application is configured to use connection pooling for MongoDB. This reuses existing database connections, reducing the overhead of establishing new connections for each request. Magento’s default configuration usually handles this correctly via its dependency injection system.

Putting It All Together: Linode Specifics and Monitoring

When deploying on Linode, consider the instance type. For Magento, CPU, RAM, and I/O performance are all critical. SSD-based storage is a must.

Linode Instance Selection

Choose an instance with sufficient RAM to accommodate PHP-FPM workers, MongoDB, and the operating system. For production Magento 2, a Dedicated CPU or High Memory plan is often recommended. Monitor your Linode’s resource utilization (CPU, RAM, I/O wait) using Linode’s dashboard and server-side tools.

Monitoring Tools

Implement comprehensive monitoring:

  • Nginx: Use stub_status module for basic connection metrics. Integrate with Prometheus/Grafana for advanced monitoring.
  • PHP-FPM: The status_path in FPM configuration allows monitoring via a web page or scraping tools.
  • MongoDB: Use mongostat, mongotop, and MongoDB’s built-in profiling. Integrate with Prometheus exporters.
  • System Metrics: Tools like htop, iotop, vmstat, and Linode’s own monitoring are essential.
  • Application Performance Monitoring (APM): Tools like New Relic, Datadog, or Tideways can provide deep insights into Magento’s performance bottlenecks, including slow database queries.

Firewall Configuration

Ensure your firewall (e.g., ufw or Linode’s Cloud Firewall) is configured to allow only necessary ports (80, 443, SSH, and MongoDB if accessed remotely, though local access is preferred).

# Example UFW configuration
sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
sudo ufw allow from 127.0.0.1 to any port 27017 proto tcp # Allow local MongoDB access
sudo ufw enable

This playbook provides a solid foundation for tuning your Magento 2 stack on Linode. Remember that performance tuning is an iterative process. Continuously monitor your system, analyze metrics, and make adjustments as needed.

Primary Sidebar

A little about the Author

Having 9+ Years of Experience in Software Development.
Expertised in Php Development, WordPress Custom Theme Development (From scratch using underscores or Genesis Framework or using any blank theme or Premium Theme), Custom Plugin Development. Hands on Experience on 3rd Party Php Extension like Chilkat, nSoftware.

Recent Posts

  • Disaster Recovery 101: Architecting Auto-Failovers for Redis and PHP Deployments on OVH
  • How We Audited a High-Traffic WooCommerce Enterprise Stack on Google Cloud and Mitigated Race conditions during high-concurrency payment processing
  • Disaster Recovery 101: Architecting Auto-Failovers for Elasticsearch and Magento 2 Deployments on DigitalOcean
  • An Auditor’s Checklist for Securing WordPress Backends on OVH
  • Step-by-Step: Diagnosing Perl script high CPU throttling due to unoptimized regular expressions on AWS Servers

Copyright © 2026 · Vinay Vengala