The latest version for WHMCS with Nginx for Cloudpanel. Production version with Hetzner and GCP working

Overview

This NGINX configuration is specifically designed for hosting a WHMCS installation with enhanced security features, SSL support, and optimized performance settings. Let’s break down each major section and understand its purpose.

Basic Server Configuration

server {
  listen 80;
  listen [::]:80;
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  {{ssl_certificate_key}}
  {{ssl_certificate}}
  server_name hosting.yoursite.com;
}

This section configures the server to:

  • Listen on both IPv4 and IPv6 for HTTP (port 80) and HTTPS (port 443)
  • Support HTTP/2 protocol for improved performance
  • Use SSL certificates (placeholders indicated by double curly braces)
  • Specify the server name as hosting.yoursite.com

SSL Redirect

if ($scheme != "https") {
  rewrite ^ https://$host$uri permanent;
}

This block ensures all HTTP traffic is permanently redirected to HTTPS, enforcing secure connections.

Core WHMCS Configuration

The configuration includes several specialized location blocks for WHMCS functionality:

Client Area Routes

location ~ /announcements/?(.*)$ {
    rewrite ^/(.*)$ /hosting/index.php?rp=/announcements/$1;
}

Similar patterns are implemented for:

  • Downloads
  • Knowledge Base
  • SSL Certificate Store
  • SiteLock
  • Website Builder
  • Order Processing
  • Account Management
  • Payment Methods
  • Password Reset
  • Security Settings
  • Subscription Management

Admin Area Security

location ~ /admin/(addons|apps|search|domains|help\/license|services|setup|utilities\/system\/php-compat)(.*) {
    rewrite ^/(.*)$ /hosting/admin/index.php?rp=/admin/$1$2 last;
}

The admin area configuration includes specialized rewrites for:

  • Client Payment Methods
  • Authentication Setup
  • Ticket Management
  • Invoice Processing
  • Two-Factor Authentication
  • Intelligent Search

Security Measures

Vendor Directory Protection

location ^~ /vendor/ {
    deny all;
    return 403;
}

This critical security measure prevents direct access to the vendor directory, addressing the security advisory from January 28, 2020.

Well-Known Directory Access

location ~ /.well-known {
    auth_basic off;
    allow all;
}

Allows access to the .well-known directory, necessary for SSL certificate validation and other standardized URLs.

PHP Configuration

location ~ \.php$ {
    include fastcgi_params;
    fastcgi_intercept_errors on;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    try_files $uri =404;
    fastcgi_read_timeout 3600;
    fastcgi_send_timeout 3600;
    fastcgi_param HTTPS $fastcgi_https;
    fastcgi_pass 127.0.0.1:{{php_fpm_port}};
    fastcgi_param PHP_VALUE "{{php_settings}}";
}

This section handles PHP processing with:

  • Extended timeouts for long-running processes (3600 seconds)
  • FastCGI configuration for PHP-FPM
  • HTTPS parameter passing
  • Custom PHP settings support

Static Content Optimization

location ~* ^.+\.(css|js|jpg|jpeg|gif|png|ico|gz|svg|svgz|ttf|otf|woff|woff2|eot|mp4|ogg|ogv|webm|webp|zip|swf)$ {
    add_header Access-Control-Allow-Origin "*";
    expires max;
    access_log off;
}

Optimizes static content delivery by:

  • Setting CORS headers
  • Maximizing cache duration
  • Disabling access logging for better performance

Best Practices Implementation

  1. Security

    • Forces HTTPS
    • Protects sensitive directories
    • Implements proper PHP handling
    • Includes security headers
  2. Performance

    • HTTP/2 support
    • Static content optimization
    • Efficient routing rules
    • Extended timeouts for complex operations
  3. Maintainability

    • Well-organized structure
    • Clear section separation
    • Template variables for flexible deployment
    • Comprehensive routing rules
server {
  listen 80;
  listen [::]:80;
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  {{ssl_certificate_key}}
  {{ssl_certificate}}
  server_name hosting.yoursite.com;
  {{root}}

  {{nginx_access_log}}
  {{nginx_error_log}}

  if ($scheme != "https") {
    rewrite ^ https://$host$uri permanent;
  }

  location ~ /.well-known {
    auth_basic off;
    allow all;
  }

  {{settings}}

  try_files $uri $uri/ /index.php?$args;
  index index.php index.html;

  location / {
    error_page 404 /index.php?$query_string;
    try_files $uri $uri/ /index.php?$query_string;
  }

   location ~ /announcements/?(.*)$ {
        rewrite ^/(.*)$ /hosting/index.php?rp=/announcements/$1;
    }

    location ~ /download/?(.*)$ {
        rewrite ^/(.*)$ /hosting/index.php?rp=/download$1;
    }

    location ~ /knowledgebase/?(.*)$ {
        rewrite ^/(.*)$ /hosting/index.php?rp=/knowledgebase/$1;
    }

    location ~ /store/ssl-certificates/?(.*)$ {
        rewrite ^/(.*)$ /hosting/index.php?rp=/store/ssl-certificates/$1;
    }

    location ~ /store/sitelock/?(.*)$ {
        rewrite ^/(.*)$ /hosting/index.php?rp=/store/sitelock/$1;
    }

    location ~ /store/website-builder/?(.*)$ {
        rewrite ^/(.*)$ /hosting/index.php?rp=/store/website-builder/$1;
    }

    location ~ /store/order/?(.*)$ {
        rewrite ^/(.*)$ /hosting/index.php?rp=/store/order/$1;
    }

    location ~ /hosting/cart/domain/renew/?(.*)$ {
        rewrite ^/(.*)$ /hosting/index.php?rp=/cart/domain/renew$1;
    }

    location ~ /account/paymentmethods/?(.*)$ {
        rewrite ^/(.*)$ /hosting/index.php?rp=/account/paymentmethods$1;
    }

    location ~ /password/reset/?(.*)$ {
        rewrite ^/(.*)$ /hosting/index.php?rp=/password/reset/$1;
    }

    location ~ /account/security/?(.*)$ {
        rewrite ^/(.*)$ /hosting/index.php?rp=/account/security$1;
    }

    location ~ /subscription?(.*)$ {
        rewrite ^/(.*)$ /hosting/index.php?rp=/subscription$1;
    }

#Social media authorization
    location ~ /auth/provider/google_signin/finalize/?(.*)$ {
        rewrite ^/(.*)$ /hosting/index.php?rp=auth/provider/google_signin/finalize$1;
    }

 #WHMCS ADMIN
location ~ /admin/(addons|apps|search|domains|help\/license|services|setup|utilities\/system\/php-compat)(.*) {
        rewrite ^/(.*)$ /hosting/admin/index.php?rp=/admin/$1$2 last; 
    }

    location ~ /admin/client/?(.*)/paymethods/?(.*)$ {
        rewrite ^/(.*)$ /hosting/admin/index.php?rp=/client/?(.*)/paymethods/$1;
    }

    location ~ /admin/setup/auth/?(.*)$ {
        rewrite ^/(.*)$ /hosting/admin/index.php?rp=/setup/auth/$1;
    }

    location ~ /admin/client/?(.*)/tickets/?(.*)$ {
        rewrite ^/(.*)$ /hosting/admin/index.php?rp=/client/?(.*)/tickets/$1;
    }

    location ~ /admin/client/?(.*)/invoice/?(.*)/capture/?(.*)$ {
        rewrite ^/(.*)$ /hosting/admin/index.php?rp=/client/?(.*)/invoice/?(.*)/capture/$1;
    }

    location ~ /admin/account/security/two-factor/?(.*)$ {
        rewrite ^/(.*)$ /hosting/admin/index.php?rp=/admin/account/security/two-factor/$1;
    }

    location ~ /admin/search/intellisearch?(.*)$ {
        rewrite ^/(.*)$ /hosting/admin/index.php?rp=/search/intellisearch/$1;
    }

# Security Advisory 2020-01-28
    location ^~ /vendor/ {
        deny all;
        return 403;
    }
# END WHMCS CONFIG

  location ~ \.php$ {
    include fastcgi_params;
    fastcgi_intercept_errors on;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    try_files $uri =404;
    fastcgi_read_timeout 3600;
    fastcgi_send_timeout 3600;
    fastcgi_param HTTPS $fastcgi_https;
    fastcgi_pass 127.0.0.1:{{php_fpm_port}};
    fastcgi_param PHP_VALUE "{{php_settings}}";
  }

  location ~* ^.+\.(css|js|jpg|jpeg|gif|png|ico|gz|svg|svgz|ttf|otf|woff|woff2|eot|mp4|ogg|ogv|webm|webp|zip|swf)$ {
    add_header Access-Control-Allow-Origin "*";
    expires max;
    access_log off;
  }

  if (-f $request_filename) {
    break;
  }
}