└── README.md /README.md: -------------------------------------------------------------------------------- 1 | # Nginx Gotchas 2 | 3 | ## [Official pitfalls and common mistakes](https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/) 4 | 5 | ## SSL best practices 6 | - ### [Mozilla SSL Configuration Generator](https://ssl-config.mozilla.org/) 7 | - ### [Bettercrypto](https://bettercrypto.org/#_nginx) 8 | - ### [Cipherli.st](https://cipherli.st/) 9 | 10 | ## Directive matching order 11 | - ### [DigitalOcean article](https://www.digitalocean.com/community/tutorials/understanding-nginx-server-and-location-block-selection-algorithms) 12 | - #### `server_name` 13 | - > ... If none of the above steps are able to satisfy the request, then the request will be passed to the `default_server` for the matching IP address and port. 14 | - If no `default_server` is specified, the **first** server block will be chosen 15 | 16 | ## MIME type detection 17 | - ### `alias`, `proxy_pass` and jumps won't recognize the destination MIME type. You need an explicit `default_type`: 18 | ```nginx 19 | location /cv { 20 | default_type text/html; 21 | alias /etc/nginx/cv.html; 22 | } 23 | ``` 24 | 25 | ## Snippets 26 | ### Jump location block 27 | > The order of execution for each approach is different, test which works for your use case. 28 | ```nginx 29 | location /example1 { 30 | ... 31 | try_files /dev/null @login; 32 | } 33 | 34 | location /example2 { 35 | ... 36 | error_page 404 = @login; 37 | return 404; 38 | } 39 | 40 | location @login { 41 | internal; 42 | ... 43 | } 44 | ``` 45 | 46 | ### Access `http` block from `.config` file 47 | ```nginx 48 | # will go in parent (http) block 49 | limit_req_zone $binary_remote_addr zone=userlimit:10m rate=1r/s; 50 | 51 | server { 52 | ... 53 | } 54 | ``` 55 | 56 | ### Reverse proxy 57 | ```nginx 58 | # pass proper hostname 59 | proxy_set_header Host $http_host; 60 | proxy_set_header X-Forwarded-Host $http_host; 61 | # pass proper client IP 62 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 63 | proxy_set_header X-Real-IP $remote_addr; 64 | # pass proper protocol 65 | proxy_set_header X-Forwarded-Proto $scheme; 66 | 67 | # don't automatically fix "location" and "redirect" headers 68 | proxy_redirect off; 69 | proxy_buffering off; 70 | 71 | proxy_pass ...; 72 | ``` 73 | 74 | ### Rate limit 75 | ```nginx 76 | limit_req_status 403; 77 | limit_req zone=serverlimit burst=10 nodelay; 78 | limit_req zone=userlimit burst=5 nodelay; 79 | ``` 80 | 81 | ### Disable search engine crawling 82 | ```nginx 83 | location = /robots.txt { 84 | add_header Content-Type text/plain; 85 | return 200 "User-agent: *\nDisallow: /\n"; 86 | } 87 | ``` 88 | 89 | ### Cookie-based auth proxy 90 | ```nginx 91 | auth_request /auth; 92 | 93 | # pass auth cookie to client 94 | auth_request_set $saved_set_cookie $upstream_http_set_cookie; 95 | add_header Set-Cookie $saved_set_cookie; 96 | 97 | # use = to take precedence over other ~ locations 98 | location = /auth { 99 | internal; 100 | proxy_pass_request_body off; 101 | proxy_set_header Content-Length ""; 102 | proxy_set_header X-Original-URI $request_uri; 103 | # the "reverse proxy" section discussed before 104 | include reverse-proxy.conf; 105 | 106 | # don't pass request headers 107 | # e.g. If-Modified will result in 412 108 | proxy_pass_request_headers off; 109 | # only pass the required 110 | proxy_set_header Authorization $http_Authorization; 111 | proxy_set_header Cookie $http_cookie; 112 | 113 | proxy_pass https://auth.example.com; 114 | } 115 | ``` 116 | 117 | ### Don't respond if invalid URL 118 | ```nginx 119 | error_page 404 403 @putoff; 120 | 121 | location @putoff { 122 | return 444; 123 | } 124 | 125 | location / { 126 | error_page 418 @putoff; 127 | return 418; 128 | } 129 | ``` 130 | ### `proxy_pass` trailing slash ([Source](https://stackoverflow.com/questions/22759345/nginx-trailing-slash-in-proxy-pass-url)) 131 | - No URI (i.e. `http://server:1234`) will forward the URI from the original request exactly as it was with all double slashes, `../` and so on 132 | - With URI (i.e. `http://server:1234/a/`) acts like the `alias` directive, meaning nginx will replace the part that matches the location prefix with the URI in the `proxy_pass` directive. For example: 133 | ```nginx 134 | location /one/ { 135 | proxy_pass http://127.0.0.1:8080/two; 136 | } 137 | ``` 138 | Accessing `http://yourserver.com/one/path/here?param=1` will become `http://127.0.0.1/twopath/here?param=1` 139 | --------------------------------------------------------------------------------