Contents

Some NGINX config files

During the years I wrote, copied and lost a lot of configuration files for the nginx webserver. I collected here some useful config, maybe now they are no more useful or incomplete. They were used ages ago or into an internal/soho network without troubles, maybe today something is changed on account of really bad software changes (eg. wordpress) and it’s no more safe/complete. To have a proper certificate move to Certbot.

Mediawiki

LEMP on Debian based distro, https enabled with SSL cert by Certbot.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
 server {
 	listen 80 ;

 	listen 443 ssl; # managed by Certbot
 	ssl_certificate /etc/letsencrypt/live/$PATH/fullchain.pem;
 	ssl_certificate_key /etc/letsencrypt/live/$PATH/privkey.pem;
     	include /etc/letsencrypt/options-ssl-nginx.conf;
     	ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

   	# config to enable HSTS(HTTP Strict Transport Security)
   	# to avoid ssl stripping <nowiki>https://en.wikipedia.org/wiki/SSL_stripping#SSL_stripping</nowiki>
   	# also <nowiki>https://hstspreload.org/</nowiki>
   	add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";

 	# Redirect non-https traffic to https
         # Change $SITE --> www.example.com or every vhost is here!
      	if ($scheme != "https") {
        		return 301 https://$SITE<nowiki/>$request_uri;
      	} # managed by Certbot

 	index index.php;
 	server_name $SITE $SITE2;

 	root /var/www/$PATH;
 	access_log /var/log/nginx/$SITE.access;
 	error_log /var/log/nginx/$SITE.error error;
 	server_tokens off;
 	error_page 401 403 404 /404.html;

 	location / {
     		try_files $uri @rewrite;
 	}

 	location @rewrite {
     		rewrite ^/(.*)$ /index.php;
 	}

     	# Keep images and CSS around in browser cache for as long as possible,
     	# to cut down on server load
 	location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
     		try_files $uri /index.php;
     		expires max;
     		log_not_found off;
 	}

 	location = /_.gif {
     		expires max;
     		empty_gif;
 	}

 	## INTERNAL DIRECTORY
 	location ^~ /bin/ { internal; }
 	location ^~ /docs/ { internal; }
 	location ^~ /extensions/ { internal; }
 	location ^~ /includes/ { internal; }
 	location ^~ /maintenance/ { internal; }
 	# Comment next line during installation
 	location ^~ /mw-config/ { internal; }
 	location ^~ /resources/lib/ { internal; }
 	location ^~ /resources/src/ { internal; }
 	location ^~ /resources/Resources.php { internal; }
 	location ^~ /resources/ResourcesOOUI.php { internal; }
 	location ^~ /serialized/ { internal; }
 	location ^~ /tests/ { internal; }
 	location ^~ /skins/ { internal; }
 	location ^~ /vendor/ { internal; }

 	## DENY ALL DIRECTORY
 	location ^~ /cache/ { deny all; }
 	location ~ \.htaccess { deny all;}

 	## PREVENT ./$/etc files
 	location ~ /\. { access_log off; log_not_found off; deny all; }		
     	location ~ /\. { access_log off; log_not_found off; deny all; }
     	location ~ ~$ { access_log off; log_not_found off; deny all; }
     	location = /robots.txt { access_log off; log_not_found off; }
     	location = /favicon.ico { access_log off; log_not_found off; }

     	# Force potentially-malicious files in the /images directory to be served
    	# with a text/plain mime type, to prevent them from being executed by
     	# the PHP handler
     	location ~* ^/images/.*.(html|htm|shtml|php)$ { types { } default_type text/plain; }

     	# Redirect all requests for unknown URLs out of images and back to the
     	# root index.php file
     	location ^~ /images/ { try_files $uri /index.php; }

     	# Deny direct access to uploads directory
     	location ~* /(?:uploads|nfsuploads|files)/.*\.php$ { deny all; }

     	location ~ \.php$ {
         	include snippets/fastcgi-php.conf;
         	fastcgi_pass unix:/run/php/php7.0-fpm.sock;
     	}

 }

Wordpress

LEMP on Debian based distro, https enabled with SSL cert by Certbot.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
 server {
 	### HELP SITE: https://gist.github.com/ethanpil/1bfd01a817a8198369efec5c4cde6628#file-wp-secure-conf-L39

 	listen 80 ;
 	listen 443 ssl; # managed by Certbot
 	ssl_certificate /etc/letsencrypt/live/fullchain.pem; # managed by Certbot
 	ssl_certificate_key /etc/letsencrypt/live/privkey.pem; # managed by Certbot
     	include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
     	ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

     	# Redirect non-https traffic to https
     	if ($scheme != "https") {
         	return 301 https://www.$SITE$request_uri;
     	} # managed by Certbot

 	index index.php;
 	server_name www.$SITE $SITE;

 	root /var/www/$SITE/wp;
 	access_log /var/log/nginx/$SITE.access;
 	error_log /var/log/nginx/$SITE.info.error error;
 	server_tokens off;

 	error_page 401 403 404 /404.html;

 	location / {
     		try_files $uri $uri/ /index.php$is_args$args;
 	}
  	location ~ \.php$ {
                 include snippets/fastcgi-php.conf;
                 fastcgi_pass unix:/run/php/php7.0-fpm.sock;
         }

     	# Keep images and CSS around in browser cache for as long as possible,
     	# to cut down on server load
 	location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
     		try_files $uri /index.php;
     		expires max;
     		log_not_found off;  
 	}

 	location = /_.gif {
      		expires max;
     		empty_gif;
 	}

 	# INTERNAL DIRECTORY
  	# Make sure files with the following extensions do not get loaded by nginx because nginx would display the source code, and these files can contain PASSWORDS!
 	location ~* \.(engine|inc|info|install|make|module|profile|test|po|sh|.*sql|theme|tpl(\.php)?|xtmpl)\$|^(\..*|Entries.*|Repository|Root|Tag|Template)\$|\.php_
 	{
 		return 444;
 	}
 	location ~* \.(pl|cgi|py|sh|lua)$ { return 444;}

 	# allow AJAX requests in themes and plugins
 	location ~ ^/wp-admin/admin-ajax.php$ { allow all; }

         ## PREVENT ./$/etc files
         location ~ /\. { access_log off; log_not_found off; deny all; }
         location ~ /\. { access_log off; log_not_found off; deny all; }
         location ~ ~$ { access_log off; log_not_found off; deny all; }
         location = /robots.txt { access_log off; log_not_found off; }
         location = /favicon.ico { access_log off; log_not_found off; }

          # Force potentially-malicious files in the /images directory to be served
         # with a text/plain mime type, to prevent them from being executed by
         # the PHP handler
          location ~* ^/images/.*.(html|htm|shtml|php)$ { types { } default_type text/plain; }

        # Redirect all requests for unknown URLs out of images and back to the
         # root index.php file
         location ^~ /images/ { try_files $uri /index.php; }

         # Deny direct access to uploads directory
         location ~* /(?:uploads|nfsuploads|files)/.*\.php$ { deny all; }

         ## DENY ALL DIRECTORY
         location ^~ /cache/ { deny all; }
         location ~ \.htaccess { deny all;}

         #Deny access to wp-content folders for suspicious files
         location ~* ^/(wp-content)/(.*?)\.(zip|gz|tar|bzip2|7z)\$ { deny all; }
 	location ~ ^/wp-content/uploads/sucuri { deny all; }
 	location ~ ^/wp-content/updraft { deny all; }
         #Block nginx-help log from public viewing
         location ~* /wp-content/uploads/nginx-helper/ { deny all; }
         # Deny access to any files with a .php extension in the uploads directory
         # Works in sub-directory installs and also in multisite network
         location ~* /(?:uploads|files)/.*\.php\$ { deny all; }
         # Deny access to uploads that aren't images, videos, music, etc.
         location ~* ^/wp-content/uploads/.*.(html|htm|shtml|php|js|swf|css)$ {
               deny all;
         }
         location ~* /(\.|wp-config\.php|wp-config\.txt|changelog\.txt|readme\.txt|readme\.html|license\.txt) { deny all; }

 	## IMAGE HOTLINKS
 	location ~ .(gif|png|jpe?g)$ {
      		valid_referers none blocked $SITE *.$SITE;
      		if ($invalid_referer) {
         		return   403;
  	   	}
 	}
 }

Roundcube

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
 server {
 	listen 80 ;
 	listen [::]:80 ;

         listen 443 ssl; # managed by Certbot
         ssl_certificate /etc/letsencrypt/live/mail.mysite.org/fullchain.pem; # managed by Certbot
         ssl_certificate_key /etc/letsencrypt/live/mail.mysite.org/privkey.pem; # managed by Certbot
         include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
         ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

         if ($scheme != "https") {
                 return 301 https://$host$request_uri;
         }

 	index index.php index.html;
 	server_name mail.mysite.org;
 	root /var/www/roundcube;
 	access_log /var/log/nginx/roundcube.access;
 	error_log /var/log/nginx/roundcube.error error;
 	server_tokens off;
 	error_page 401 403 404 /404.html;

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

     	location ~ \.php$ {
         	include snippets/fastcgi-php.conf;
         	fastcgi_pass unix:/run/php/php7.0-fpm.sock;
     	}


 	error_page 404 /404.html;
   	error_page 500 502 503 504 /50x.html;

   	location ~ ^/(README|INSTALL|LICENSE|CHANGELOG|UPGRADING)$ {
     		deny all;
   	}
   	location ~ ^/(bin|SQL|config|temp|logs)/ {
     		deny all;
   	}

         location ~ ^/favicon.ico$ {
                 root /var/www/roundcube/skins/default/images;
                 log_not_found off;
                 access_log off;
                 expires max;
        	}

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

 	location ~ /\. {
                 deny all;
                 access_log off;
                 log_not_found off;
         }
 }

Awstats

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 server {
     	listen 80;
 	server_name awstat.mysite.com;
        root /var/www/awstats;

 	error_log /var/log/nginx/awstat.mysite.com.error;
 	access_log /var/log/nginx/awstat.mysite.com.access;
 	log_not_found off;
 	server_tokens off;
 	error_page 401 403 404 /404.html;

     	location ^~ /icon {
         	alias /usr/local/awstats/wwwroot/icon/;
     	}
 	location ^~ /css/ {
 		alias /usr/local/awstats/wwwroot/css/;
 	}

        # beautifying the url
     	location ~ ^/([a-z0-9-_\.]+)$ {
         	return 301 $scheme://awstats.mysite.org/cgi-bin/awstats.pl?config=$1;
     	}

 	location ~ ^/cgi-bin/(awredir|awstats)\.pl {
 		gzip off;
 		fastcgi_pass unix:/run/php/php7.0-fpm.sock;
 		fastcgi_param SCRIPT_FILENAME  /etc/nginx/cgi-bin.php;
 		fastcgi_param X_SCRIPT_FILENAME /usr/local/awstats/wwwroot$fastcgi_script_name;
 		fastcgi_param X_SCRIPT_NAME $fastcgi_script_name;
 		include fastcgi_params;
 	}

 }

Piwik

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
 server {
     	listen 80;

         listen 443 ssl; # managed by Certbot
         ssl_certificate /etc/letsencrypt/live/piwik.example.org/fullchain.pem; # managed by Certbot
         ssl_certificate_key /etc/letsencrypt/live/piwik.example.org/privkey.pem; # managed by Certbot
         include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
         ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot


         # Redirect non-https traffic to https
         if ($scheme != "https") {
             return 301 https://$host$request_uri;
         } # managed by Certbot

 	server_name piwik.example.org;
 	root /var/www/piwik;

 	error_log /var/log/nginx/piwik.example.org.error;
 	access_log /var/log/nginx/piwik.example.org.access;
 	log_not_found off;
 	server_tokens off;

 	index index.php;

 	# Disallow access to directories
 	location ~ ^/(config|core|lang|misc|tmp)/ {
         	deny all;
 	}

 	## Do not serve HTML files from the /tmp folder.
         location ~* ^/tmp/.*\.html?$ {
             	return 404;
         }

         ## Redirect to the root if attempting to access a txt file.
         location ~* (?:DESIGN|(?:gpl|README|LICENSE)[^.]*|LEGALNOTICE)(?:\.txt)*$ {
             	return 302;
         }

         ## Disallow access to several helper files.
         location ~* \.(?:bat|git|md|ini|sh|svn[^.]*|txt|tpl|xml)$ {
             	return 404;
         }

       	location ~ \.php$ {
             	include snippets/fastcgi-php.conf;
             	fastcgi_pass unix:/run/php/php7.0-fpm.sock;
         }

     	## Support for favicon. Return a 1x1 transparent GIF it it doesn't
     	## exist.  doesn't exist.
     	location = /favicon.ico {
         	try_files /favicon.ico @empty;
     	}

     	location @empty {
         	empty_gif;
     	}

 	## Enable clickjacking protection in modern browsers. Available in
     	## IE8 also. See
     	## https://developer.mozilla.org/en/The_X-FRAME-OPTIONS_response_header
     	add_header X-Frame-Options SAMEORIGIN;
 }

= 301 Redirect =

 server {
 	listen 80 ;
 	server_name www.example.com example.com;
 	return 301 https://www.mysite.com;
 }

GeoIP configuration

Download GeoIP dat at https://dev.maxmind.com/geoip/legacy/geolite/ and decompress it :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 mkdir /etc/nginx/geoip
 cd /etc/nginx/geoip
 gunzip $file
 vi /etc/nginx/nginx.conf

 http{
 ...
  	##
  	# GEOIP
 	##
 	geoip_country  /etc/nginx/geoip/GeoIP.dat;
  	geoip_city     /etc/nginx/geoip/GeoLiteCity.dat;
 ...
 }

 vi /etc/nginx/fastcgi.conf

 fastcgi_param GEOIP_ADDR $remote_addr;
 fastcgi_param GEOIP_COUNTRY_CODE $geoip_country_code;
 fastcgi_param GEOIP_COUNTRY_NAME $geoip_country_name;
 fastcgi_param GEOIP_REGION $geoip_region;
 fastcgi_param GEOIP_REGION_NAME $geoip_region_name;
 fastcgi_param GEOIP_CITY $geoip_city;
 fastcgi_param GEOIP_AREA_CODE $geoip_area_code;
 fastcgi_param GEOIP_LATITUDE $geoip_latitude;
 fastcgi_param GEOIP_LONGITUDE $geoip_longitude;
 fastcgi_param GEOIP_POSTAL_CODE $geoip_postal_code;