Needs work
Project:
Drupal core
Version:
main
Component:
documentation
Priority:
Normal
Category:
Feature request
Assigned:
Issue tags:
Reporter:
Created:
16 Jan 2018 at 21:24 UTC
Updated:
13 Sep 2026 at 17:45 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #2
gaurav.kapoor commentedComment #3
gaurav.kapoor commentedComment #4
cilefen commentedComment #5
sk33lz commentedIt looks like this example is based directly off the Nginx documentation found here, https://www.nginx.com/resources/wiki/start/topics/recipes/drupal/, which is a great start. This initial patch applies cleanly to 8.6.x, although we need to also update the
core/INSTALL.txtand create a newcore/INSTALL.nginx.txtfile with specific documentation regarding installing Drupal on Nginx that explains additional requirements this config requires such as installingphp-fpm.Comment #15
kunalgautam commentedPatch is successfully applied for version 10.1.x as well.
Comment #16
tstermitzDrupal Media Systemt and NGINX file upload problem, client_max_body_size
NGINX Error log Message: "client intended to send too large body"
I recently rebuilt a new Digital Ocean server with LEMP, and installed Drupal 10 with success.
Media files uploads were sometimes failing without a user visible error message.
To fix this I had to add a client_max_body_size in TWO locations in my conf file. This directive is not suggested in any of the common Drupal NGINX conf examples.
Here is my working nginx.conf file main Server block:
Comment #17
dwwMarked #3336659: Add a sample nginx configuration file duplicate, tagging this for Security improvements. +1 to doing this!
Thanks,
-Derek
Comment #19
andypostThat sounds like good material for help topic
Meantime there should be page like https://unit.nginx.org/howto/drupal/
So help topic can provide links to actual configuration maintained by upstream
Comment #20
neclimdulMaybe, but I think something in core is a better fit. Especially since the documentation could then be tied to specific versions instead of generalized documentation which ends up needing a sprinkling of "Do X for 7, Y for 8-10, Z for 10.1+" which ends up needing quite a bit of expertise to get an actual working config.
Another reason is #1014086: Stampedes and cold cache performance issues with css/js aggregation broke things and caused this to bubble back up. There wasn't a clear way to really communicate that within core and how sites should fix it. Honestly, unless you find the thread in slack, I'm not sure the possible fixes are even documented anywhere.
Additionally, I know the "official" nginx version has had problems in the past as well so would very much support providing something with best practices as captured by the Drupal community.
Comment #21
gaele commentedAddition for multisite installation in a subdirectory:
https://samwaters.net/nginx-drupal-9-multisite-and-path-based-urls/
In short:
Comment #22
o'briatThere are some config from the default htaccess that is not present in the patch, for example:
Since this patch is related to V11, all mention of Drupal 8 should be removed and the Change records Asset aggregation deprecations and additions, hook_js_alter()/hook_css_alter() changes should be added.
Comment #23
andypostNot sure it doable as one file as fastcgi backend needs definition too, but in case of https://unit.nginx.org/howto/drupal/ less configuration required
the file is missing
webp/avif should be added
Comment #24
o'briatI tried to port https://www.drupal.org/project/drupal/issues/3327115 as
If I understand it correctly apache match only the last part of the url/filepath (most right directory or filename) but nginx match the whole path.
So in order to deny all
composer.json,composer.lock,web.config,yarn.lockorpackage.json, I move this part to specific part of the regex:Could someone test and validate this modification?
As I don't understand what
Entries.*|Repository|Root|Tag|Templateis referring too, it would be nice to document this part.You could test it with
Comment #25
o'briatComment #26
ericgsmith commented@O'Briat I hit the same issue trying to update the regex with the change from #3327115 - your suggested config looks good to me - tested and now correctly seeing the expected 404 for composer.json, composer.lock, web.config, yarn.lock and package.json
Comment #27
ericgsmith commented@O'Briat there looks to be a typo in the first diff - the regex is different from the test command - I was looking at the regex in your test command.
Your correct that the regex from the
.htaccessfile matches filenames and the nginx config matches URIs.My colleague @Rosk0 and I built out some test cases for that regex https://regexr.com/7o2av
I essentially just replaced with
^with\/so that anywhere the.htaccessblock was looking for the start of the string it now looks for/Ah, I see you already opened MR - I missed that!I'm going to move the patch to an MR and address some of the comments above
Comment #28
ericgsmith commentedComment #30
ericgsmith commentedMade the following changes to the branch:
Adjust regex - see commit message for explanation and test
Applied changes for asset aggregation from https://www.drupal.org/node/2888767#nginx-php-fpm
Added additional file types suggested in #23
Updated
web.config,.htaccessandexample.nginxto block the newexample.nginxfileComment #31
o'briat@ericgsmith: Great, the
^should have been remove from my regexp^(\.(?!well-known).*, thanks for the review & fix.I didn't see it because it was already blocked by :
This block and the
location ~* ^/.well-known/could be safely removed, no ?By the way, all the 403 should be switch to 404 for security obfuscation.
I wonder if this file should not be put in place by the scaffold process?
Comment #32
johnpitcairn commentedOnly if Drupal does that in .htaccess for Apache as well. It's a misuse of the response code.
Sites are free to modify the defaults for their own purposes, if obfuscation is a requirement.
Comment #34
rosk0Back to NW for the comments on the MR.
Comment #35
solideogloria commentedHide patch as it's very outdated compared with the current recipe at https://www.nginx.com/resources/wiki/start/topics/recipes/drupal/
Comment #36
solideogloria commentedAs a note, you can also use this Nginx generator to help with getting an "A+" for security on SSL Labs.
https://ssl-config.mozilla.org/#server=nginx
Comment #37
c-logemannThe old nginx.com recipe is gone. Here is a copy in wayback machine:
https://web.archive.org/web/20240511055421/https://www.nginx.com/resourc...
It seems that it's now more important that we have a kind of official nginx example on d.o maybe not only in code.
Comment #38
andypostATM there's 2 main forks
- https://angie.software/en/
- https://freenginx.org/
Comment #39
solideogloria commentedIt looks like Nginx is moving towards Unit.
Here's the Nginx Unit recipe for Drupal: https://unit.nginx.org/howto/drupal/
I definitely like how readable it looks (prior Nginx was a challenge to read), though I have yet to give it a try.
Comment #40
poker10 commentedI think that Nginx Unit and Nginx + PHP-FPM are two different solutions and neither one is going away. If anything, we should probably still target classic Nginx + PHP-FPM config, which should be used by majority users these days (but I have not found relevant usage statistics for Nginx Unit).
Comment #41
solideogloria commentedHere's a post that compares the performance of PHP-FPM and Nginx Unit: Comparing PHP-FPM, NGINX Unit, and Laravel Octane
Comment #42
c-logemannThe official wiki repo is still available:
https://github.com/nginxinc/nginx-wiki/blob/master/source/start/topics/r...
Because there so many links to the nginx.com wiki I think it's a bad move to just shut it down.
Maybe they need a little bit help to configure a proper redirect.
@solideogloria I don't know if unit fit's all the things I do with nginx config for now.
@andypost Especially angie seems to be very interesting. I planned to try it ASAP.
Comment #43
solideogloria commentedMe neither. I don't use it yet (still using PHP-FPM); I'm just looking at what's available.
Comment #44
andypostI'm using following config ATM for Nginx Unit
Comment #45
fred6633 commentedThis code below breaks my site, if I enable aggregate css and javascript. It's a composer install with a web directory. Brave says too many redirects.
If I replace "try_files $uri @rewrite;" with "try_files $uri /index.php?$query_string;" it works.
I also have not been able to get this code to work with images that Drupal has converted to webp. Drupal creates a file "filename.png.webp". Drupal also sets "?itok=suhCNess", so the total name is "filename.png.webp?itok=suhCNess" But is has no effect to change the regex to "webp.*". The expires directive still does not work.
The approach that works for me in order to get the expires directive to work with converted webp images is described here: https://linux-audit.com/web/nginx-adding-expires-header-to-improve-caching/
Comment #46
solideogloria commentedThe nginx.org recipe was outdated compared to Drupal's .htaccess file. It's probably a good thing that Nginx.org removed it.
This one looks better, at least when it comes to the "Protect files and directories from prying eyes" section:
https://github.com/uselagoon/lagoon-images/blob/main/images/nginx-drupal...
Comment #47
solideogloria commentedAnother good one: https://github.com/wodby/nginx/blob/master/templates/presets/drupal11.co...
Comment #48
fred6633 commentedDon't forget this :
https://www.drupal.org/project/drupal/issues/3034643.
I had to add code under comment #15 in order to run update.php.
Comment #49
gregglesIf #2868079: Add a default Content-Security-Policy-header for svg files happens then that should get rolled into these recipes as well.
Comment #50
longwaveNow we have GitLab CI, we have the possibility of running some tests on nginx, which would be good to ensure both that things work and that we match the protections we provide for Apache.
Comment #51
andypostCurious how we can create image containing both nginx and apache
Comment #52
longwave@andypost install both in the container, run Apache by default, but in a specific CI job we kill it and run nginx instead before starting tests?
Comment #53
andypostYes, there's server-setup.sh script which can be improved, so only a backend question remains - fpm or what?!
Comment #54
gregglesThe issue summary says:
Does anyone have data about the level of popularity?
Comment #55
solideogloria commentedHere's Nginx compared with Apache. Nginx is more popular than Apache is. Note that this is in general, not only for Drupal sites.
https://trends.builtwith.com/Web-Server/nginx
https://trends.builtwith.com/Web-Server/Apache
Nginx:
Apache:
Comment #56
gregglesTIL - thanks @solideogloria! It would be ideal to know the number of Drupal sites among those, but I recognize that may not be possible.
Comment #57
solideogloria commentedFor BuiltWith, I think that might require a Pro account. I couldn't figure out how to do it.
Comment #58
alexgreyhead commentedApologies if this has already been covered here, or isn't appropriate to this discussion, but I'm fixing an issue where Nginx is no longer passing requests to generate aggregated JS files to Drupal in D10.
I think the following change is needed to my existing Nginx configuration which might also be applicable for other Nginx users:
Old config - in nginx.conf:
New config - note both are passed into the rewrite rule, but JS and CSS files have a different expiry header:
Hopefully helpful to someone other than me :o)
/A
Comment #59
solideogloria commented@alexgreyhead Your old config didn't match what the MR has. Does the MR's suggested config work for you?
https://git.drupalcode.org/project/drupal/-/merge_requests/5596/diffs#92...
Comment #60
holo96 commentedI think it is covered in change record
https://www.drupal.org/node/2888767
Comment #61
alexgreyhead commentedHi @solideogloria, would I be right in thinking the only key difference there is the line to route the request via index.php? (Ignoring the additional extensions) - old:
New:
/A
Comment #62
solideogloria commentedYes, that's the main difference.
I will also note that
jpg|jpegcan be shortened tojpe?gif desired.Comment #63
andrii-500 commentedHello everyone!
This code works fine for me on NGINX:
Comment #64
quietone commentedHi, in Drupal core changes are made on on 11.x (our main development branch) first, and are then back ported as needed according to the Core change policies. Thanks.
@andrii-500, this is assigned to you. Are you still working on it?
Comment #65
andrii-500 commentedThanks.
Comment #67
sirclickalot@andrii-500
Why are there two separate
server { }clauses with the first ending in...return 301 https://www.example.com$request_uri;?Comment #68
andrii-500 commentedThere are two `server` blocks because they serve two different purposes.
The first server block only handles the redirect from the non-www domain to the canonical domain:
`example.com → https://www.example.com`
It does not process the site itself (no root, PHP, or Drupal logic). It simply catches requests to `example.com` and immediately returns a 301 redirect to the main domain while preserving the request URI.
The second server block is the one that actually serves the website. It contains the root directive, PHP-FPM configuration, Drupal rewrites, and the rest of the NGINX logic required to run the site.
This separation is a common and recommended NGINX practice because it:
keeps the configuration clean and easy to understand
avoids unnecessary rewrite logic in the main server block
ensures a clear canonical domain for SEO
makes redirects faster since the server immediately returns a 301
In short:
server block 1 = redirect
server block 2 = actual website
Comment #69
ressaI wanted to install Varnish in front of an Apache server, when I was reminded that Nginx adds caching close to Varnish-level by default. So I searched for Drupal/Nginx-documentation, but found only old or fragmented examples ...
It would be really great to get Nginx set up for Drupal documented, so thank you everyone for working on it.
@longwave: Great suggestion about adding an Nginx test in GitLab CI, I have added it to the remaining tasks, and added usage statistics links as well in the Issue Summary.
We could also create a documentation page, which show the basic steps to set it up, perhaps under a new page at https://www.drupal.org/docs/getting-started/system-requirements/nginx-setup, and maybe even include how to set up Let’s Encrypt for Nginx, since HTTPS is required by everyone?
Comment #70
andrii-500 commentedI have updated the example.nginx file in the MR with a production-tested configuration. Changes include:
Merged security constraints for sensitive files (composer.json, .git, etc.).
Added support for webp and avif static assets.
Restricted PHP execution to core files only (index.php, update.php, etc.) for better security.
Note: The branch is currently behind main and has merge conflicts, so it will need a rebase, but the NGINX config rules are updated and ready for review.
Comment #71
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. The merge request has merge conflicts and cannot be merged. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.