Skip to content

Instantly share code, notes, and snippets.

@rahilwazir
Last active April 15, 2017 11:29
Show Gist options
  • Save rahilwazir/d552d685d3379df094614dae447be951 to your computer and use it in GitHub Desktop.
Save rahilwazir/d552d685d3379df094614dae447be951 to your computer and use it in GitHub Desktop.
Linux Nginx: CMS configurations

WordPress

Create a file /etc/nginx/global/wordpress.conf and paste the following content:

# WordPress single site rules.
# Designed to be included in any server {} block.

# This order might seem weird - this is attempted to match last if rules below fail.
# http://wiki.nginx.org/HttpCoreModule
location / {
	try_files $uri $uri/ /index.php?$args;
}

# Add trailing slash to */wp-admin requests.
rewrite /wp-admin$ $scheme://$host$uri/ permanent;

# Directives to send expires headers and turn off 404 error logging.
location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
       access_log off; log_not_found off; expires max;
}

# Uncomment one of the lines below for the appropriate caching plugin (if used).
#include global/wordpress-wp-super-cache.conf;
#include global/wordpress-w3-total-cache.conf;

# Pass all .php files onto a php-fpm/php-fcgi server.
location ~ [^/]\.php(/|$) {
	fastcgi_split_path_info ^(.+?\.php)(/.*)$;
	if (!-f $document_root$fastcgi_script_name) {
		return 404;
	}
	# This is a robust solution for path info security issue and works with "cgi.fix_pathinfo = 1" in /etc/php.ini (default)

	include fastcgi_params;
	fastcgi_index index.php;
	fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
	fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
}

Any configuration file in /etc/nginx/conf.d/example.conf, can include the global config for reuse, e.g:

server {
	include global/ssl_http2.conf; #To use port 443 (https://)
	#listen 80; #To use port 80 (http://)

	server_name example.com; #111.111.111.111 FOR_DNS_ACCESS
	root /home/user/html/example;

	index index.php;

    # Error/Access logs per-site basis
	access_log /var/log/nginx/example.log;
	error_log /var/log/nginx/example.error.log;

	# Additional rules go here.
    
    # To serve wildcard subdirectories wordpress installation
    #location ^~ /(?<wd>.*?) {
	#    try_files $uri $uri/ /$wd/index.php?$args;
    #}

    # Include global configuration file for all WP installation
    include global/wordpress.conf;
}

Drupal

Same as above, create a file /etc/nginx/global/drupal.conf and paste the following content:

location = /favicon.ico {
    log_not_found off;
    access_log off;
}

location = /robots.txt {
    allow all;
    log_not_found off;
    access_log off;
}

# Very rarely should these ever be accessed outside of your lan
location ~* \.(txt|log)$ {
    allow 192.168.0.0/16;
    deny all;
}

location ~ \..*/.*\.php$ {
    return 403;
}

location ~ ^/sites/.*/private/ {
    return 403;
}

# Allow "Well-Known URIs" as per RFC 5785
location ~* ^/.well-known/ {
    allow all;
}

# Block access to "hidden" files and directories whose names begin with a
# period. This includes directories used by version control systems such
# as Subversion or Git to store control files.
location ~ (^|/)\. {
    return 403;
}

location / {
    # try_files $uri @rewrite; # For Drupal <= 6
    try_files $uri /index.php?$query_string; # For Drupal >= 7
}

location @rewrite {
    rewrite ^/(.*)$ /index.php?q=$1;
}

# Don't allow direct access to PHP files in the vendor directory.
location ~ /vendor/.*\.php$ {
    deny all;
    return 404;
}

# In Drupal 8, we must also match new paths where the '.php' appears in
# the middle, such as update.php/selection. The rule we use is strict,
# and only allows this pattern with the update.php front controller.
# This allows legacy path aliases in the form of
# blog/index.php/legacy-path to continue to route to Drupal nodes. If
# you do not have any paths like that, then you might prefer to use a
# laxer rule, such as:
#   location ~ \.php(/|$) {
# The laxer rule will continue to work if Drupal uses this new URL
# pattern with front controllers other than update.php in a future
# release.
location ~ '\.php$|^/update.php' {
    fastcgi_split_path_info ^(.+?\.php)(|/.*)$;
    # Security note: If you're running a version of PHP older than the
    # latest 5.3, you should have "cgi.fix_pathinfo = 0;" in php.ini.
    # See http://serverfault.com/q/627903/94922 for details.
    include fastcgi_params;
    # Block httpoxy attacks. See https://httpoxy.org/.
    fastcgi_param HTTP_PROXY "";
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_path_info;
    fastcgi_intercept_errors on;
    # PHP 5 socket location.
    #fastcgi_pass unix:/var/run/php5-fpm.sock;
    # PHP 7 socket location.
    fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
}

# Fighting with Styles? This little gem is amazing.
# location ~ ^/sites/.*/files/imagecache/ { # For Drupal <= 6
location ~ ^/sites/.*/files/styles/ { # For Drupal >= 7
    try_files $uri @rewrite;
}

# Handle private files through Drupal.
location ~ ^/system/files/ { # For Drupal >= 7
    try_files $uri /index.php?$query_string;
}

location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
    expires max;
    log_not_found off;
}

Include above per site configuration like you did for WP.

Joomla

Create a file /etc/nginx/global/joomla.conf and paste the following content:

# Support Clean (aka Search Engine Friendly) URLs
server_name_in_redirect off;

location / {
    try_files $uri $uri/ /index.php?$args;
}

# deny running scripts inside writable directories
location ~* /(images|cache|media|logs|tmp)/.*\.(php|pl|py|jsp|asp|sh|cgi)$ {
    return 403;
    error_page 403 /403_error.html;
}

location ~ \.php$ {
	include fastcgi_params;
	fastcgi_index index.php;
	fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
	fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
}

# caching of files 
location ~* \.(ico|pdf|flv)$ {
    expires 1y;
}

location ~* \.(js|css|png|jpg|jpeg|gif|swf|xml|txt)$ {
    expires 14d;
}

Include above per site configuration like you did for WP.

HTTP2 (SSL)

Create a file /etc/nginx/global/ssl_http2.conf and paste the following content:

listen *:443 ssl http2;
listen [::]:443 ssl http2;

ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;

Extra

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment