Skip to content

Instantly share code, notes, and snippets.

@apmarshall
Created November 25, 2015 16:35
Show Gist options
  • Save apmarshall/a4c14747d1667a24e5f0 to your computer and use it in GitHub Desktop.
Save apmarshall/a4c14747d1667a24e5f0 to your computer and use it in GitHub Desktop.
Boilerplate Config file for nginx, originally written for a Joomla instal. @nikosdion/master-htaccess
server {
######################################################################
## The Master .htaccess - NginX adaptation
##
## Version 3.3
##
## This file is designed to be the template NginX server configuration file
## for your Joomla! sites. You should go through all of its sections and
## modify it to match your site. Most notably, all instances of example.com
## and example\.com should be replaced with your real domain name.
##
## Some sections are too picky and may cause problems with legitimate requests.
## You are ultimately responsible for disabling them or writing exception rules
## for your requests. Most notably, the advanced server protection section will
## cause issues with several minifiers, eXtplorer, VirtueMart and other exten-
## sions which use non-standard scripts as their entry points. You must add
## exceptions for them manually.
##
## Some sections - depending on your server configuration - may cause your site
## to throw 500 Internal Server Error. The only way to figure out which one is
## causing it is trial and error.
##
## This is an adaptation of my Master .htaccess, a similar file which
## I have designed for Apache-based servers. This adaptation would not
## be possible without all the wonderful people who helped me write and
## test the original Master .htaccess, the Joomla! project which now
## recommends it in its official documentation wiki and the thousands
## of Admin Tools Professional subscribers who provided invaluable
## feedback on the Master .htaccess' performance across different servers.
##
## Have fun, stay safe.
##
## Nicholas K. Dionysopoulos
## Lead Developer, AkeebaBackup.com
##
######################################################################
######################################################################
## Basic server setup. Change to match YOUR system!
######################################################################
# -- Basic configuration
# ---- Port to listen to. For SSL sites change this to 443.
listen 80;
# ---- Domain name(s) of this site, separated by commas
server_name www.example.com example.com www.example.org example.org;
# ---- Site root path
root /home/web/domains/www.example.com/public_html;
# ---- Path to the access log
access_log /home/web/domains/www.example.com/logs/access.log;
# ---- Path to the error log
error_log /home/web/domains/www.example.com/logs/error.log;
# ---- Custom error pages. Each error page is four lines. The first one
# defines which page will be shown for each error code. The next
# three lines make sure that the error page cannot be accessed
# directly over the web.
error_page 404 /errors/404.html;
location /errors/404.html {
internal;
}
error_page 500 /errors/500.html;
location /errors/500.html {
internal;
}
error_page 403 /errors/403.html;
location /errors/403.html {
internal;
}
######################################################################
## SSL Configuration
##
## Only use this block if you are setting up the SSL (HTTPS) server
## definition of your site.
######################################################################
ssl on;
ssl_certificate /etc/ssl/localcerts/webserver.pem;
ssl_certificate_key /etc/ssl/localcerts/webserver.key;
ssl_session_timeout 5m;
ssl_protocols SSLv3 TLSv1;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv3:+EXP;
ssl_prefer_server_ciphers on;
######################################################################
## The Kitchen Sink - An array of useful and performance-tuning options
######################################################################
# -- Timeout handling, see http://wiki.nginx.org/HttpCoreModule
client_header_timeout 10;
client_body_timeout 10;
send_timeout 30;
keepalive_timeout 40 20;
# -- Socket settings, see http://wiki.nginx.org/HttpCoreModule
connection_pool_size 8192;
client_header_buffer_size 4k;
large_client_header_buffers 8 8k;
request_pool_size 8k;
# -- Performance, see http://wiki.nginx.org/HttpCoreModule
sendfile on;
sendfile_max_chunk 1m;
postpone_output 0;
tcp_nopush on;
tcp_nodelay off;
# -- Output buffering, see http://wiki.nginx.org/HttpCoreModule
output_buffers 8 32k;
# -- Character encoding, see http://wiki.nginx.org/HttpCharsetModule
charset utf-8;
source_charset utf-8;
# -- Security options, see http://wiki.nginx.org/HttpCoreModule
server_name_in_redirect off;
server_tokens off;
ignore_invalid_headers on;
# You may have to comment out the next line on multi-site installations
disable_symlinks if_not_owner;
######################################################################
## Redirect non-www to www
##
## If you enable this, disable the "Redirect www to non-www" below!
######################################################################
if ($host = 'example.com' ) {
rewrite ^/(.*)$ http://www.example.com/$1 permanent;
}
######################################################################
## Redirect www to non-www
##
## If you enable this, disable the "Redirect non-www to www" above!
######################################################################
if ($host = 'www.example.com' ) {
rewrite ^/(.*)$ http://example.com/$1 permanent;
}
######################################################################
## Redirect example.org to example.com
##
## Your server_name must include both the old and new domain names!
######################################################################
if ($host ~ "(www\.)?example.org$" ) {
rewrite ^/(.*)$ http://www.example.com/$1 permanent;
}
######################################################################
## CloudFlare support - see http://wiki.nginx.org/NginxHttpRealIpModule
## Comment out if you are not using the CloudFlare CDN
######################################################################
set_real_ip_from 204.93.240.0/24;
set_real_ip_from 204.93.177.0/24;
set_real_ip_from 199.27.128.0/21;
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 190.93.240.0/20;
real_ip_header CF-Connecting-IP;
######################################################################
## Directory indices
## Forces index.php to be read before the index.htm(l) files
######################################################################
index index.php index.html index.htm;
######################################################################
## Status page - DISABLE THIS ON LIVE SITES!
######################################################################
location /nginx_status {
stub_status on;
access_log off;
# Remember to change this to your PC's IP address
allow 192.168.0.1;
}
######################################################################
## Google Apps redirection
## This also shows how to redirect a directory to an external server
######################################################################
location ~* /mail {
rewrite ^ http://mail.google.com/a/example.com permanent;
}
######################################################################
## Block some common exploits
######################################################################
set $common_exploit 0;
if ($query_string ~ "proc/self/environ") {
set $common_exploit 1;
}
if ($query_string ~ "mosConfig_[a-zA-Z_]{1,21}(=|\%3D)") {
set $common_exploit 1;
}
if ($query_string ~ "base64_(en|de)code\(.*\)") {
set $common_exploit 1;
}
if ($query_string ~ "(<|%3C).*script.*(>|%3E)") {
set $common_exploit 1;
}
if ($query_string ~ "GLOBALS(=|\[|\%[0-9A-Z]{0,2})") {
set $common_exploit 1;
}
if ($query_string ~ "_REQUEST(=|\[|\%[0-9A-Z]{0,2})") {
set $common_exploit 1;
}
if ($common_exploit = 1) {
return 403;
}
######################################################################
## File injection protection
######################################################################
set $file_injection 0;
if ($query_string ~ "[a-zA-Z0-9_]=http://") {
set $file_injection 1;
}
if ($query_string ~ "[a-zA-Z0-9_]=(\.\.//?)+") {
set $file_injection 1;
}
if ($query_string ~ "[a-zA-Z0-9_]=/([a-z0-9_.]//?)+") {
set $file_injection 1;
}
if ($file_injection = 1) {
return 403;
}
######################################################################
## SQL injection first line of defence (NOT comprehensive!)
######################################################################
set $sql_injection 0;
if ($query_string ~ "concat.*\(") {
set $sql_injection 1;
}
if ($query_string ~ "union.*select.*\(") {
set $sql_injection 1;
}
if ($query_string ~ "union.*all.*select.*") {
set $sql_injection 1;
}
if ($sql_injection = 1) {
return 403;
}
######################################################################
## Basic anti-spam
######################################################################
set $looks_like_spam 0;
if ($query_string ~ "\b(ambien|blue\spill|cialis|cocaine|ejaculation|erectile)\b") {
set $looks_like_spam 1;
}
if ($query_string ~ "\b(erections|hoodia|huronriveracres|impotence|levitra|libido)\b") {
set $looks_like_spam 1;
}
if ($query_string ~ "\b(lipitor|phentermin|pro[sz]ac|sandyauer|tramadol|troyhamby)\b") {
set $looks_like_spam 1;
}
if ($query_string ~ "\b(ultram|unicauca|valium|viagra|vicodin|xanax|ypxaieo)\b") {
set $looks_like_spam 1;
}
if ($looks_like_spam = 1) {
return 403;
}
######################################################################
## Advanced server protection rules exceptions
##
## You will DEFINITELY need to add exceptions for a lot of extensions
## to work. Yeah, I have to write an illustrated guide at some point.
## However, if you can use Firebug or Google Chrome Web Developer
## window then you can find out the exceptions all by yourself. Use the
## following as a guide.
######################################################################
# Allow direct access to a specific PHP file
location = /tmp/test.php {
fastcgi_pass $fastcgi_pass;
break;
}
# Allow direct access to a specific static (non-PHP) file
location = /administrator/test.png {
break;
}
######################################################################
## Server protection
##
## Nothing on my site runs unless I say so!
######################################################################
# Allow media files in select back-end directories
location ~* ^/administrator/(components|modules|templates|images)/.*.(jp(e?g|2)?|png|gif|bmp|css|js|swf|html?|ico|mpe(eg?[34])|avi|wav|og[gv]|xlsx?|docx?|pptx?|zip|rar|pdf|xps|txt|7z|svg|od[tsp]|flv|mov)$ {
break;
}
# Allow media files in select front-end directories
location ~* ^/(components|modules|templates|images|plugins|media|includes/js)/.*.(jp(e?g|2)?|png|gif|bmp|css|js|swf|html?|ico|mpe(eg?[34])|avi|wav|og[gv]|xlsx?|docx?|pptx?|zip|rar|pdf|xps|txt|7z|svg|od[tsp]|flv|mov)$ {
break;
}
# Allow access to the front-end index.php file
location = / {
try_files $uri $uri/ /index.php?q=$uri&$args;
}
location = /index.php {
fastcgi_pass $fastcgi_pass;
break;
}
# Allow access to the back-end index.php file
location = /administrator {
rewrite ^ /administrator/index.php last;
}
location = /administrator/ {
rewrite ^ /administrator/index.php last;
}
location = /administrator/index.php {
fastcgi_pass $fastcgi_pass;
break;
}
# Disable access to everything else.
location ~* /.*$ {
# If it is a file, directory or symlink and I haven't deliberetaly
# enabled access to it, forbid any access to it!
if (-e $request_filename) {
return 403;
}
# In any other case, just treat as a SEF URL
try_files $uri $uri/ /index.php?q=$uri&$args;
}
######################################################################
## PHP Setup
######################################################################
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
set $fastcgi_pass "unix:/var/run/php5-fpm-web.sock";
location ~ index.php$ {
fastcgi_pass $fastcgi_pass;
}
######################################################################
## Expiration control
##
## Optimises the expiration time
######################################################################
# CSS and JavaScript : 1 week
location ~* \.(css|js)$ {
expires 1w;
}
# Image files : 1 month
location ~* \.(bmp|gif|jpg|jpeg|jp2|png|svg|tif|tiff|ico|wbmp|wbxml|smil)$ {
expires 1m;
}
# Document files : 1 month
location ~* \.(pdf|txt|xml)$ {
expires 1m;
}
# Audio files : 1 month
location ~* \.(mid|midi|mp3|m4a|m4r|aif|aiff|ra|wav|voc|ogg)$ {
expires 1m;
}
# Video files : 1 month
location ~* \.(swf|vrml|avi|mkv|mpg|mpeg|mp4|m4v|mov|asf)$ {
expires 1m;
}
######################################################################
## User agent blocking
##
## Disables access to your site by user agent. Useful to block some
## bandwidth hoggers.
######################################################################
set $bad_ua 0;
# This also disables Akeeba Remote Control 2.5 and earlier
if ($http_user_agent ~ "Indy Library") {
set $bad_ua 1;
}
# Disabling Wget will also block the most common method to run CRON jobs
if ($http_user_agent ~ "Wget") {
set $bad_ua 1;
}
# Common bandwidth hoggers and hacking tools. Each rule is three lines, beginning with "if"
if ($http_user_agent ~ "libwww-perl") {
set $bad_ua 1;
}
if ($http_user_agent ~ "Download Demon") {
set $bad_ua 1;
}
if ($http_user_agent ~ "GetRight") {
set $bad_ua 1;
}
if ($http_user_agent ~ "GetWeb!") {
set $bad_ua 1;
}
if ($http_user_agent ~ "Go!Zilla") {
set $bad_ua 1;
}
if ($http_user_agent ~ "Go-Ahead-Got-It") {
set $bad_ua 1;
}
if ($http_user_agent ~ "GrabNet") {
set $bad_ua 1;
}
if ($http_user_agent ~ "TurnitinBot") {
set $bad_ua 1;
}
# If you enable any of the above don't remove this. It's what blocks
# the bad user agents!
if ($bad_ua = 1) {
return 403;
}
######################################################################
## Automatic compression of static resources
## Compress text, html, javascript, css, xml and other static resources
## May kill access to your site for old versions of Internet Explorer
######################################################################
gzip on;
gzip_vary on;
gzip_comp_level 4;
gzip_min_length 1100;
gzip_types text/plain text/html text/xml text/css application/xml application/xhtml+xml application/xml+rss application/rss+xml application/x-javascript application/javascript text/javascript;
gzip_buffers 16 8k;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment