├── 50x.html ├── README.md ├── conf.d ├── error-page.conf ├── html5-sse.conf ├── https.conf └── proxy.conf └── nginx.conf /50x.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ExampleCorp | Example's being upgraded! 5 | 48 | 49 | 50 |

51 | 52 | 53 | 54 | 55 | 56 | ExampleCorp Examplary work since 1981 57 |

58 |

Example is being upgraded!

59 |

We'll be back shortly.

60 | 61 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## An nginx config for 2017 2 | 3 | nginx has [excellent official documentation](https://www.nginx.com/resources/wiki/start/) but putting all the logic together can take a while. Here's an `nginx.conf` with: 4 | 5 | - HTTP/2 6 | - IPv6 7 | - Load balancing between multiple app servers 8 | - A sorry page (shown if all the app servers go down) 9 | - Static content served on a separate server 10 | - HTML5 SSE support 11 | - Correct proxy headers for working GeoIP 12 | - The various www vs non-www, HTTP vs HTTPS combinations redirected to a single HTTPS site 13 | 14 | See the [full documentation at CertSimple](https://certsimple.com/blog/nginx-http2-load-balancing-config), including diagrams and explanations for why particular values were chosen. 15 | 16 | ## Pull requests welcome 17 | 18 | If you have useful changes or additions you're welcome to send pull requests. Try and use include files in `conf.d` where possible! -------------------------------------------------------------------------------- /conf.d/error-page.conf: -------------------------------------------------------------------------------- 1 | # Gateway error page - should only ever been seen if no servers are up 2 | # 500 and 40x errors are handled by the app servers 3 | # http://nginx.org/en/docs/http/ngx_http_core_module.html#error_page 4 | error_page 502 503 504 /50x.html; # Bad gateway, service unavailable, gateway timeout 5 | location = /50x.html { 6 | root /etc/nginx; 7 | internal; 8 | } -------------------------------------------------------------------------------- /conf.d/html5-sse.conf: -------------------------------------------------------------------------------- 1 | # From http://stackoverflow.com/questions/13672743/eventsource-server-sent-events-through-nginx 2 | proxy_set_header Connection ''; 3 | proxy_http_version 1.1; 4 | chunked_transfer_encoding off; 5 | proxy_buffering off; -------------------------------------------------------------------------------- /conf.d/https.conf: -------------------------------------------------------------------------------- 1 | # Based on Mozilla SSL Configuration Generatorr 2 | # This is using the 'intermediate' config, you may prefer 'modern' 3 | # Check https://mozilla.github.io/server-side-tls/ssl-config-generator/ and update this file! 4 | ssl_certificate /etc/https/cert-and-intermediate.pem; 5 | ssl_certificate_key /etc/https/private-key.pem; 6 | ssl_session_timeout 1d; 7 | ssl_session_cache shared:SSL:50m; 8 | ssl_session_tickets off; 9 | 10 | # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits 11 | # Create this file with: 12 | # openssl dhparam -out dhparam.pem 2048 13 | ssl_dhparam /etc/https/dhparam.pem; 14 | 15 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 16 | ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS'; 17 | ssl_prefer_server_ciphers on; 18 | 19 | # HSTS (15768000 seconds = 6 months) 20 | add_header Strict-Transport-Security max-age=15768000; 21 | 22 | # OCSP Stapling 23 | # fetch OCSP records from URL in ssl_certificate and cache them 24 | ssl_stapling on; 25 | ssl_stapling_verify on; 26 | 27 | # verify chain of trust of OCSP response using Root CA and Intermediate certs 28 | ssl_trusted_certificate /etc/https/root-and-intermediate.pem; 29 | 30 | # Use local DNS server 31 | resolver ; -------------------------------------------------------------------------------- /conf.d/proxy.conf: -------------------------------------------------------------------------------- 1 | proxy_set_header Host $host; 2 | proxy_set_header X-Real-IP $remote_addr; 3 | proxy_set_header X-Forwarded-Proto $scheme; 4 | proxy_set_header X-Forwarded-For $remote_addr; -------------------------------------------------------------------------------- /nginx.conf: -------------------------------------------------------------------------------- 1 | # Default Ubuntu nginx config 2 | user www-data; 3 | worker_processes auto; 4 | pid /run/nginx.pid; 5 | 6 | events { 7 | worker_connections 768; 8 | } 9 | 10 | http { 11 | sendfile on; 12 | tcp_nopush on; 13 | tcp_nodelay on; 14 | keepalive_timeout 65; 15 | types_hash_max_size 2048; 16 | 17 | include mime.types; 18 | default_type application/octet-stream; 19 | 20 | log_format main '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for"'; 21 | access_log /var/log/nginx/access.log; 22 | error_log /var/log/nginx/error.log; 23 | 24 | gzip on; 25 | 26 | # End default Ubuntu nginx config 27 | 28 | # Fix nginx sending its version number in error pages and Server header 29 | server_tokens off; 30 | # No iframes 31 | add_header X-Frame-Options SAMEORIGIN; 32 | # We'll supply correct content types, don't let browsers guess 33 | add_header X-Content-Type-Options nosniff; 34 | 35 | upstream app { 36 | # Make each client IP address stick to the same server 37 | # See http://nginx.org/en/docs/http/load_balancing.html 38 | ip_hash; 39 | 40 | # Use IP addresses: see recommendation at https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/ 41 | server 10.132.29.223:8000; # example-a 42 | server 10.132.55.149:8000; # example-b 43 | } 44 | 45 | # Redirect www HTTP clients to non-www HTTPS permanently 46 | # See http://nginx.org/en/docs/http/converting_rewrite_rules.html 47 | server { 48 | listen 80; 49 | listen [::]:80; 50 | server_name www.example.com; 51 | return 301 https://example.com$request_uri; 52 | } 53 | 54 | # Redirect www HTTPS clients to non-www HTTPS permanently 55 | server { 56 | listen 443 ssl http2; 57 | listen [::]:443 ssl http2; 58 | server_name www.example.com; 59 | include conf.d/https.conf; 60 | return 301 https://example.com$request_uri; 61 | } 62 | 63 | # Redirect non-HTTPs clients to non-www HTTPS permanently 64 | server { 65 | listen 80; 66 | listen [::]:80; 67 | server_name example.com; 68 | return 301 https://example.com$request_uri; 69 | include conf.d/https.conf; 70 | } 71 | 72 | # Single HTTPS non-www point all browsers will talk to 73 | server { 74 | listen 443 ssl http2; 75 | listen [::]:443 ssl http2; 76 | server_name example.com; 77 | include conf.d/https.conf; 78 | 79 | # Tilde means case-sensitive RE match 80 | location ~ ^(/help|/sitemap.xml|/BingSiteAuth.xml|/about|/why-ev-ssl|/blog|/rosetta-stone|/videos/blog|/images/blog|/fonts/blog|/images/rosetta-stone|/css/blog|/js/blog|/css/rosetta-stone.css) { 81 | proxy_pass http://localhost:8000; 82 | include conf.d/proxy.conf; 83 | } 84 | 85 | location / { 86 | proxy_pass http://app; # See 'upstream' directive above 87 | # proxy.conf must be included in this level (and not the parent) otherwise they won't be inherited due to other proxy options in html-sse.conf 88 | # http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_set_header 89 | include conf.d/proxy.conf; 90 | include conf.d/html5-sse.conf; 91 | } 92 | 93 | # From https://easyengine.io/tutorials/nginx/status-page/ 94 | location /nginx_status { 95 | stub_status on; 96 | access_log off; 97 | allow 127.0.0.1; 98 | deny all; 99 | } 100 | 101 | include conf.d/error-page.conf; 102 | } 103 | } --------------------------------------------------------------------------------