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

Vengala Vinay

Having 12+ Years of Experience in Software Development

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

The Ultimate DevOps Playbook: Tuning Nginx, Gunicorn/FPM, and Redis on OVH for C

Nginx as a High-Performance Reverse Proxy and Load Balancer

When deploying applications on OVH, particularly those leveraging Python (with Gunicorn) or PHP (with FPM), Nginx serves as the indispensable front-end. Its efficiency in handling static assets, SSL termination, and request routing is paramount. We’ll focus on tuning Nginx for optimal performance in this specific environment.

Nginx Configuration Tuning

The core of Nginx performance tuning lies within its nginx.conf file, typically located at /etc/nginx/nginx.conf or within /etc/nginx/conf.d/. We’ll adjust key worker processes and connection parameters.

Worker Processes and Connections

The worker_processes directive should ideally be set to the number of CPU cores available on your OVH instance. This allows Nginx to utilize all available processing power for handling requests concurrently. The worker_connections directive defines the maximum number of simultaneous connections that each worker process can open. A common starting point is 1024, but this can be increased based on expected traffic load and system memory.

user www-data;
worker_processes auto; # Or set to the number of CPU cores
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;

    # SSL configuration
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m; # Adjust size as needed
    ssl_session_timeout 10m;

    # Gzip compression
    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;

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

Explanation:

  • worker_processes auto;: Automatically sets the number of worker processes to the number of available CPU cores.
  • worker_connections 4096;: Significantly increases the connection limit per worker, allowing for more concurrent requests.
  • sendfile on;: Enables efficient transfer of files from disk to network socket without user-space buffering.
  • tcp_nopush on;: Instructs Nginx to send header and file in one packet if possible.
  • tcp_nodelay on;: Disables the Nagle algorithm, reducing latency for small packets.
  • keepalive_timeout 65;: Sets the keep-alive timeout for client connections.
  • gzip on;: Enables Gzip compression for responses.
  • gzip_types ...;: Specifies the MIME types to be compressed.
  • ssl_session_cache shared:SSL:10m;: Configures a shared SSL session cache for improved handshake performance.

Caching and Static File Serving

Nginx excels at serving static files. Configuring appropriate caching headers and directives can offload significant load from your application servers.

location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$ {
    expires 30d;
    add_header Cache-Control "public, immutable";
    access_log off;
    log_not_found off;
}

Explanation:

  • expires 30d;: Sets the Expires header to 30 days in the future, instructing browsers to cache these assets.
  • add_header Cache-Control "public, immutable";: Provides more granular control over caching, indicating that the resource is publicly cacheable and its content will not change.
  • access_log off; and log_not_found off;: Disables logging for static assets to reduce disk I/O and improve performance.

Gunicorn Tuning for Python Applications

Gunicorn (Green Unicorn) is a popular WSGI HTTP Server for Python. Its performance is heavily influenced by the number of worker processes and the type of worker class used.

Worker Processes and Threads

The --workers flag determines the number of worker processes Gunicorn will spawn. A common recommendation is (2 * CPU_CORES) + 1. For I/O-bound applications, using --threads with the gthread worker class can improve concurrency without the overhead of multiple processes.

# Example command to start Gunicorn
gunicorn --workers 5 \
         --bind 0.0.0.0:8000 \
         --worker-class sync \
         --timeout 120 \
         your_project.wsgi:application

# For threaded workers (if your application is I/O bound)
gunicorn --workers 2 \
         --threads 4 \
         --bind 0.0.0.0:8000 \
         --worker-class gthread \
         --timeout 120 \
         your_project.wsgi:application

Explanation:

  • --workers 5: Spawns 5 worker processes. Adjust based on your OVH instance’s CPU cores.
  • --bind 0.0.0.0:8000: Listens on all network interfaces on port 8000. Nginx will proxy to this.
  • --worker-class sync: The default and most common worker class, suitable for CPU-bound tasks.
  • --worker-class gthread: Uses threads for concurrency, beneficial for I/O-bound applications. Requires careful consideration of GIL limitations.
  • --threads 4: Specifies the number of threads per worker when using gthread.
  • --timeout 120: Sets the worker timeout to 120 seconds. Adjust based on your application’s longest-running requests.

Gunicorn Configuration File

For more complex configurations, using a Python configuration file is recommended. This file can be loaded using the -c flag.

# gunicorn_config.py
import multiprocessing

bind = "0.0.0.0:8000"
workers = multiprocessing.cpu_count() * 2 + 1
worker_class = "sync" # or "gthread"
threads = 4 # if using gthread
timeout = 120
loglevel = "info"
accesslog = "-" # Log to stdout
errorlog = "-"  # Log to stderr

# Example for gthread
# workers = 2
# threads = 4
# worker_class = "gthread"
# Example command using config file
gunicorn -c gunicorn_config.py your_project.wsgi:application

PHP-FPM Tuning

For PHP applications, PHP-FPM (FastCGI Process Manager) is the standard. Tuning its process management and performance settings is crucial.

PHP-FPM Pool Configuration

The primary configuration file for PHP-FPM pools is typically found in /etc/php/[version]/fpm/pool.d/www.conf. Key directives to adjust include the process manager settings.

; /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 = 50
pm.start_servers = 5
pm.min_spare_servers = 2
pm.max_spare_servers = 10
pm.process_idle_timeout = 10s
pm.max_requests = 500

; For static process management (use with caution, can be less flexible)
; pm = static
; pm.max_children = 20

; Other performance-related settings
request_terminate_timeout = 120
; rlimit_files = 1024
; rlimit_nofile = 65536

Explanation:

  • pm = dynamic: PHP-FPM will dynamically manage the number of child processes based on load.
  • pm.max_children: The maximum number of child processes that will be created. This is a critical setting and should be tuned based on server memory and CPU. Too high can lead to OOM errors.
  • pm.start_servers: The number of child processes to start when PHP-FPM starts.
  • pm.min_spare_servers: The minimum number of idle supervisor processes.
  • pm.max_spare_servers: The maximum number of idle supervisor processes.
  • pm.process_idle_timeout: The number of seconds after which an idle process will be killed.
  • pm.max_requests: The number of requests each child process should execute before respawning. This helps prevent memory leaks.
  • request_terminate_timeout: The number of seconds a script is allowed to run before it is terminated.

Choosing the Right Process Manager

Dynamic PM: Recommended for most use cases. It balances resource usage by scaling processes up and down. Tune max_children carefully. A common starting point is (total_memory_in_MB / average_process_memory_in_MB) / 2, but empirical testing is key.

Static PM: Useful for predictable, high-traffic environments where you want to ensure a fixed number of processes are always available. This can reduce latency by eliminating process startup time but may waste resources if traffic is low.

On-Demand PM: (Less common for high-performance scenarios) Processes are spawned only when a request is received and killed after a period of inactivity. Good for saving memory but can introduce latency.

Redis Performance Tuning

Redis is an in-memory data structure store, often used as a cache, message broker, and database. Optimizing its configuration on OVH is vital for fast data retrieval.

Redis Configuration File

The primary configuration file is redis.conf, typically located at /etc/redis/redis.conf.

# /etc/redis/redis.conf

# General
daemonize yes
pidfile /var/run/redis/redis-server.pid
logfile /var/log/redis/redis-server.log
loglevel notice

# Network
bind 127.0.0.1 ::1 # Bind to localhost for security if Nginx/App are on the same server
# bind 0.0.0.0 # If Redis is on a separate server or needs external access (use with firewall)
port 6379
tcp-backlog 511 # Default is 511, can be increased if OS allows

# Memory Management
maxmemory 256mb # Set a limit to prevent Redis from consuming all system RAM
maxmemory-policy allkeys-lru # Eviction policy: LRU (Least Recently Used) is common

# Persistence (adjust based on needs)
save "" # Disable RDB persistence if only using as a cache
appendonly no # Disable AOF persistence if only using as a cache

# Performance
tcp-keepalive 300 # Keep TCP connections alive for 5 minutes
databases 16



Explanation:

  • bind 127.0.0.1 ::1: Restricts Redis to listen only on the local loopback interface. Crucial for security if your application and Redis are on the same OVH instance. If on separate instances, use a private IP and secure with a firewall.
  • maxmemory 256mb: Sets a hard limit on Redis memory usage. Essential to prevent it from consuming all available RAM and causing system instability. Adjust this value based on your OVH instance's RAM and your application's caching needs.
  • maxmemory-policy allkeys-lru: When maxmemory is reached, Redis will evict the least recently used keys. Other policies include volatile-lru, allkeys-random, etc.
  • save "" and appendonly no: If Redis is purely used as a cache and data loss on restart is acceptable, disabling persistence significantly reduces disk I/O and can improve performance.
  • tcp-backlog 511: The maximum number of pending connections. Increasing this can help under heavy load, but requires OS-level tuning (e.g., net.core.somaxconn).
  • tcp-keepalive 300: Keeps idle TCP connections open for a longer period, reducing the overhead of establishing new connections for frequent Redis operations.

Monitoring Redis

Regularly monitor Redis performance using redis-cli INFO and tools like RedisInsight or Prometheus with the Redis exporter. Key metrics include:

  • used_memory: Current memory usage.
  • mem_fragmentation_ratio: Indicates memory fragmentation. A ratio > 1.5 might suggest memory issues.
  • instantaneous_ops_per_sec: Current operations per second.
  • keyspace_hits and keyspace_misses: Crucial for cache hit ratio. Aim for a high hit ratio.
redis-cli
127.0.0.1:6379> INFO memory
127.0.0.1:6379> INFO stats
127.0.0.1:6379> INFO persistence
127.0.0.1:6379> INFO commandstats # To see performance of individual commands

Putting It All Together: OVH Deployment Strategy

On an OVH instance, a typical setup would involve:

  1. Nginx: Configured as a reverse proxy, handling SSL termination, static file serving, and forwarding dynamic requests to Gunicorn/PHP-FPM. It should listen on port 80/443.
  2. Gunicorn/PHP-FPM: Running on a non-privileged port (e.g., 8000 for Gunicorn, 9000 for PHP-FPM) or via a Unix socket. Nginx will proxy requests to these. Ensure they are configured to run as a non-root user (e.g., www-data).
  3. Redis: Running on 127.0.0.1 (if on the same server) with appropriate maxmemory and eviction policies.

Example Nginx Virtual Host Configuration:

# /etc/nginx/sites-available/your_app
server {
    listen 80;
    server_name your_domain.com www.your_domain.com;

    # Redirect HTTP to HTTPS
    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl http2;
    server_name your_domain.com www.your_domain.com;

    # SSL Configuration (ensure you have certs)
    ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    # Static files
    location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$ {
        root /var/www/your_app/public; # Adjust path to your static assets
        expires 30d;
        add_header Cache-Control "public, immutable";
        access_log off;
        log_not_found off;
    }

    # Dynamic requests to Gunicorn
    location / {
        proxy_pass http://127.0.0.1:8000; # For Gunicorn
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 300s; # Increase timeout if needed
        proxy_connect_timeout 75s;
    }

    # Dynamic requests to PHP-FPM
    # location ~ \.php$ {
    #     include snippets/fastcgi-php.conf;
    #     fastcgi_pass unix:/run/php/php8.1-fpm.sock; # Adjust PHP version
    #     fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    #     include fastcgi_params;
    #     fastcgi_read_timeout 300s;
    # }

    root /var/www/your_app/public; # Default root for PHP-FPM
    index index.php index.html index.htm;
}

By meticulously tuning these components—Nginx for efficient request handling, Gunicorn/PHP-FPM for application execution, and Redis for fast caching—you can achieve a highly performant and scalable infrastructure on OVH.

Primary Sidebar

A little about the Author

Having 12+ Years of Experience in Software Development, Vinay is a principal software architect, senior systems engineer, and elite technical consultant. He specializes in bespoke PHP/WordPress development, high-performance Magento 2 & Shopify architectures, custom plugin/theme development from scratch, and legacy code modernization (including VB6, VB.NET, PyQt, and Crystal Reports). Known for solving complex database bottlenecks, speed optimization (Core Web Vitals), and advanced security code auditing, Vinay engineers production-ready systems designed to scale under heavy concurrent load conditions.



Chat on WhatsApp

Recent Posts

  • Go Goroutines vs. Node.js Event Loop: Scaling I/O-Bound Microservices Under High Load
  • Elixir Phoenix vs. Go Gin: Concurrency Models and Fault Tolerance Under Peak Request Volume
  • Python Celery vs. Go Channels: Distributed Task Queue Overhead and Memory Reliability
  • Scala Pekko vs. Go Goroutines: Actor Model vs. CSP for Event-Driven Reactive Systems
  • Java Loom Virtual Threads vs. Go Goroutines: Under-the-Hood Scheduler and Thread Overhead Comparison

Categories

  • apache (1)
  • Business & Monetization (390)
  • Centos (4)
  • Comparisons & Decision Making (55)
  • Debian (2)
  • Debugging & Troubleshooting (584)
  • Desktop Applications (14)
  • DevOps (7)
  • DevOps & Cloud Scaling (962)
  • Django (1)
  • Laravel (4)
  • Migration & Architecture (192)
  • Mobile Applications (24)
  • MySQL (1)
  • Performance & Optimization (806)
  • PHP (5)
  • PHP Development (21)
  • Plugins & Themes (244)
  • Programming Languages (9)
  • Python (19)
  • Ruby on Rails (1)
  • Security & Compliance (543)
  • SEO & Growth (491)
  • Server (23)
  • Ubuntu (9)
  • VB6 & VB.NET (8)
  • Web Applications & Frontend (19)
  • Web Assembly (Wasm) (2)
  • WordPress (22)
  • WordPress Plugin Development (7)
  • WordPress Theme Development (357)

Recent Posts

  • Go Goroutines vs. Node.js Event Loop: Scaling I/O-Bound Microservices Under High Load
  • Elixir Phoenix vs. Go Gin: Concurrency Models and Fault Tolerance Under Peak Request Volume
  • Python Celery vs. Go Channels: Distributed Task Queue Overhead and Memory Reliability

Top Categories

  • DevOps & Cloud Scaling (962)
  • Performance & Optimization (806)
  • Debugging & Troubleshooting (584)
  • Security & Compliance (543)
  • SEO & Growth (491)
  • Business & Monetization (390)

Our Products

  • ERP & LMS Systems (4)
  • Directories & Marketplaces (4)
  • Healthcare Portals (3)
  • Point of Sale (POS) (2)
  • E-Commerce Engines (2)

Our Services

  • E-Commerce Development (10)
  • WordPress Development (8)
  • Python & Desktop GUI (7)
  • General Consulting (7)
  • Legacy Modernization (5)
  • Mobile App Development (4)

Copyright © 2026 · Vinay Vengala