Server Default Settings

In the example server defined earlier there is a include statement to load various settings, which every website should use for enhanced performance and security.

1
2
 # Common Server Settings
 include     server-conf.d/*.conf;

Note

Some web applications like ownCloud might provide their own settings which may duplicate or even conflict with some of the settings defined here. In this case only some of the configuration files might be included individually.

Since the order in which these configurations are applied does matter, the files are numbered.

The configuration options are explained in the files comments

Server Security

In the file /etc/nginx/server-conf.d/10_server-security.conf we set various security related settings which every website should include..

 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
#
# Default Server Security and Access Restrictions
#

#
# Limit allowed HTTP methods
#
# Available methods:
#  GET, HEAD, POST, PUT, DELETE, MKCOL, COPY, MOVE, OPTIONS, PROPFIND,
#  PROPPATCH, LOCK, UNLOCK, or PATCH.
#
# Note that Nginx never allows the TRACE method (hard-coded)
#
# Only allow GET, HEAD and POST requests.
#location ~ / {
#    limit_except GET POST OPTIONS {
#        deny all;
#    }
#}

# Prevent clients from accessing (hidden) files starting with a dot
# (i.e .htaccess, .htpasswd). Access to `/.well-known/` is allowed.
location ~* /\.(?!well-known\/) {
  deny all;
}

#
# Prevent clients from accessing backup/config/source files
location ~* (?:\.(?:bak|config|sql|fla|psd|ini|log|sh|inc|swp|dist)|~)$ {
    deny all;
}

Client Security

In the file /etc/nginx/server-conf.d/20_client-security.conf we set various security related settings which every website should include..

 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
#
# Default Client Security Settings
# For protection against click-jacking, cross-site-request-forgery (CSRF) and
# cross-site-scripting (XSS) protection
#

# Tell clients not to load scripts and stylesheets unless the server indicates
# the correct MIME type, as files incorrectly detected as scripts or stylesheets
# may lead to XSS attacks.
add_header  X-Content-Type-Options 'nosniff' always;

# Tell clients not to render pages inside frames or iframes to avoid click-jacking.
add_header  X-Frame-Options 'DENY' always;

# Tell client to only send the 'Referer' header for resources on this same site.
#add_header  Referrer-Policy 'same-origin' always;

# Tell clients to never ever send the 'Referer' header.
add_header  Referrer-Policy 'no-referrer' always;

# Enable the Cross-site scripting (XSS) filter built into recent browsers.
# https://www.owasp.org/index.php/List_of_useful_HTTP_headers
add_header  X-XSS-Protection '1; mode=block' always;

# Force the latest IE version
add_header  X-UA-Compatible 'IE=Edge' always;

Error Pages

The file /etc/nginx/server-conf.d/50_error-pages.conf defines a fallback error page for every HTTP client error (error-4xx.html) and HTTP server error (http-5xx.html). Individual error pages for specific errors will be delivered to clients if they exist (i.e. error-404.html).

  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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#
# Nginx Error Pages
#

#
# HTTP Client Errors
#

# 400 Bad Request
# 401 Unauthorized (RFC 7235)
# 402 Payment Required
# 403 Forbidden
# 404 Not Found
# 406 Not Acceptable
# 407 Proxy Authentication Required (RFC 7235)
# 408 Request Time-out
# 409 Conflict
# 410 Gone
# 411 Length Required
# 412 Precondition Failed (RFC 7232)
# 413 Payload Too Large (RFC 7231)
# 414 URI Too Long (RFC 7231)
# 415 Unsupported Media Type
# 416 Range Not Satisfiable (RFC 7233)
# 417 Expectation Failed
# 418 I'm a teapot (RFC 2324)
# 421 Misdirected Request (RFC 7540)
# 422 Unprocessable Entity (WebDAV; RFC 4918)
# 423 Locked (WebDAV; RFC 4918)
# 424 Failed Dependency (WebDAV; RFC 4918)
# 426 Upgrade Required
# 428 Precondition Required (RFC 6585)
# 431 Request Header Fields Too Large (RFC 6585)
# 444 No Response (Nginx)
# 449 Retried after appropriate action (MS Exchange)
# 450 Blocked by Windows Parental Controls (Microsoft)
# 451 Unavailable For Legal Reasons (Fahrenheit 451)
# 495 SSL Certificate Error (Nginx)
# 496 SSL Certificate Required (Nginx)
# 497 HTTP Request Sent to HTTPS Port (Nginx)
# 499 Client Closed Request (Nginx, unsupported)

error_page
    400 401 402 403 404 406 407 408 409 410
    411 412 413 414 415 416 417 418 421 422
    423 424 426 428 431 444 449 450 451 495
    496 497
    @http_error_4xx;
location @http_error_4xx {
    root /usr/local/share/nginx/http/error;
    allow all;
    ssi on;
    try_files $uri /error-$status.html /error-4xx.html =400;
}

#
# Client Errors who need special handling
# Send additional headers etc.

# 405 Method Not Allowed
error_page 405 @http_error_405;
location @http_error_405 {
    root /usr/local/share/nginx/http/error;
    allow all;
    ssi on;
    add_header Access-Control-Allow-Methods "GET, HEAD, POST" always;
    try_files $uri /error-405.html =405;
}

# 429 Too Many Requests (RFC 6585)
error_page 429 @http_error_429;
location @http_error_429 {
    root /usr/local/share/nginx/http/error;
    allow all;
    ssi on;
    set $ip_req_rate_limit 100;
    set $ip_conn_limit 512;
    add_header X-RateLimit-Limit "100r/s" always;
    add_header Retry-After: 300 always;
    try_files $uri /error-429.html =429;
}


#
# HTTP Server Errors
#

# 500 Internal Server Error
# 501 Not Implemented
# 502 Bad Gateway
# 504 Gateway Time-out
# 505 HTTP Version Not Supported
# 506 Variant Also Negotiates (RFC 2295)
# 507 Insufficient Storage (WebDAV; RFC 4918)
# 508 Loop Detected (WebDAV; RFC 5842)
# 509 Bandwidth Limit Exceeded (Apache Web Server/cPanel)
# 510 Not Extended (RFC 2774)
# 511 Network Authentication Required (RFC 6585)
# 520 Unknown Error (Cloudflare)
# 521 Web Server Is Down (Cloudflare)
# 522 Connection Timed Out (Cloudflare)
# 523 Origin Is Unreachable (Cloudflare)
# 524 A Timeout Occurred (Cloudflare)
# 525 SSL Handshake Failed (Cloudflare)
# 526 Invalid SSL Certificate (Cloudflare)
# 527 Railgun Error (Cloudflare)
# 599 Network connect timeout error
error_page
    500 501 502 504 505 506 507 508 509 510
    511 520 521 522 523 524 525 526 527 599
    @http_error_5xx;
location @http_error_5xx {
    root /usr/local/share/nginx/http/error;
    allow all;
    ssi on;
    try_files $uri /error-$status.html /error-5xx.html =500;
}

#
# Server Errors who need special handling
# Send additional headers etc.

# 503 Service Unavailable
error_page 503 @http_error_503;
location @http_error_503 {
    root /usr/local/share/nginx/http/error;
    allow all;
    ssi on;
    add_header Retry-After: 1800 always;
    try_files $uri /error-503.html =503;
}

#
# Location for assets included in error page (css, js, fonts, etc.)
location ^~ /http_assets {
    alias /usr/local/share/nginx/http/assets;
    allow all;
}

No Transform

The file /etc/nginx/server-conf.d/70_no_transform.conf.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#
# Note:
#   If you are using `ngx_pagespeed`, the the `Cache-Control: no-transform`
#   response header will prevent `PageSpeed` from rewriting `HTML` files, and,
#   if `pagespeedDisableRewriteOnNoTransform off` is not used, also from
#   rewriting other resources.
#
# https://developers.google.com/speed/pagespeed/module/configuration#notransform

# Prevent mobile network providers from modifying your site
add_header  Cache-Control 'no-transform' always;

Browser Cache

The cache of our visitors web browsers is the best place to improve the website performance for our visitors and reduce the load on our servers.

We use file /etc/nginx/server-defaults/80_client-cache-control.conf to control what and how long is cached by our visitors browser cache.

 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
#
# Client Cache Control
#

#
# Expire rules for static content
# Do not use a default expire rule with nginx unless a site is completely static

# cache.appcache, your document html and data
location ~* \.(?:manifest|appcache|html?|xml|json)$ {
    expires -1;
}

# Feed
location ~* \.(?:rss|atom)$ {
    expires 1h;
    add_header Cache-Control "public";
}

# Compressed Media: images, icons, video, audio, HTC
location ~* \.(?:jpg|jpeg|gif|png|gz|svgz|mp3|mp4|ogg|ogv|webm|htc)$ {
    gzip off;
    expires 1M;
    add_header Cache-Control "public";
}

# Uncompressed Media: images, icons, video, audio, HTC
location ~* \.(?:ico|cur|svg|webm|htc|mid|midi|wav|bmp)$ {
    expires 1M;
    add_header Cache-Control "public";
}

# CSS and Javascript
location ~* \.(?:css|js)$ {
    expires 1y;
    add_header Cache-Control "public";
}

# WebFonts
# If you are NOT using cross-domain-fonts, uncomment the following directive
location ~* \.(?:ttf|ttc|otf|eot|woff|woff2)$ {
    expires 1y;
    add_header Cache-Control "public";
    add_header  Access-Control-Allow-Origin "*" ;
}

# Compressed Archives
location ~* \.(?:zip|tgz|gz|rar|bz2|deb|rar)$ {
    gzip off;
    expires 1M;
    add_header Cache-Control "public";
}

# Uncompressed Archives
location ~* \.(?:tar|exe)$ {
    expires 1M;
    add_header Cache-Control "public";
}

# Documents
location ~* \.(?:doc|xls|pfd|ppt|rtf|rst|tex)$ {
    expires 1M;
    add_header Cache-Control "public";
}

#
# Filename-based cache busting
# Route all requests for /css/style.20120716.css to /css/style.css
# github.com/h5bp/html5-boilerplate/wiki/cachebusting
#location ~* (.+)\.(?:\d+)\.(js|css|png|jpg|jpeg|gif)$ {
#    try_files $uri $1.$2;
#}