Add a sample nginx configuration file

Created on 26 January 2023, almost 2 years ago
Updated 24 May 2024, 6 months ago

Problem/Motivation

nginx is even more popular than Apache: https://w3techs.com/technologies/overview/web_server

We ship with .htaccess for Apache and web.config for IIS. We do not provide any sample configuration for nginx.

There is a recipe in the nginx wiki at https://www.nginx.com/resources/wiki/start/topics/recipes/drupal/ but it likely does not match our current set of regular expressions, header rules, etc, that we ship in .htaccess and web.config.

It is likely that we cannot provide a drop-in configuration file as the exact location of the php-fpm upstream depends on how php-fpm is installed, but we could provide a commented sample file that matches our current best practices for security.

Steps to reproduce

Proposed resolution

Add a sample configuration file for nginx that is equivalent to the rules in .htaccess/web.config.

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

πŸ“Œ Task
Status

Closed: duplicate

Version

10.1 ✨

Component
BaseΒ  β†’

Last updated 43 minutes ago

Created by

πŸ‡¬πŸ‡§United Kingdom longwave UK

Live updates comments and jobs are added and updated live.
  • Security improvements

    It makes Drupal less vulnerable to abuse or misuse. Note, this is the preferred tag, though the Security tag has a large body of issues tagged to it. Do NOT publicly disclose security vulnerabilities; contact the security team instead. Anyone (whether security team or not) can apply this tag to security improvements that do not directly present a vulnerability e.g. hardening an API to add filtering to reduce a common mistake in contributed modules.

Sign in to follow issues

Comments & Activities

  • Issue created by @longwave
  • πŸ‡ΊπŸ‡ΈUnited States effulgentsia

    +1. There's some prior art in https://github.com/uselagoon/lagoon-images/blob/main/images/nginx-drupal... and maybe other places on the internet as well.

  • πŸ‡ΊπŸ‡ΈUnited States tstermitz Colorado

    Drupal Media Sysetm and NGINX file upload problem, client_max_body_size

    Error Message: "client intended to send too large body"

    I recently rebuilt a new Digital Ocean server with LEMP, and installed Drupal 10 with success. (Relatively smooth sailing, I must say!).

    I had to work through a few issues that would be easier if there were some good Drupal-successful NGINX Conf files. I uses a couple of tutorials, and examples including the Drupal recipe listed above in the initial issue:

    https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on...
    https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-wit...

    A difficult issue I had was dealing with Media upload of files which failed silently. I was only able to identify the problem in the nginx error logs. Even with php.info max_file_size set to 100M, NGINX needs a "client_max_body_size: 100M;" directive. This needed to be placed in both the main Server block, and the PHP Location block.

    The requirement of adding the client_max_body_size directive is not very well documented as I discovered after searching with many google attempts.

    For the record here is my NGINX main server block:

    server {
    		listen 443 ssl;
    		listen [::]:443 ssl;
    
    		root /var/www/mydomain/web;
    
    		#server_name _;
    		server_name mydomain.com www.mydomain.com;
    
        index index.html index.htm index.nginx-debian.html index.php;
    
        client_max_body_size 100M;
    
        location / {
            try_files $uri $uri/ /index.php$is_args$args;
        }
    
        location = /favicon.ico { log_not_found off; access_log off; }
        location = /robots.txt { log_not_found off; access_log off; allow all; }
    
        location @rewrite {
          rewrite ^/(.*)$ /index.php?q=$1;
        }
    
        location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ {
            try_files $uri @rewrite;
            expires max;
            log_not_found off;
        }
    
        location ~ \.php$ {
           try_files $uri =404;
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include fastcgi_params;
            client_max_body_size 100M;
        }
    
        # Deny Access to all of Wordpress Front End files
            location ~* ^/(/wp-admin*|/wp-cron*|/wp-config*) {
            rewrite ^ / permanent;
        }
    
        ssl_certificate /etc/letsencrypt/live/mydomain.com/fullchain.pem; # managed by Certbot
        ssl_certificate_key /etc/letsencrypt/live/mydomain.com/privkey.pem; # managed by Certbot
    
    }
    
    server {
        if ($host = www.mydomain.com) {
            return 301 https://$host$request_uri;
        } # managed by Certbot
    
        if ($host = mydomain.com) {
            return 301 https://$host$request_uri;
        } # managed by Certbot
    
        listen 80;
        listen [::]:80;
        server_name mydomain.com www.mydomain.com;
        return 302 https://$server_name$request_uri;
    }
  • Status changed to Closed: duplicate almost 2 years ago
  • πŸ‡ΊπŸ‡ΈUnited States dww

    Great idea, but let's continue in the earlier issue where this is proposed. Thanks!

  • πŸ‡ΈπŸ‡ͺSweden fred6633

    Thanks!
    Do you have a code to get expiration to work with images that Drupal converts to webp, eg "filename.png.webp"? Below does not work.

    location ~* \.(css|gif|ico|jpeg|jpg|js|png|webp)$ {
            try_files $uri @rewrite;
            expires 1y;
            log_not_found off;
        }
    
  • πŸ‡ΈπŸ‡ͺSweden fred6633

    Below code breaks my site.

    location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ {
            try_files $uri @rewrite;
            expires max;
            log_not_found off;
        }
    

    If I replace "try_files $uri @rewrite;" with "try_files $uri /index.php?$query_string;" it works.

    Here is my code.

    location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
    try_files $uri /index.php?$query_string;
     expires 1y;
    log_not_found off;
    add_header Cache-Control "private,must-revalidate";
    }
Production build 0.71.5 2024