├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── forge-templates ├── NginxFastCGICacheTemplate.conf └── NginxTemplate.conf ├── nginx-partials ├── cache-busting.conf ├── compression.conf ├── expires.conf └── security.conf └── sites-available ├── basic_localdev.com.conf └── somedomain.com.conf /.gitignore: -------------------------------------------------------------------------------- 1 | # MISC FILES / aaw -- 2016.10.26 2 | .cache 3 | .DS_Store 4 | .idea 5 | .project 6 | .settings 7 | *.esproj 8 | *.sublime-workspace 9 | *.sublime-project 10 | *.tmproj 11 | *.tmproject 12 | Thumbs.db 13 | /logs/* 14 | /yarn-error.log 15 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Nginx-Craft Changelog 2 | 3 | ## 1.0.34 - 2021.04.18 4 | ### Added 5 | * Added a [Forge Template](https://forge.laravel.com/docs/1.0/servers/nginx-templates.html) `NginxFastCGICacheTemplate.conf` 6 | * Opt out of Google Federated Learning of Cohorts ("FLoC") via the `Permissions-Policy` header. [ref:](https://amifloced.org/) 7 | 8 | ## 1.0.33 - 2021.03.17 9 | ### Changed 10 | * Updated the Forge template to use more Forge-provided variables 11 | 12 | ## 1.0.32 - 2021.02.08 13 | ### Changed 14 | * Changed the include path from `/etc/nginx` to `/home/forge` for the Forge config 15 | * Removed repeated `server_tokens` within Primary block 16 | * Changes max-age for HSTS to be one year for preloading 17 | 18 | ## 1.0.31 - 2020.11.19 19 | ### Changed 20 | * Changed `public` to `web` for the server `root` example 21 | 22 | ## 1.0.30 - 2020.11.05 23 | ### Added 24 | * Added support for [Forge Templates](https://forge.laravel.com/docs/1.0/servers/nginx-templates.html) via `forge-templates/NginxTemplate.conf` 25 | 26 | ## 1.0.29 - 2020.10.21 27 | ### Changed 28 | * Fix multi-site requests missing query params 29 | 30 | ## 1.0.28 - 2020.08.20 31 | ### Changed 32 | * Set `server_tokens` to `off` 33 | * Changed the `dhparam` setting to `/etc/nginx/dhparams.pem` to mirror the Forge default 34 | 35 | ## 1.0.27 - 2020.06.23 36 | ### Changed 37 | * Explicitly set `DOCUMENT_ROOT` 38 | 39 | ## 1.0.26 - 2020.06.23 40 | ### Changed 41 | * Changed `$document_root` to `$realpath_root` to sidestep opcache issues automatically [Learn More](https://ma.ttias.be/php-opcache-and-symlink-based-deploys/) 42 | 43 | ## 1.0.25 - 2020.06.15 44 | ### Changed 45 | * Route any 404s for `expires.conf` matches back through Craft for handling 46 | 47 | ## 1.0.24 - 2020.05.14 48 | ### Added 49 | * Added `always` to all of the added headers in `security.conf` so that they are added regardless of response code 50 | 51 | ## 1.0.23 - 2020.05.14 52 | ### Added 53 | * Added better `Cache-Control` header settings in `expires.conf` for static resources, leveraging `immutable`, `must-revalidate`, and `max-age` 54 | * Added `svg` to cache-busted extensions in `cache-busting.conf` 55 | 56 | ## 1.0.22 - 2019.12.31 57 | ### Changed 58 | * Enable serving of static gzip files via [gzip_static](http://nginx.org/en/docs/http/ngx_http_gzip_static_module.html) 59 | * Removed superfluous whitespace in map block 60 | 61 | ## 1.0.21 - 2019.07.24 62 | ### Changed 63 | * Load `security.conf` from nginx-partials again inside of the `location ~ [^/]\.php(/|$)` block 64 | * Added `xmlrpc` to the WordPress redirects 65 | 66 | ## 1.0.20 - 2019.05.15 67 | ### Changed 68 | * Removed the `location` block in `expires.conf` that matched `.rss` and `.atom` since these almost always should go through Craft 69 | 70 | ## 1.0.19 - 2019.04.10 71 | ### Added 72 | * Include an example of serving up a placeholder image when a 404 happens for static image assets 73 | 74 | ## 1.0.18 - 2019.03.21 75 | ### Added 76 | * Includes [Dotenvy](https://github.com/nystudio107/dotenvy) generated `.env` files 77 | 78 | ## 1.0.17 - 2018.08.21 79 | ### Added 80 | * Don't allow browser caching of dynamically generated content 81 | 82 | ### Changed 83 | * Added "Remove if you don't plan to use server-set ENV variables" comment 84 | 85 | ## 1.0.16 - 2018.05.14 86 | ### Changed 87 | * Removed duplicate `client_max_body_size` directives 88 | 89 | ## 1.0.15 - 2018.01.23 90 | ### Changed 91 | * Removed incorrect `=404` directives 92 | 93 | ## 1.0.14 - 2018.01.21 94 | ### Added 95 | * Explicitly set fastcgi_param `HTTP_HOST` to mitigate [HTTP_HOST Security Issues](https://expressionengine.com/blog/http-host-and-server-name-security-issues) 96 | * Added `=404` as the last parameter in each of the `try_files` directives to avoid internal loops 97 | * Added `ssi on;` to the default config for server-side includes 98 | 99 | ## 1.0.13 - 2017.12.14 100 | ### Added 101 | * Disable limits on the maximum allowed size of the client request body via `client_max_body_size` 102 | * Add expires headers for `mp3` files 103 | * Updated bot UserAgents list 104 | 105 | ## 1.0.12 - 2017.11.23 106 | ### Added 107 | * Added configuration for banning bots based on UserAgent 108 | 109 | ## 1.0.11 - 2017.10.02 110 | ### Added 111 | * Added a `basic_localdev.com.conf` for people who just want a basic Nginx configuration for Craft local dev 112 | 113 | ## 1.0.10 - 2017.09.12 114 | ### Changed 115 | * Updated the config to use php7.1 by default 116 | * Added comments for the CME config 117 | 118 | ## 1.0.9 - 2017.09.01 119 | ### Changed 120 | * Added OCSP stapling 121 | * Tweaked TLS settings for performance 122 | * Optimized `ssl_buffer_size` for TTFB 123 | * Updated README.md with instructions for downloading your Issuer certificate 124 | 125 | ## 1.0.8 - 2017.08.24 126 | ### Changed 127 | * Fixed an issue where the removal of trailing slashes could cause directory URLs to fail with "too many redirects" 128 | 129 | ## 1.0.7 - 2017.08.05 130 | ### Added 131 | * Added `Referrer-Policy "no-referrer-when-downgrade";` to `security.conf` 132 | 133 | ## 1.0.6 - 2017.07.06 134 | ### Added 135 | * Added handling of missing `.php` files routed through Craft 136 | * Added `404` handler 137 | * Added `.gitignore` 138 | 139 | ### Changed 140 | * Removed `html` and other non-cacheable files from matching in `expires.conf` 141 | 142 | ## 1.0.5 - 2017.03.27 143 | ### Added 144 | * Added `webp` to the `expires` header support 145 | 146 | ### Changed 147 | * Remove `etags` from static resources 148 | * Updated the CHANGELOG.md format 149 | 150 | ## 1.0.4 - 2017.03.02 151 | ### Added 152 | * Added (commented out) support for error logging going to `SYSLOG` for log services 153 | * Redirect bots probing the site for WordPress vulnerabilities 154 | * Added information on `opcache` 155 | * Added a redirect for Do Not Track as per https://www.eff.org/dnt-policy 156 | * Change // -> / for all URLs, so it works for our php location block, too 157 | 158 | ### Changed 159 | * Removed `le-well-known.conf` so that it doesn't conflict with default Forge setups 160 | * Updated README.md 161 | 162 | ## 1.0.3 - 2016.12.10 163 | ### Added 164 | * Added support for localized sites (commented out by default) 165 | * Added `HTTP_PROXY` 166 | * Added `client_max_body_size` to the README.md 167 | 168 | ### Changed 169 | * Updated README.md 170 | 171 | ## 1.0.2 - 2016.11.30 172 | ### Added 173 | * Added an example Forge configuration in `forge-example` 174 | * 301 Redirect URLs with trailing /'s as per https://webmasters.googleblog.com/2010/04/to-slash-or-not-to-slash.html 175 | 176 | ### Changed 177 | * Updated README.md 178 | 179 | ## 1.0.1 - 2016.11.09 180 | ### Added 181 | * Added `server_tokens off` to disable sending the Nginx version number 182 | * Added a commented out `Content-Security-Policy` header in `security.conf` 183 | 184 | ### Changed 185 | * Updated README.md 186 | 187 | ## 1.0.0 - 2016.11.01 188 | ### Added 189 | * Initial release 190 | 191 | Brought to you by [nystudio107](https://nystudio107.com/) 192 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 nystudio107 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nginx-craft 2 | 3 | An Nginx virtual host configuration for Craft CMS that implements a number of best-practices. 4 | 5 | ## Overview 6 | 7 | ### What it handles 8 | 9 | The Nginx-Craft configuration handles: 10 | 11 | * Redirecting from HTTP to HTTPS 12 | * Canonical domain rewrites from www.SOMEDOMAIN.com to SOMEDOMAIN.com 13 | * 301 Redirect URLs with trailing /'s as per https://webmasters.googleblog.com/2010/04/to-slash-or-not-to-slash.html 14 | * Setting `PATH_INFO` properly via php-fpm -> PHP 15 | * Setting `HTTP_HOST` to mitigate [HTTP_HOST Security Issues](https://expressionengine.com/blog/http-host-and-server-name-security-issues) 16 | * "Far-future" Expires headers 17 | * Enable serving of static gzip files via [gzip_static](http://nginx.org/en/docs/http/ngx_http_gzip_static_module.html) 18 | * Adding XSS and other security headers 19 | * Gzip compression 20 | * Filename-based cache busting for static resources 21 | * IPv4 and IPv6 support 22 | * http2 support 23 | * Reasonable SSL cipher suites and TLS protocols 24 | * Localized sites 25 | * Server-side includes 26 | * Optionally includes [Dotenvy](https://github.com/nystudio107/dotenvy) generated `.env` files 27 | 28 | ### Assumptions made 29 | 30 | The following are assumptions made in this configuration: 31 | 32 | * The site is https 33 | * The SSL certificate is from LetsEncrypt.com 34 | * The canonical domain is SOMEDOMAIN.com (no www.) 35 | * Nginx is version 1.9.5 or later (and thus supports http2) 36 | * Paths are standard Ubuntu, change as needed 37 | * You're using php7.1 via php-fpm 38 | * You have `'omitScriptNameInUrls' => true,` in your `craft/general.php` 39 | 40 | If any of these assumptions are invalid, make the appropriate changes. 41 | 42 | **Note**: We disable TLSv1.0 because it is insecure, but IE 8, 9 & 10 need to have support for TLSv1.1 [manually enabled or they will not be able to connect](https://answers.microsoft.com/en-us/ie/forum/ie10-windows_other/disabling-tlsv10-breaks-compatibility-with-ie-9/80e77823-0f0c-49a8-b525-15ce6d7a570d?auth=1). 43 | 44 | ### What's included 45 | 46 | This Nginx configuration comes in two parts: 47 | 48 | * `sites-available/somedomain.com.conf` - an Nginx virtual host configuration file tailored for Craft CMS; it will require some minor customization for your domain 49 | * `nginx-partials` - some Nginx configuration partials used by all of the virtual hosts, logically segregated. These don't need to be changed, but can be selectively disabled by changing the suffix to `.off` (or anything other than `.conf`) 50 | 51 | ## Using Nginx-Craft 52 | 53 | 1. Obtain an SSL certificate for your domain via [LetsEncrypt.com](https://letsencrypt.org/) (or via other certificate authorities). LetsEncrypt.com is free, and it's automated. You will need a basic server up and running that responds to port 80 to do this, [LetsEnecrypt/Nginx tutorial](https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-16-04) 54 | 2. Create a `dhparam.pem` via `sudo openssl dhparam -out /etc/nginx/dhparams.pem 2048` 55 | 3. Download your Issuer certificate via `mkdir /etc/nginx/ssl; sudo wget -O /etc/nginx/ssl/lets-encrypt-x3-cross-signed.pem "https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem"` 56 | 4. Upload the entire `nginx-partials` folder to `/etc/nginx/` 57 | 5. Rename the `somedomain.com.conf` file to `yourdomain.com.conf` 58 | 6. Do a search & replace in `yourdomain.com.conf` to change `SOMEDOMAIN` -> `yourdomain` 59 | 7. Tweak any paths that may need changing on your server 60 | 8. Change the `fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;` line to reflect whatever version of PHP you're running 61 | 9. Restart nginx via `sudo nginx -s reload` 62 | 63 | If you're using [Forge](https://forge.laravel.com/), it takes care of a number of these things for you, but still needs tuning. 64 | 65 | The same applies for CloudWays, ServerPilot, Homestead, MAMP, etc. 66 | 67 | A [Forge Template](https://forge.laravel.com/docs/1.0/servers/nginx-templates.html) is provided in `forge-templates/NginxTemplate.conf` that you can use to [automate setting up](https://blog.laravel.com/forge-nginx-templates) your Forge servers. 68 | 69 | For this to work, you must clone the repo into `/home/forge` via: 70 | ``` 71 | git clone https://github.com/nystudio107/nginx-craft.git /home/forge 72 | ``` 73 | 74 | For further information on TLS optimization, see the [How to properly configure your nginx for TLS](https://medium.com/@mvuksano/how-to-properly-configure-your-nginx-for-tls-564651438fe0) article. 75 | 76 | ## Forge & opcache 77 | 78 | **N.B.:** Forge now has `opcache` functionality baked-in, you can enable it via the Server settings, so this information is largely deprecated. 79 | 80 | If you're using Forge, understand that `opcache` is off by default. To enable it, go to your server in Forge, click on *Edit Files* and choose *Edit PHP FPM Configuration* and search on `opcache`. Here are the defaults I use; tweak them to suit your needs: 81 | 82 | [opcache] 83 | ; Determines if Zend OPCache is enabled 84 | opcache.enable=1 85 | 86 | ; Determines if Zend OPCache is enabled for the CLI version of PHP 87 | ;opcache.enable_cli=0 88 | 89 | ; The OPcache shared memory storage size. 90 | opcache.memory_consumption=256 91 | 92 | ; The amount of memory for interned strings in Mbytes. 93 | opcache.interned_strings_buffer=16 94 | 95 | ; The maximum number of keys (scripts) in the OPcache hash table. 96 | ; Only numbers between 200 and 100000 are allowed. 97 | opcache.max_accelerated_files=8000 98 | 99 | ; If disabled, all PHPDoc comments are dropped from the code to reduce the 100 | ; size of the optimized code. 101 | opcache.save_comments=0 102 | 103 | More about tweaking `opcache` can be found in the [Fine-Tune Your Opcache Configuration to Avoid Caching Suprises](https://tideways.io/profiler/blog/fine-tune-your-opcache-configuration-to-avoid-caching-suprises) article. The [Best Zend OpCache Settings/Tuning/Config](https://www.scalingphpbook.com/blog/2014/02/14/best-zend-opcache-settings.html) article is very useful as well. 104 | 105 | ## Local Development 106 | 107 | While all of the configuration in the `somedomain.com.conf` will work fine in local development as well, some people might want a simpler setup for local development. 108 | 109 | There is a `basic_localdev.com.conf` that you can use for a basic Nginx configuration that will work with Craft without any of the bells, whistles, or optimizations found in the `somedomain.com.conf`. 110 | 111 | While this is suitable for getting up and running quickly for local development, do not use it in production. There are a number of performance optimizations missing from it. 112 | 113 | Brought to you by [nystudio107](https://nystudio107.com/) 114 | -------------------------------------------------------------------------------- /forge-templates/NginxFastCGICacheTemplate.conf: -------------------------------------------------------------------------------- 1 | # FastCGI Cache 2 | fastcgi_cache_path /var/run/nginx-cache/{{ SITE }} levels=1:2 keys_zone={{ SITE }}:100m inactive=1d use_temp_path=off max_size=100m; 3 | 4 | # FORGE CONFIG (DO NOT REMOVE!) 5 | include forge-conf/{{ SITE }}/before/*; 6 | 7 | # Bots to ban via user agent 8 | map $http_user_agent $limit_bots { 9 | default 0; 10 | ~*(AhrefsBot|Baiduspider|PaperLiBot) 1; 11 | } 12 | 13 | server { 14 | # Listen for both IPv4 & IPv6 requests on port 443 with http2 enabled 15 | listen {{ PORT }}; 16 | listen {{ PORT_V6 }}; 17 | 18 | # General virtual host settings 19 | server_name {{ DOMAINS }}; 20 | server_tokens off; 21 | root {{ PATH }}; 22 | index index.html index.htm index.php; 23 | charset utf-8; 24 | 25 | # Enable serving of static gzip files as per: http://nginx.org/en/docs/http/ngx_http_gzip_static_module.html 26 | gzip_static on; 27 | 28 | # Enable server-side includes as per: http://nginx.org/en/docs/http/ngx_http_ssi_module.html 29 | ssi on; 30 | 31 | # Disable limits on the maximum allowed size of the client request body 32 | client_max_body_size 0; 33 | 34 | # Ban certain bots from crawling the site 35 | if ($limit_bots = 1) { 36 | return 403; 37 | } 38 | 39 | # 404 error handler 40 | error_page 404 /index.php?$query_string; 41 | 42 | # 301 Redirect URLs with trailing /'s as per https://webmasters.googleblog.com/2010/04/to-slash-or-not-to-slash.html 43 | rewrite ^/(.*)/$ /$1 permanent; 44 | 45 | # Change // -> / for all URLs, so it works for our php location block, too 46 | merge_slashes off; 47 | rewrite (.*)//+(.*) $1/$2 permanent; 48 | 49 | # Handle Do Not Track as per https://www.eff.org/dnt-policy 50 | location /.well-known/dnt-policy.txt { 51 | try_files /dnt-policy.txt /index.php?p=/dnt-policy.txt; 52 | } 53 | 54 | # For WordPress bots/users 55 | location ~ ^/(wp-login|wp-admin|wp-config|wp-content|wp-includes|wp-json|xmlrpc) { 56 | return 301 https://wordpress.com/wp-login.php; 57 | } 58 | 59 | #Cache everything by default 60 | fastcgi_cache_key "$scheme$request_method$host$request_uri"; 61 | add_header X-Cache-Status $upstream_cache_status; 62 | set $no_cache 0; 63 | if ($request_method = POST) 64 | { 65 | set $no_cache 1; 66 | } 67 | if ($request_uri ~* "/(admin/|cpresources/)") 68 | { 69 | set $no_cache 1; 70 | } 71 | 72 | # Access and error logging 73 | access_log off; 74 | error_log /var/log/nginx/{{ SITE }}-error.log error; 75 | # If you want error logging to go to SYSLOG (for services like Papertrailapp.com), uncomment the following: 76 | #error_log syslog:server=unix:/dev/log,facility=local7,tag=nginx,severity=error; 77 | 78 | # FORGE SSL (DO NOT REMOVE!) 79 | ssl_certificate /etc/nginx/ssl/{{ SITE }}/XXXXXX/server.crt; 80 | ssl_certificate_key /etc/nginx/ssl/{{ SITE }}/XXXXXX/server.key; 81 | 82 | # SSL/TLS configuration, with TLSv1.0 disabled because it is insecure; note that IE 8, 9 & 10 support 83 | # TLSv1.1, but it's not enabled by default clients using those browsers will not be able to connect 84 | ssl_protocols TLSv1.2 TLSv1.1; 85 | ssl_prefer_server_ciphers on; 86 | ssl_dhparam /etc/nginx/dhparams.pem; 87 | ssl_ciphers 'ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5'; 88 | ssl_buffer_size 4k; 89 | ssl_session_timeout 4h; 90 | ssl_session_cache shared:SSL:40m; 91 | ssl_stapling on; 92 | ssl_stapling_verify on; 93 | ssl_trusted_certificate /etc/nginx/ssl/lets-encrypt-x3-cross-signed.pem; 94 | 95 | # FORGE CONFIG (DO NOT REMOVE!) 96 | include forge-conf/{{ SITE }}/server/*; 97 | 98 | # Load configuration files from nginx-partials 99 | # For this to work, you must clone the repo into /home/forge via: 100 | # git clone https://github.com/nystudio107/nginx-craft.git /home/forge 101 | include /home/forge/nginx-craft/nginx-partials/*.conf; 102 | 103 | # Root directory location handler 104 | location / { 105 | try_files $uri/index.html $uri $uri/ /index.php?$query_string; 106 | } 107 | 108 | # Localized sites, hat tip to Johannes -- https://gist.github.com/johanneslamers/f6d2bc0d7435dca130fc 109 | 110 | # If you are creating a localized site as per: https://craftcms.com/docs/localization-guide 111 | # the directives here will help you handle the locale redirection so that requests will 112 | # be routed through the appropriate index.php wherein you set the `CRAFT_LOCALE` 113 | 114 | # Enable this by un-commenting it, and changing the language codes as appropriate 115 | # Add a new location @XXrewrites and location /XX/ block for each language that 116 | # you need to support 117 | 118 | #location @enrewrites { 119 | # rewrite ^/en/(.*)$ /en/index.php?$query_string? last; 120 | #} 121 | # 122 | #location /en/ { 123 | # try_files $uri $uri/ @enrewrites; 124 | #} 125 | 126 | # Craft-specific location handlers to ensure AdminCP requests route through index.php 127 | # If you change your `cpTrigger`, change it here as well 128 | location ^~ /admin { 129 | try_files $uri $uri/ @phpfpm_nocache; 130 | } 131 | location ^~ /index.php/admin { 132 | try_files $uri $uri/ @phpfpm_nocache; 133 | } 134 | location ^~ /cpresources { 135 | try_files $uri $uri/ /index.php?$query_string; 136 | } 137 | location ^~ /actions { 138 | try_files $uri $uri/ /index.php?$query_string; 139 | } 140 | 141 | # php-fpm configuration 142 | location ~ [^/]\.php(/|$) { 143 | try_files $uri $uri/ /index.php?$query_string; 144 | fastcgi_split_path_info ^(.+\.php)(/.+)$; 145 | # Change this to whatever version of php you are using 146 | fastcgi_pass {{ PROXY_PASS }}; 147 | fastcgi_index index.php; 148 | include fastcgi_params; 149 | fastcgi_param PATH_INFO $fastcgi_path_info; 150 | fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; 151 | fastcgi_param DOCUMENT_ROOT $realpath_root; 152 | fastcgi_param HTTP_PROXY ""; 153 | fastcgi_param HTTP_HOST {{ SITE }}; 154 | 155 | # Don't allow browser caching of dynamically generated content 156 | add_header Last-Modified $date_gmt; 157 | add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0"; 158 | if_modified_since off; 159 | expires off; 160 | etag off; 161 | # Load security.conf from nginx-partials again, because add_header used in this location 162 | # block removes any already added headers https://nginx.org/en/docs/http/ngx_http_headers_module.html 163 | include /home/forge/nginx-partials/security.conf; 164 | 165 | # Use Dotenvy to generate the .env variables as per: https://github.com/nystudio107/dotenvy 166 | # and then uncomment this line to include them: 167 | # include /home/forge/SOMEDOMAIN/.env_nginx.txt 168 | 169 | fastcgi_intercept_errors off; 170 | fastcgi_buffer_size 16k; 171 | fastcgi_buffers 4 16k; 172 | fastcgi_connect_timeout 300; 173 | fastcgi_send_timeout 300; 174 | fastcgi_read_timeout 300; 175 | 176 | # FastCGI Cache settings 177 | fastcgi_ignore_headers Cache-Control Expires Set-Cookie; 178 | fastcgi_cache {{ SITE }}; 179 | fastcgi_hide_header Set-Cookie; 180 | fastcgi_cache_valid 200 1d; 181 | fastcgi_cache_use_stale updating error timeout invalid_header http_500; 182 | fastcgi_cache_bypass $no_cache; 183 | fastcgi_no_cache $no_cache; 184 | } 185 | 186 | # php-fpm configuration for non-cached content 187 | location @phpfpm_nocache { 188 | fastcgi_split_path_info ^(.+\.php)(/.+)$; 189 | # Change this to whatever version of php you are using 190 | fastcgi_pass {{ PROXY_PASS }}; 191 | fastcgi_index index.php; 192 | include fastcgi_params; 193 | fastcgi_param PATH_INFO $query_string; 194 | fastcgi_param SCRIPT_FILENAME $realpath_root/index.php; 195 | fastcgi_param DOCUMENT_ROOT $realpath_root; 196 | fastcgi_param HTTP_PROXY ""; 197 | fastcgi_param HTTP_HOST {{ SITE }}; 198 | 199 | # Don't allow browser caching of dynamically generated content 200 | add_header X-Cache-Status $upstream_cache_status; 201 | add_header Last-Modified $date_gmt; 202 | add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0"; 203 | if_modified_since off; 204 | expires off; 205 | etag off; 206 | # Load security.conf from nginx-partials again, because add_header used in this location 207 | # block removes any already added headers https://nginx.org/en/docs/http/ngx_http_headers_module.html 208 | include /home/forge/nginx-craft/nginx-partials/security.conf; 209 | 210 | # Use Dotenvy to generate the .env variables as per: https://github.com/nystudio107/dotenvy 211 | # and then uncomment this line to include them: 212 | # include /home/forge/SOMEDOMAIN/.env_nginx.txt 213 | 214 | fastcgi_intercept_errors off; 215 | fastcgi_buffer_size 16k; 216 | fastcgi_buffers 4 16k; 217 | fastcgi_connect_timeout 300; 218 | fastcgi_send_timeout 300; 219 | fastcgi_read_timeout 300; 220 | 221 | # No FastCGI Cache 222 | fastcgi_cache_bypass 1; 223 | fastcgi_no_cache 1; 224 | } 225 | 226 | location ~ /\.ht { 227 | deny all; 228 | } 229 | } 230 | 231 | # FORGE CONFIG (DO NOT REMOVE!) 232 | include forge-conf/{{ SITE }}/after/*; 233 | -------------------------------------------------------------------------------- /forge-templates/NginxTemplate.conf: -------------------------------------------------------------------------------- 1 | # FORGE CONFIG (DO NOT REMOVE!) 2 | include forge-conf/{{ SITE }}/before/*; 3 | 4 | # Bots to ban via user agent 5 | map $http_user_agent $limit_bots { 6 | default 0; 7 | ~*(AhrefsBot|Baiduspider|PaperLiBot) 1; 8 | } 9 | 10 | server { 11 | # Listen for both IPv4 & IPv6 requests on port 443 with http2 enabled 12 | listen {{ PORT }}; 13 | listen {{ PORT_V6 }}; 14 | 15 | # General virtual host settings 16 | server_name {{ DOMAINS }}; 17 | server_tokens off; 18 | root {{ PATH }}; 19 | index index.html index.htm index.php; 20 | charset utf-8; 21 | 22 | # Enable serving of static gzip files as per: http://nginx.org/en/docs/http/ngx_http_gzip_static_module.html 23 | gzip_static on; 24 | 25 | # Enable server-side includes as per: http://nginx.org/en/docs/http/ngx_http_ssi_module.html 26 | ssi on; 27 | 28 | # Disable limits on the maximum allowed size of the client request body 29 | client_max_body_size 0; 30 | 31 | # Ban certain bots from crawling the site 32 | if ($limit_bots = 1) { 33 | return 403; 34 | } 35 | 36 | # 404 error handler 37 | error_page 404 /index.php?$query_string; 38 | 39 | # 301 Redirect URLs with trailing /'s as per https://webmasters.googleblog.com/2010/04/to-slash-or-not-to-slash.html 40 | rewrite ^/(.*)/$ /$1 permanent; 41 | 42 | # Change // -> / for all URLs, so it works for our php location block, too 43 | merge_slashes off; 44 | rewrite (.*)//+(.*) $1/$2 permanent; 45 | 46 | # Handle Do Not Track as per https://www.eff.org/dnt-policy 47 | location /.well-known/dnt-policy.txt { 48 | try_files /dnt-policy.txt /index.php?p=/dnt-policy.txt; 49 | } 50 | 51 | # For WordPress bots/users 52 | location ~ ^/(wp-login|wp-admin|wp-config|wp-content|wp-includes|wp-json|xmlrpc) { 53 | return 301 https://wordpress.com/wp-login.php; 54 | } 55 | 56 | # Access and error logging 57 | access_log off; 58 | error_log /var/log/nginx/{{ SITE }}-error.log error; 59 | # If you want error logging to go to SYSLOG (for services like Papertrailapp.com), uncomment the following: 60 | #error_log syslog:server=unix:/dev/log,facility=local7,tag=nginx,severity=error; 61 | 62 | # FORGE SSL (DO NOT REMOVE!) 63 | ssl_certificate /etc/nginx/ssl/{{ SITE }}/XXXXXX/server.crt; 64 | ssl_certificate_key /etc/nginx/ssl/{{ SITE }}/XXXXXX/server.key; 65 | 66 | # SSL/TLS configuration, with TLSv1.0 disabled because it is insecure; note that IE 8, 9 & 10 support 67 | # TLSv1.1, but it's not enabled by default clients using those browsers will not be able to connect 68 | ssl_protocols TLSv1.2 TLSv1.1; 69 | ssl_prefer_server_ciphers on; 70 | ssl_dhparam /etc/nginx/dhparams.pem; 71 | ssl_ciphers 'ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5'; 72 | ssl_buffer_size 4k; 73 | ssl_session_timeout 4h; 74 | ssl_session_cache shared:SSL:40m; 75 | ssl_stapling on; 76 | ssl_stapling_verify on; 77 | ssl_trusted_certificate /etc/nginx/ssl/lets-encrypt-x3-cross-signed.pem; 78 | 79 | # FORGE CONFIG (DO NOT REMOVE!) 80 | include forge-conf/{{ SITE }}/server/*; 81 | 82 | # Load configuration files from nginx-partials 83 | # For this to work, you must clone the repo into /home/forge via: 84 | # git clone https://github.com/nystudio107/nginx-craft.git /home/forge 85 | include /home/forge/nginx-craft/nginx-partials/*.conf; 86 | 87 | # Root directory location handler 88 | location / { 89 | try_files $uri/index.html $uri $uri/ /index.php?$query_string; 90 | } 91 | 92 | # Localized sites, hat tip to Johannes -- https://gist.github.com/johanneslamers/f6d2bc0d7435dca130fc 93 | 94 | # If you are creating a localized site as per: https://craftcms.com/docs/localization-guide 95 | # the directives here will help you handle the locale redirection so that requests will 96 | # be routed through the appropriate index.php wherein you set the `CRAFT_LOCALE` 97 | 98 | # Enable this by un-commenting it, and changing the language codes as appropriate 99 | # Add a new location @XXrewrites and location /XX/ block for each language that 100 | # you need to support 101 | 102 | #location @enrewrites { 103 | # rewrite ^/en/(.*)$ /en/index.php?$query_string? last; 104 | #} 105 | # 106 | #location /en/ { 107 | # try_files $uri $uri/ @enrewrites; 108 | #} 109 | 110 | # Craft-specific location handlers to ensure AdminCP requests route through index.php 111 | # If you change your `cpTrigger`, change it here as well 112 | location ^~ /admin { 113 | try_files $uri $uri/ /index.php?$query_string; 114 | } 115 | location ^~ /cpresources { 116 | try_files $uri $uri/ /index.php?$query_string; 117 | } 118 | 119 | # php-fpm configuration 120 | location ~ [^/]\.php(/|$) { 121 | try_files $uri $uri/ /index.php?$query_string; 122 | fastcgi_split_path_info ^(.+\.php)(/.+)$; 123 | # Change this to whatever version of php you are using 124 | fastcgi_pass {{ PROXY_PASS }}; 125 | fastcgi_index index.php; 126 | include fastcgi_params; 127 | fastcgi_param PATH_INFO $fastcgi_path_info; 128 | fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; 129 | fastcgi_param DOCUMENT_ROOT $realpath_root; 130 | fastcgi_param HTTP_PROXY ""; 131 | fastcgi_param HTTP_HOST {{ SITE }}; 132 | 133 | # Don't allow browser caching of dynamically generated content 134 | add_header Last-Modified $date_gmt; 135 | add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0"; 136 | if_modified_since off; 137 | expires off; 138 | etag off; 139 | # Load security.conf from nginx-partials again, because add_header used in this location 140 | # block removes any already added headers https://nginx.org/en/docs/http/ngx_http_headers_module.html 141 | include /home/forge/nginx-partials/security.conf; 142 | 143 | # Use Dotenvy to generate the .env variables as per: https://github.com/nystudio107/dotenvy 144 | # and then uncomment this line to include them: 145 | # include /home/forge/SOMEDOMAIN/.env_nginx.txt 146 | 147 | fastcgi_intercept_errors off; 148 | fastcgi_buffer_size 16k; 149 | fastcgi_buffers 4 16k; 150 | fastcgi_connect_timeout 300; 151 | fastcgi_send_timeout 300; 152 | fastcgi_read_timeout 300; 153 | } 154 | 155 | location ~ /\.ht { 156 | deny all; 157 | } 158 | } 159 | 160 | # FORGE CONFIG (DO NOT REMOVE!) 161 | include forge-conf/{{ SITE }}/after/*; 162 | -------------------------------------------------------------------------------- /nginx-partials/cache-busting.conf: -------------------------------------------------------------------------------- 1 | # HTML5 Boilerplate from - https://github.com/h5bp/server-configs-nginx 2 | 3 | # Built-in filename-based cache busting 4 | 5 | # This will route all requests for /css/style.20120716.css to /css/style.css 6 | # Read also this: github.com/h5bp/html5-boilerplate/wiki/cachebusting 7 | # This is not included by default, because it'd be better if you use the build 8 | # script to manage the file names. 9 | location ~* (.+)\.(?:\d+)\.(js|css|png|jpg|svg|jpeg|gif|webp)$ { 10 | etag off; 11 | expires 1M; 12 | access_log off; 13 | add_header Cache-Control "public"; 14 | try_files $uri $1.$2; 15 | } 16 | -------------------------------------------------------------------------------- /nginx-partials/compression.conf: -------------------------------------------------------------------------------- 1 | # HTML5 Boilerplate from - https://github.com/h5bp/server-configs-nginx 2 | 3 | # Compression 4 | 5 | # Enable Gzip compressed. 6 | gzip on; 7 | 8 | # Compression level (1-9). 9 | # 5 is a perfect compromise between size and cpu usage, offering about 10 | # 75% reduction for most ascii files (almost identical to level 9). 11 | gzip_comp_level 5; 12 | 13 | # Don't compress anything that's already small and unlikely to shrink much 14 | # if at all (the default is 20 bytes, which is bad as that usually leads to 15 | # larger files after gzipping). 16 | gzip_min_length 256; 17 | 18 | # Compress data even for clients that are connecting to us via proxies, 19 | # identified by the "Via" header (required for CloudFront). 20 | gzip_proxied any; 21 | 22 | # Tell proxies to cache both the gzipped and regular version of a resource 23 | # whenever the client's Accept-Encoding capabilities header varies; 24 | # Avoids the issue where a non-gzip capable client (which is extremely rare 25 | # today) would display gibberish if their proxy gave them the gzipped version. 26 | gzip_vary on; 27 | 28 | # Compress all output labeled with one of the following MIME-types. 29 | gzip_types 30 | application/atom+xml 31 | application/javascript 32 | application/json 33 | application/ld+json 34 | application/manifest+json 35 | application/rss+xml 36 | application/vnd.geo+json 37 | application/vnd.ms-fontobject 38 | application/x-font-ttf 39 | application/x-web-app-manifest+json 40 | application/xhtml+xml 41 | application/xml 42 | font/opentype 43 | image/bmp 44 | image/svg+xml 45 | image/x-icon 46 | text/cache-manifest 47 | text/css 48 | text/plain 49 | text/vcard 50 | text/vnd.rim.location.xloc 51 | text/vtt 52 | text/x-component 53 | text/x-cross-domain-policy; 54 | # text/html is always compressed by HttpGzipModule 55 | 56 | # This should be turned on if you are going to have pre-compressed copies (.gz) of 57 | # static files available. If not it should be left off as it will cause extra I/O 58 | # for the check. It is best if you enable this in a location{} block for 59 | # a specific directory, or on an individual server{} level. 60 | # gzip_static on; 61 | 62 | -------------------------------------------------------------------------------- /nginx-partials/expires.conf: -------------------------------------------------------------------------------- 1 | # HTML5 Boilerplate from - https://github.com/h5bp/server-configs-nginx 2 | 3 | # Expire rules for static content 4 | 5 | # No default expire rule. This config mirrors that of apache as outlined in the 6 | # html5-boilerplate .htaccess file. However, nginx applies rules by location, 7 | # the apache rules are defined by type. A consequence of this difference is that 8 | # if you use no file extension in the url and serve html, with apache you get an 9 | # expire time of 0s, with nginx you'd get an expire header of one month in the 10 | # future (if the default expire rule is 1 month). Therefore, do not use a 11 | # default expire rule with nginx unless your site is completely static 12 | 13 | # Media: images, icons, video, audio, HTC 14 | location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp3|mp4|ogg|ogv|webm|htc|webp)$ { 15 | # Uncomment these lines if you want to serve up a placeholder image for 404s 16 | # for static assets: 17 | # error_page 404 /img/placeholder-image.png; 18 | # try_files $uri =404; 19 | etag off; 20 | expires 1M; 21 | access_log off; 22 | # Route any 404s back through Craft 23 | try_files $uri /index.php?$query_string; 24 | # max-age=2592000 = 1 month in seconds, stale-while-revalidate=86400 = 1 day in seconds 25 | add_header Cache-Control "public, max-age=2592000, must-revalidate, stale-while-revalidate=86400"; 26 | } 27 | 28 | # CSS and Javascript 29 | location ~* \.(?:css|js)$ { 30 | etag off; 31 | expires 1y; 32 | access_log off; 33 | # Route any 404s back through Craft 34 | try_files $uri /index.php?$query_string; 35 | # max-age=31556952 = 1 year in seconds 36 | add_header Cache-Control "public, max-age=31556952, immutable"; 37 | } 38 | 39 | # WebFonts 40 | location ~* \.(?:ttf|ttc|otf|eot|woff|woff2)$ { 41 | etag off; 42 | add_header "Access-Control-Allow-Origin" "*"; 43 | expires 1M; 44 | access_log off; 45 | # Route any 404s back through Craft 46 | try_files $uri /index.php?$query_string; 47 | # max-age=2592000 = 1 month in seconds, stale-while-revalidate=86400 = 1 day in seconds 48 | add_header Cache-Control "public, max-age=2592000, must-revalidate, stale-while-revalidate=86400"; 49 | } 50 | -------------------------------------------------------------------------------- /nginx-partials/security.conf: -------------------------------------------------------------------------------- 1 | # Security headers via https://securityheaders.io 2 | # Submit your domain at https://hstspreload.org to be included in Chrome as HTTPS only. 3 | add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; 4 | add_header X-Frame-Options "SAMEORIGIN" always; 5 | add_header X-XSS-Protection "1; mode=block" always; 6 | add_header X-Content-Type-Options "nosniff" always; 7 | add_header Referrer-Policy "no-referrer-when-downgrade" always; 8 | # Opt out of Google Federated Learning of Cohorts ("FLoC"). ref:(https://amifloced.org/) 9 | add_header Permissions-Policy "interest-cohort=()" always; 10 | 11 | # Add Content-Security-Policy HTTP response header. Helps reduce XSS risks on 12 | # modern browsers by declaring what dynamic resources are allowed to load via a 13 | # HTTP Header. See https://content-security-policy.com/ 14 | # Uncomment this only if you know what you're doing; it will need tweaking 15 | #add_header Content-Security-Policy "default-src https: data: 'unsafe-inline' 'unsafe-eval'" always; 16 | -------------------------------------------------------------------------------- /sites-available/basic_localdev.com.conf: -------------------------------------------------------------------------------- 1 | # Nginx-Craft virtual host configuration file 2 | # @author nystudio107 3 | # @copyright Copyright (c) 2016 nystudio107 4 | # @link https://nystudio107.com/ 5 | # @package nginx-craft 6 | # @since 1.0.11 7 | # @license MIT 8 | 9 | # This is a BASIC Nginx config for Craft, suitable for use in for local development 10 | # DO NOT use this config in production, it is not performant. Instead, use the 11 | # somedomain.com.conf config 12 | server { 13 | # Listen for both IPv4 & IPv6 on port 80 14 | listen 80; 15 | listen [::]:80; 16 | 17 | # General virtual host settings 18 | server_name SOMEDOMAIN.com; 19 | server_tokens off; 20 | root "/var/www/SOMEDOMAIN/web"; 21 | index index.html index.htm index.php; 22 | charset utf-8; 23 | 24 | # Enable serving of static gzip files as per: http://nginx.org/en/docs/http/ngx_http_gzip_static_module.html 25 | gzip_static on; 26 | 27 | # Enable server-side includes as per: http://nginx.org/en/docs/http/ngx_http_ssi_module.html 28 | ssi on; 29 | 30 | # Disable limits on the maximum allowed size of the client request body 31 | client_max_body_size 0; 32 | 33 | # 404 error handler 34 | error_page 404 /index.php?$query_string; 35 | 36 | # Access and error logging 37 | access_log off; 38 | error_log /var/log/nginx/SOMEDOMAIN.com-error.log error; 39 | # If you want error logging to go to SYSLOG (for services like Papertrailapp.com), uncomment the following: 40 | #error_log syslog:server=unix:/dev/log,facility=local7,tag=nginx,severity=error; 41 | 42 | # Root directory location handler 43 | location / { 44 | try_files $uri/index.html $uri $uri/ /index.php?$query_string; 45 | } 46 | 47 | # php-fpm configuration 48 | location ~ [^/]\.php(/|$) { 49 | try_files $uri $uri/ /index.php?$query_string; 50 | fastcgi_split_path_info ^(.+\.php)(/.+)$; 51 | # Change this to whatever version of php you are using 52 | fastcgi_pass unix:/var/run/php/php7.1-fpm.sock; 53 | fastcgi_index index.php; 54 | include fastcgi_params; 55 | fastcgi_param PATH_INFO $fastcgi_path_info; 56 | fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; 57 | fastcgi_param DOCUMENT_ROOT $realpath_root; 58 | fastcgi_param HTTP_PROXY ""; 59 | fastcgi_param HTTP_HOST SOMEDOMAIN.com; 60 | 61 | # Use Dotenvy to generate the .env variables as per: https://github.com/nystudio107/dotenvy 62 | # and then uncomment this line to include them: 63 | # include /home/forge/SOMEDOMAIN/.env_nginx.txt 64 | 65 | # Don't allow browser caching of dynamically generated content 66 | add_header Last-Modified $date_gmt; 67 | add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0"; 68 | if_modified_since off; 69 | expires off; 70 | etag off; 71 | 72 | fastcgi_intercept_errors off; 73 | fastcgi_buffer_size 16k; 74 | fastcgi_buffers 4 16k; 75 | fastcgi_connect_timeout 300; 76 | fastcgi_send_timeout 300; 77 | fastcgi_read_timeout 300; 78 | } 79 | 80 | # Disable reading of Apache .htaccess files 81 | location ~ /\.ht { 82 | deny all; 83 | } 84 | 85 | # Misc settings 86 | sendfile off; 87 | } 88 | -------------------------------------------------------------------------------- /sites-available/somedomain.com.conf: -------------------------------------------------------------------------------- 1 | # Nginx-Craft virtual host configuration file 2 | # @author nystudio107 3 | # @copyright Copyright (c) 2016 nystudio107 4 | # @link https://nystudio107.com/ 5 | # @package nginx-craft 6 | # @since 1.0.0 7 | # @license MIT 8 | 9 | # Bots to ban via user agent 10 | map $http_user_agent $limit_bots { 11 | default 0; 12 | ~*(AhrefsBot|Baiduspider|PaperLiBot) 1; 13 | } 14 | 15 | # redirect http to https 16 | server { 17 | listen 80; 18 | listen [::]:80; 19 | server_name .SOMEDOMAIN.com; 20 | server_tokens off; 21 | return 301 https://SOMEDOMAIN.com$request_uri; 22 | } 23 | 24 | # Cannonical domain rewrite to remove www., etc. An SSL certificate is required to do the redirect 25 | server { 26 | # Listen for both IPv4 & IPv6 requests on port 443 with http2 enabled 27 | listen 443 ssl http2; 28 | listen [::]:443 ssl http2; 29 | server_name *.SOMEDOMAIN.com; 30 | server_tokens off; 31 | ssl_certificate /etc/letsencrypt/live/SOMEDOMAIN.com/fullchain.pem; 32 | ssl_certificate_key /etc/letsencrypt/live/SOMEDOMAIN.com/privkey.pem; 33 | return 301 https://SOMEDOMAIN.com$request_uri; 34 | } 35 | 36 | # Primary virtual host server block 37 | server { 38 | # Listen for both IPv4 & IPv6 requests on port 443 with http2 enabled 39 | listen 443 ssl http2; 40 | listen [::]:443 ssl http2; 41 | 42 | # General virtual host settings 43 | server_name SOMEDOMAIN.com; 44 | root "/var/www/SOMEDOMAIN/web"; 45 | index index.html index.htm index.php; 46 | charset utf-8; 47 | 48 | # Enable serving of static gzip files as per: http://nginx.org/en/docs/http/ngx_http_gzip_static_module.html 49 | gzip_static on; 50 | 51 | # Enable server-side includes as per: http://nginx.org/en/docs/http/ngx_http_ssi_module.html 52 | ssi on; 53 | 54 | # Disable limits on the maximum allowed size of the client request body 55 | client_max_body_size 0; 56 | 57 | # Ban certain bots from crawling the site 58 | if ($limit_bots = 1) { 59 | return 403; 60 | } 61 | 62 | # 404 error handler 63 | error_page 404 /index.php?$query_string; 64 | 65 | # 301 Redirect URLs with trailing /'s as per https://webmasters.googleblog.com/2010/04/to-slash-or-not-to-slash.html 66 | rewrite ^/(.*)/$ /$1 permanent; 67 | 68 | # Change // -> / for all URLs, so it works for our php location block, too 69 | merge_slashes off; 70 | rewrite (.*)//+(.*) $1/$2 permanent; 71 | 72 | # For WordPress bots/users 73 | location ~ ^/(wp-login|wp-admin|wp-config|wp-content|wp-includes|xmlrpc) { 74 | return 301 https://wordpress.com/wp-login.php; 75 | } 76 | 77 | # Handle Do Not Track as per https://www.eff.org/dnt-policy 78 | location /.well-known/dnt-policy.txt { 79 | try_files /dnt-policy.txt /index.php?p=/dnt-policy.txt; 80 | } 81 | 82 | # Access and error logging 83 | access_log off; 84 | error_log /var/log/nginx/SOMEDOMAIN.com-error.log error; 85 | # If you want error logging to go to SYSLOG (for services like Papertrailapp.com), uncomment the following: 86 | #error_log syslog:server=unix:/dev/log,facility=local7,tag=nginx,severity=error; 87 | 88 | # Don't send the nginx version number in error pages and Server header 89 | server_tokens off; 90 | 91 | # Load configuration files from nginx-partials 92 | include /etc/nginx/nginx-partials/*.conf; 93 | 94 | # Root directory location handler 95 | location / { 96 | try_files $uri/index.html $uri $uri/ /index.php?$query_string; 97 | } 98 | 99 | # Localized sites, hat tip to Johannes -- https://gist.github.com/johanneslamers/f6d2bc0d7435dca130fc 100 | 101 | # If you are creating a localized site as per: https://craftcms.com/docs/localization-guide 102 | # the directives here will help you handle the locale redirection so that requests will 103 | # be routed through the appropriate index.php wherein you set the `CRAFT_LOCALE` 104 | 105 | # Enable this by un-commenting it, and changing the language codes as appropriate 106 | # Add a new location @XXrewrites and location /XX/ block for each language that 107 | # you need to support 108 | 109 | #location @enrewrites { 110 | # rewrite ^/en/(.*)$ /en/index.php?$query_string? last; 111 | #} 112 | # 113 | #location /en/ { 114 | # try_files $uri $uri/ @enrewrites; 115 | #} 116 | 117 | # Craft-specific location handlers to ensure AdminCP requests route through index.php 118 | # If you change your `cpTrigger`, change it here as well 119 | location ^~ /admin { 120 | try_files $uri $uri/ /index.php?$query_string; 121 | } 122 | location ^~ /cpresources { 123 | try_files $uri $uri/ /index.php?$query_string; 124 | } 125 | 126 | # php-fpm configuration 127 | location ~ [^/]\.php(/|$) { 128 | try_files $uri $uri/ /index.php?$query_string; 129 | fastcgi_split_path_info ^(.+\.php)(/.+)$; 130 | # Change this to whatever version of php you are using 131 | fastcgi_pass unix:/var/run/php/php7.1-fpm.sock; 132 | fastcgi_index index.php; 133 | include fastcgi_params; 134 | fastcgi_param PATH_INFO $fastcgi_path_info; 135 | fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; 136 | fastcgi_param DOCUMENT_ROOT $realpath_root; 137 | fastcgi_param HTTP_PROXY ""; 138 | fastcgi_param HTTP_HOST SOMEDOMAIN.com; 139 | 140 | # Don't allow browser caching of dynamically generated content 141 | add_header Last-Modified $date_gmt; 142 | add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0"; 143 | if_modified_since off; 144 | expires off; 145 | etag off; 146 | # Load security.conf from nginx-partials again, because add_header used in this location 147 | # block removes any already added headers https://nginx.org/en/docs/http/ngx_http_headers_module.html 148 | include /etc/nginx/nginx-partials/security.conf; 149 | 150 | # Use Dotenvy to generate the .env variables as per: https://github.com/nystudio107/dotenvy 151 | # and then uncomment this line to include them: 152 | # include /home/forge/SOMEDOMAIN/.env_nginx.txt 153 | 154 | fastcgi_intercept_errors off; 155 | fastcgi_buffer_size 16k; 156 | fastcgi_buffers 4 16k; 157 | fastcgi_connect_timeout 300; 158 | fastcgi_send_timeout 300; 159 | fastcgi_read_timeout 300; 160 | } 161 | 162 | # SSL/TLS configuration, with TLSv1.0 disabled because it is insecure; note that IE 8, 9 & 10 support 163 | # TLSv1.1, but it's not enabled by default clients using those browsers will not be able to connect 164 | ssl_certificate /etc/letsencrypt/live/SOMEDOMAIN.com/fullchain.pem; 165 | ssl_certificate_key /etc/letsencrypt/live/SOMEDOMAIN.com/privkey.pem; 166 | ssl_protocols TLSv1.2 TLSv1.1; 167 | ssl_prefer_server_ciphers on; 168 | ssl_dhparam /etc/nginx/dhparams.pem; 169 | ssl_ciphers 'ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5'; 170 | ssl_buffer_size 4k; 171 | ssl_session_timeout 4h; 172 | ssl_session_cache shared:SSL:40m; 173 | ssl_stapling on; 174 | ssl_stapling_verify on; 175 | ssl_trusted_certificate /etc/nginx/ssl/lets-encrypt-x3-cross-signed.pem; 176 | 177 | # Disable reading of Apache .htaccess files 178 | location ~ /\.ht { 179 | deny all; 180 | } 181 | 182 | # Misc settings 183 | sendfile off; 184 | } 185 | --------------------------------------------------------------------------------