Giter Club home page Giter Club logo

drupal-with-nginx's Introduction

Nginx configuration for running Drupal

Introduction

This is an example configuration from running Drupal using nginx. Which is a high-performance non-blocking HTTP server.

Nginx doesn't use a module like Apache does for PHP support. The Apache module approach simplifies a lot of things because what you have in reality is nothing less than a PHP engine running on top of the HTTP server.

Instead nginx uses FastCGI to proxy all requests for PHP processing to a php fastcgi daemon that is waiting for incoming requests and then handles the php file being requested.

Although the fcgi approach is more cumbersome to set up it provides a greater degree of control over which actions are permitted, hence greater security.

This configuration started life as a fork of yhager's configuration, tempered by omega8cc and Brian Mercer (dead link) configurations.

I've since then changed it substantially. Tried to remove as best as I can the traces of bad habits promoted by Apache's configuration logic. Namely the use of a .htaccess and what it entails in terms or reverse logic on the server configuration. I've incorporated tidbits and advices gotten, mostly, from the nginx mailing list and the nginx Wiki.

I'm in a hurry just show me how to install it

Jump immediately to the installation. I'll read up on all other stuff later.

Layout

The configuration comes in two flavors:

  1. Drupal 6.

  2. Drupal 7.

Furthermore there are two options for each configuration:

  1. A non drush aware option that uses wget/curl to run cron and updating the site using update.php, i.e., via a web interface.

  2. A drush aware flavor that runs cron and updates the site using drush.

    To get drush to run cron jobs the easiest way is to define your own site aliases. See the example aliases file example.aliases.drushrc.php that comes under the examples directory in the drush distribution.

    Example: You create the aliases for example.com and example.net, with aliases @excom and @exnet respectively.

    Your crontab should contain something like:

    COLUMNS=80
    DRUSH=/full/path/to/drush
    */50 * * * * $DRUSH @excom cron -q
    1 2 * * * $DRUSH @exnet cron -q
    

    This means that the cron job for example.com will be run every 50 minutes and the cron job for example.net will be run every day at 02:01 hours. Check the section 7 of the Drupal INSTALL.txt for further details about running cron.

    Note that the /path/to/drush is the path to the shell script wrapper that comes with drush not to to the drush.php script. If using drush.php then add php in front of the /path/to/drush.php.

Branching

The configuration has 3 main branches:

  1. A D7 branch if you're running Drupal 7 sites only on a given machine use this branch.

  2. A D6 branch if you're running Drupal 6 sites only on a given machine use this branch.

  3. A master branch if you're running both Drupal 6 and Drupal 7 sites on a given machine use this branch.

Escaped URIs

It happens that some sites have URIs that use reserved characters. In that case because we're not using any rewrite and since Nginx makes the exact matching of locations without escaping the reserved characters present in a URI we must use another mechanism for performing the escape. I've opted for the set_by_lua directive made available by the Embedded Lua module. This module provides a method ngx.escape_uri that encodes a URI.

## Drupal 7 site. We define a new variable that has the escaped
## URI as value.
set_by_lua $escaped_uri 'return ngx.escape_uri($uri)';

This means that each configuration has an escaped uri version.

Configuration Selection Algorithm

  1. I'm not using Boost:
  • On drupal 7 use the drupal.conf config in your vhost (server block): include apps/drupals/drupal.conf;.
  • On drupal 7 having to serve URIs that need to be escaped, e.g., that have + and/or ? then use the drupal_escaped.conf config in your vhost (server block): include apps/drupal/drupal_escaped.conf.
  • On drupal 6 use the drupal6.conf config in your vhost (server block): include apps/drupals/drupal6.conf;.
  • On drupal 6 if having to serve URIs that need to be escaped, e.g., that have + and/or ? then use the drupal6_escaped.conf config in your vhost (server block): include apps/drupal/drupal6_escaped.conf.
  1. I'm using Boost for caching on my drupal site.
  • On drupal 7 use the drupal_boost.conf config in your vhost (server block): include apps/drupal/drupal_boost.conf;.
  • On drupal 7 if having to serve URIs that need to be escaped, e.g., that have + and/or ? then use the drupal_boost_escaped.conf config in your vhost (server block): include apps/drupal/drupal_boost_escaped.conf.
  • On drupal 6 use the drupal_boost6.conf config in your vhost (server block): include apps/drupal/drupal_boost6.conf;.
  • On drupal 6 if having to serve URIs that need to be escaped, e.g., that have + and/or ? then use the drupal_boost6_escaped.conf config in your vhost (server block): include apps/drupal/drupal_boost6_escaped.conf.
  1. I'm not using drush for updating and running cron. Additionally you should also include the drupal_cron_update.conf config in your vhost (server block): include apps/drupal/drupal_cron_update.conf;

  2. I'm using drupal 8. Just use the drupal 7 configuration. The only thing that changes so far is the location of install.php.

    It's /core/install.php instead of install.php.

Boost and Drupal 6

The standard Drupal 6 core sets cookies also for anonymous users. Therefore the following map directive from map_cache.conf will result in the Boost generated pages not being served.

map $http_cookie $no_cache {
    default 0;
    ~SESS 1; # PHP session cookie
}

If you're using the standard Drupal 6 without no_anon then the cache bursting map directive is:

map $http_cookie $no_cache {
    default 0;
    ~DRUPAL_UID 1; # PHP session cookie
}

This is properly documented in map_cache.conf.

Drupal 6 Global Redirect and the 0 Rewrites Configuration

There's a setting that is enabled by default in globalredirect that removes the trailing slash in the URIs. That setting creates a redirect loop with the 0 rewrites config provided by sites-available/drupal.conf or sites-available/drupal_boost.conf if using Boost.

There are two ways to deal with that:

  1. Install the module nginx_fast_config that takes care of this setting removing it from the settings form at /admin/settings/globalredirect and presents a status line on the status page at /admin/reports/status. This module fixes the issues for you.

  2. Take care of the deslash setting yourself by disabling it at /admin/settings/globalredirect. Note that this is enabled by default.

This is strictly a drupal 6 issue.

General Features

  1. The use of two server directives to do the domain name rewriting, usually redirecting www.example.com to example.com or vice-versa. As recommended in nginx Wiki Pitfalls page.

  2. Clean URL support.

  3. Access control for cron.php. It can only be requested from a set of IPs addresses you specify. This is for the non drush aware version.

  4. Support for multisite.

  5. Support for the Boost module.

  6. Support for virtual hosts. The example.com.conf file.

  7. Support for Sitemaps RSS feeds.

  8. Support for the Filefield Nginx Progress module for the upload progress bar.

  9. Use of non-capturing regex for all directives that are not rewrites that need to use URI components.1

  10. IPv6 and IPv4 support.

  11. Support for private file serving in drupal.

  12. Support for hot link protection imagecache generated images.

  13. If using php-cgi with UNIX sockets in /tmp/ subdirectory with permissions 700, i.e., accessible only to the user running the process. You may consider the init script that I make available here on github that launches the PHP FastCGI daemon and spawns new instances as required. This is not needed if you're using php-fpm.

  14. End of the expensive 404s that Drupal usually handles when using Apache with the default .htaccess.

  15. Possibility of using Apache as a backend for dealing with PHP. Meaning using Nginx as reverse proxy.

  16. Advanced Help support.

  17. Advanced Aggregation support.

  18. Microcaching support for both anonymous and authenticated users.

  19. Support for escaped URIs, i.e., URIs that require percent encoding.

  20. ETag support. This requires a Nginx version greater or equal to 1.3.3.

  21. Support for drupal 8.

  22. Support for the file_force module.

Secure HTTP aka SSL/TLS support

  1. By default and since version 0.8.21 only SSLv3 and TLSv1 are supported. The anonymous Diffie-Hellman (ADH) key exchange and MD5 message autentication algorithms are not supported. They can be enabled explicitly but due to their insecure nature they're discouraged. The same goes for SSLv2.

  2. SSL/TLS shared cache for SSL session resume support of 10 MB. SSL session timeout is set to 10 minutes.

  3. Note that for session resumption to work the setting of the SSL socket as default, at least, is required. Meaning a listen directive like this:

    listen [::]:443 ssl default_server;

    This is so because session resumption takes place before any TLS extension is enabled, namely Server Name Indication. The ClientHello message requests a session ID from a given IP address (server). Therefore the default server setting is required.

    Another option, the one I've chosen here, is to move the ssl_session_cache directive to the http context setting. Of course the downside of this approach is that the ssl_session_cache settings are the same for all configured virtual hosts.

Security Features

  1. No direct access to PHP scripts. All PHP scripts, including index.php are acessed only internally.

  2. The use of a default configuration file to block all illegal Host HTTP header requests.

  3. Access control using HTTP Basic Auth for install.php and other Drupal sensitive files. The configuration expects a password file named .htpasswd-users in the top nginx configuration directory, usually /etc/nginx. I provide an empty file. This is also for the non drush aware version.

    If you're on Debian or any of its derivatives like Ubuntu you need either the thttpd-util or apache2-utils package installed.

    With thttpd-util create your password file by issuing:

    thtpasswd -c .htpasswd-users

    With apache2-utils create your password file by issuing:

    htpasswd -d -b -c .htpasswd-users

    You should delete this command from your shell history afterwards with history -d <command number> or alternatively omit the -b switch, then you'll be prompted for the password.

    This creates the file (there's a -c switch). For adding additional users omit the -c.

    If you're on Debian or any of its derivatives like Ubuntu you need the apache2-utils package installed. Then create your password file by issuing:

    htpasswd -d -b -c .htpasswd-users <user> <password>
    

    You should delete this command from your shell history afterwards with history -d <command number> or alternatively omit the -b switch, then you'll be prompted for the password.

    This creates the file (there's a -c switch). For adding additional users omit the -c.

    Of course you can rename the password file to whatever you want, then accordingly change its name in drupal_boost.conf.

  4. Support for X-Frame-Options HTTP header to avoid Clickjacking attacks.

  5. Support for X-Content-Options for avoiding MIME type deviation from the declared Content-Type.

  6. Protection of the upload directory. You can try to bypass the UNIX file utility or the PHP Fileinfo extension and upload a fake jpeg:

    echo -e "\xff\xd8\xff\xe0\n<?php echo 'hello'; ?>" > test.jpg
    

    If you run php test.jpg you get 'hello'. The fact is that all files with php extension are either matched by a particular location, as is the case for xmlrpc.php, update.php and install.php or match the last directive of the configuration:

    location ~* ^.+\.php$ {
      return 404; 
    }
    

    Returning a 404 (Not Found) for every PHP file not matched by all the previous locations.

    Note that index.php is accessed only indirectly, meaning it always from within the Nginx config. You cannot access it directly from outside.

  7. Use of Strict Transport Security for enhanced security. It forces during the specified period for the configured domain to be contacted only over HTTPS. Requires a modern browser to be of use, i.e., Chrome/Chromium, Firefox 4 or Firefox with NoScript.

  8. DoS prevention with a low number of connections by client allowed: 32. This number can be adjusted as you see fit.

  9. The Drupal specific headers like X-Drupal-Cache provided by pressflow or the X-Generator header that Drupal 7 sets are both hidden.

  10. Limitation of allowed HTTP methods. Out of the box only GET, HEAD and POSTare allowed.

  11. Protection of the /admin URIs with Basic Auth.

Private file handling

This config assumes that private files are stored under a directory named private. I suggest sites/default/files/private or sites/<sitename>/files/private but can be anywhere inside the site root as long as you keep the top level directory name private. If you want to have a different name for the top level then replace in the location ~* private in drupal.conf and/or drupal7.conf the name of your private files top directory.

Example: Calling the top level private files directory protected instead of private.

   location ^~ /sites/default/files/protected {
     internal;
   }

Now any attempt to access the files under this directory directly will return a 404.

Note that this practice it's not what's usually recommended. The usual practice involves setting up a directory outside of files directory and giving write permissions to the web server user. While that might be a simple alternative in the sense that doesn't require to tweak the web server configuration, I think it to be less advisable, in the sense that now there's another directory that is writable by the server.

I prefer to use a directory under files, which is the only one that is writable by the web server, and use the above location (protected or private) to block access by the client to it.

Also bear in mind that the above configuration stanza is for a drupal 7 or a drupal 6 site not relying on purl. For sites that use it, e.g., sites/products based on spaces like OpenAtrium or ManagingNews require a regex based location, i.e.:

   location ~* /sites/default/files/protected {
     internal;
   }

in order to work properly.

Fast Private File Transfer

Nginx implements Lighty X-Sendfile using the header: X-Accel-Redirect.

This allows fast private file transfers. I've developed a module tailored for Nginx: nginx_accel_redirect.

Connections per client and DoS Mitigation

The connection zone defined, called arbeit allows for 32 connections to be established for each client. That seems to me to be a reasonable number. It could happen that you have a setup with lots of CDNs (see this issue) or extensive domain sharding and the number of allowed connections by client can be greater than 32, specially when using Nginx as a reverse proxy.

It may happen that 32 is not enough and you start getting a lot of 503 Service Unavailable status codes as a reply from the server. In that case tweak the value of limit_conn until you have a working setup. This number must be as small as possible as a way to mitigate the potential for DoS attacks.

ETag support

ETags are an additional facility to help caching of static assets on the web. Usually based on the file modification time a hash is generated. The hash is sent as an additional header to the client. Here's an example of a request reply with an ETag:

   HTTP/1.1 200 OK
   Server: nginx
   Date: Mon, 17 Sep 2012 17:46:36 GMT
   Content-Type: image/png
   Content-Length: 5399
   Last-Modified: Wed, 02 May 2012 16:36:16 GMT
   Connection: keep-alive
   Keep-Alive: timeout=10
   ETag: "4fa16280-1517"
   Expires: Thu, 01 Jan 1970 00:00:01 GMT
   Cache-Control: no-cache
   Accept-Ranges: bytes

Image hotlinking protection

Imagecache generated images can be expensive to generate. In those cases providing protection against hotlinking is a must.

To make use of that uncomment the proper line on the /imagecache/ location that includes the sites-available/hotlinking_protection.conf file.

The protection is based on the Nginx referer module. You must specify the hosts that are allowed to access the images. The hostnames can use wildcards or use regexes.

HTTP allowed methods made to measure

For a standard drupal install there's no need for any method besides GET, HEAD and POST. The allowed methods are enumerated in the file map_block_http_methods.conf.

If your site uses/provide web services then you must add the methods you need to the list. For example if you want to allow PUT then do:

   map $request_method $not_allowed_method {
       default 1;
       GET 0;
       HEAD 0;
       POST 0;
       PUT 0;
   }

Note that this enables PUT for all locations and clients. If you need a finer control then use the limit_except directive and enumerate the client IPs that are allowed to use the extra methods like PUT.

Protection of the /admin URIs using Basic Auth

Just uncomment the line that includes the apps/drupal/admin_basic_auth.conf file. Now whenever you got to a /admin URI the server will prompt you for a username/password pair. Note that by default this config provides no username/password values for the .htpasswd-users file. This is to avoid the creeping of laziness and that 80% of the sites that have the /admin URIs protected have the same username/password.

Note that this is much more effective if at least all your logged in traffic goes over SSL (HTTPS).

Multisite support

Drupal multisite is supported out of the box with this configuration you just need to configure the server_name directive with all the sites that your Drupal installation serves.

For example your Drupal installation serves the sites foo.example.com, bar.example.net and baz.foo.example.org. Then you need to configure your vhost like this:

   server_name foo.example.com bar.example.net baz.foo.example.org;

Note that Nginx allows for the server name to be either a regex or a wildcard expression. See this to delve deeper into the multiple ways to define server names.

This is the most simple multisite setup. You can have different vhosts. I find that it sorts of defeats the purpose to have to deal with different vhosts for a multisite. You get all the advantages of a set of separate sites in terms of web server configuration, while getting no advantage in terms of code separation.

As very wise man once said: everyhting in life is a matter of taste. I don't like multisite. It's something that might be handy for dealing with small sites, but quickly becomes unmaintanable with large sites. Code separation is a good thing. You've been warned.

Nginx as a Reverse Proxy: Proxying to Apache for PHP

If you absolutely need to use the rather bad habit of deploying web apps relying on .htaccess, or you just want to use Nginx as a reverse proxy. The config allows you to do so. Note that this provides some benefits over using only Apache, since Nginx is much faster than Apache. Not only due to its architecture but also to using buffering for handling upstream replies. Furthermore you can use the proxy cache and/or use Nginx as a load balancer.

Static index.html file

The / location is a fallback location, meaning that after trying all other, more specific locations, Nginx, will return here.

Since there's a try_files $uri directive within @cache, if using Boost, or @drupal, or index.php?q=$uri&$args otherwise, as fallback it will return a 404 if no file is found. Even if you have an index.html file at the root. That is for a request URI of /. It will work however with /index.html, since that's the argument of the try_files directive.

There's several possible ways to fix that. Be with nested locations inside location / or with an aditional try_files $uri/index.html.

The one I opted for is instead making use of the error_page directive. There's an exact location / that issues a 200 code and serves /index.html when a 404 is returned.

Gzipped static files

Nginx has a directive gzip_static that when set to on in a given location makes it always search for a file ending in .gz before trying to serve the file. This involves making an additional stat() call. It isn't generally used. So you can save that additional call for extracting even more speed from Nginx.

Example if we're trying to serve foobar.html in a certain location if gzip_static is set to on, then Nginx will make a stat() call to try to serve foobar.html.gz first.

Exceptions to that rule are rare in the drupal world. The most common occasion to found such a practice is when using Boost. Since there's a configuration option to make it create gzipped HTML pages in its cache.

By default on the Boost cache locations we have:

 gzip_static on;

If you have other locations, besides the Boost cache, that have gzipped files to be served you have to set:

 gzip_static on;

Note that in order to use gzip_static the ngx_http_gzip_static_module must be enabled. Check your nginx with nginx -V to see if the module is enabled.

Microcaching

Introduction

Microcaching is a caching concept that takes simple is better approach. Meaning we don't care about content expiration because the cache valid time is small enough for that not to be an issue. In this config we set it to 15 seconds. You can tune all cache parameters to your liking. Check the microcache_fcgi.conf or microcache_proxy.conf for anonymous users cache and microcache_fcgi_auth.conf or microcache_proxy_auth.conf for authenticated users cache.

Microcaching and Drupal

You can implement a microcaching strategy on drupal using cache_warmer. Tune the many options of that drush command to fit your site traffic pattern.

Anonymous and Authenticated users microcaching

This configuration supports both anonymous and authenticated users caching. You should enable one and only one. The authenticated user cache also supports anonymous users.

By default on both drupal 6 and drupal 7 the anonymous user microcache is enabled. If you want to use the authenticated user microcache instead comment out the line:

  1. include apps/drupal/microcache_fcgi.conf if using the FCGI microcache (when proxying to FCGI).

  2. include apps/drupal/microcache_proxy.conf if using the proxy cache (proxying to Apache or other PHP handler).

and uncomment:

  1. include apps/drupal/microcache_fcgi_auth.conf if using the FCGI microcache (when proxying to FCGI).

  2. include apps/drupal/microcache_proxy_auth.conf if using the proxy cache (proxying to Apache or other PHP handler).

You're set to go.

Boost and authenticated user microcaching

When using Boost you can use the authenticated user microcache. It will give you an additional layer of caching.

This is enabled by default. Comment out the include sites-available/microcache_fcgi_auth.conf or include sites-available/microcache_proxy_auth.conf line if you don't want to use microcaching at all with Boost.

Microcaching for authenticated users under the hood

The way microcaching for authentitcated is implemented uses a $cache_uid variable that is set on map_cache.conf.

  • anonymous users get a $cache_uid value of nil.

  • authenticated users get a $cache_uid value that is the session id. Note that the named capture that grabs the session ID assumes that you're using the default setting in terms of what drupal calls the session cookie. Hence it starts with SESS. If this isn't the case just remove the string SESS from the regex.

    See drupal_settings_initialize() for drupal 7 or conf_init() for drupal 6 for further information.

Useful scripts for working with Nginx cache

Here's two useful scripts for working with the Nginx cache:

  1. nginx cache inspector allows you to inspect the cache files.

  2. nginx cache purge allows you to purge and item or set of items from the Nginx cache.

IPv6 and IPv4

The configuration of the example vhosts uses separate sockets for IPv6 and IPv4. This way is simpler for those not (yet) having IPv6 support to disable it by commenting out the listen directive with the ipv6only=on parameter.

Note that the IPv6 address uses an IP stolen from the IPv6 Wikipedia page. You must replace the indicated address by your address.

For Nginx versions greater or equal than 1.3.4 IPv6 and IPv4 sockets are separate by default.

Note also that socket options like ipv6only=on can only be specified once. Hence the use of different IPv6 addresses for the server block that redirects from www to the base domain in both HTTP and HTTPS servers.

Installation

  1. Move the old /etc/nginx directory to /etc/nginx.old.

  2. Clone the git repository from github:

    git clone https://github.com/perusio/drupal-with-nginx.git /etc/nginx
    

    If you want to use only the Drupal specific version configuration you must do one of the checkouts below:

  • For the D7 branch (running only D7 sites on the same server):

        git checkout D7
    
  • For the D6 branch (running only D6 sites on the same server):

        git checkout D6      
    
  1. Edit the sites-available/example.com.conf configuration file to suit your requirements. Namely replacing example.com with your domain.

  2. Setup the PHP handling method. It can be:

  • Upstream HTTP server like Apache with mod_php. To use this method comment out the include upstream_phpcgi.conf; line in nginx.conf and uncomment the lines:

     include reverse_proxy.conf;
     include upstream_phpapache.conf;
    

    Now you must set the proper address and port for your backend(s) in the upstream_phpapache.conf. By default it assumes the loopback 127.0.0.1 interface on port 8080. Adjust accordingly to reflect your setup.

    Comment out all fastcgi_pass directives in either drupal_boost.conf or drupal_boost_drush.conf, depending which config layout you're using. Uncomment out all the proxy_pass directives. They have a comment around them, stating these instructions.

  • FastCGI process using php-cgi. In this case an init script is required. This is how the server is configured out of the box. It uses UNIX sockets. You can use TCP sockets if you prefer.

  • PHP FPM, this requires you to configure your fpm setup, in Debian/Ubuntu this is done in the /etc/php5/fpm directory.

    Look here for an example configuration of php-fpm.

    Check that the socket is properly created and is listening. This can be done with netstat, like this for UNIX sockets:

      netstat --unix -l
    

    And like this for TCP sockets:

      netstat -t -l
    

    or sudo netstat -t -l -p

    It should display the PHP CGI socket.

    Note that the default socket type is UNIX and the config assumes it to be listening on unix:/tmp/php-cgi/php-cgi.socket, if using the php-cgi, or in unix:/var/run/php-fpm.sock using php-fpm and that you should change to reflect your setup by editing upstream_phpcgi.conf.

  1. Create the /etc/nginx/sites-enabled directory and enable the virtual host using one of the methods described below.

    Note that if you're using the nginx_ensite script described below it creates the /etc/nginx/sites-enabled directory if it doesn't exist the first time you run it for enabling a site.

  2. Reload Nginx:

    /etc/init.d/nginx reload
    
  3. Check that your site is working using your browser.

  4. Remove the /etc/nginx.old directory.

  5. Done.

Enabling and Disabling Virtual Hosts

I've created a shell script nginx_ensite that lives here on github for quick enabling and disabling of virtual hosts.

If you're not using that script then you have to manually create the symlinks from sites-enabled to sites-available. Only the virtual hosts configured in sites-enabled will be available for Nginx to serve.

Troubleshooting

If by any reason you have some kind of error, please get a debug log and paste it in a Gist and open an issue on the github issue queue for the module.

Acessing the php-fpm status and ping pages

You can get the status and a ping pages for the running instance of php-fpm. There's a php_fpm_status.conf file with the configuration for both features.

  • the status page at /fpm-status;

  • the ping page at /ping.

For obvious reasons these pages are acessed only from a given set of IP addresses. In the suggested configuration only from localhost and non-routable IPs of the 192.168.1.0 network.

The allowed hosts are defined in a geo block in file php_fpm_status_allowed_hosts.conf. You should edit the predefined IP addresses to suit your setup.

To enable the status and ping pages uncomment the line in the example.com.conf virtual host configuration file.

Getting the latest Nginx packaged for Debian or Ubuntu

I maintain a debian repository with the latest version of Nginx. This is packaged for Debian unstable or testing. The instructions for using the repository are presented on this page.

It may work or not on Ubuntu. Since Ubuntu seems to appreciate more finding semi-witty names for their releases instead of making clear what's the status of the software included, meaning. Is it stable? Is it testing? Is it unstable? The package may work with your currently installed environment or not. I don't have the faintest idea which release to advise. So you're on your own. Generally the APT machinery will sort out for you any dependencies issues that might exist.

Ad and Additional modules support

The config is quite tight in the sense that if you have something that is not contemplated in the exact match locations, /index.php, /install.php, etc, and you try to make it work it will fail. Some Drupal modules like ad provide a PHP script. This script needs to be invoked. In the case of the ad module you must add the following location block:

   location = /sites/all/modules/ad/serve.php {
      fastcgi_pass phpcgi;
    }

Of course this assumes that you installed the ad module such that is usable for all sites. To make it usable when targeting a single site, e.g., mysite.com, insert instead:

   location = /sites/mysite.com/modules/ad/serve.php {
      fastcgi_pass phpcgi;
   }   
   
Proceed similarly for other modules requiring the usage of PHP
scripts like `ad`.   

On groups.drupal.org

There's a nginx groups.drupal.org group for sharing and learning more about using nginx with Drupal.

Monitoring nginx

I use Monit for supervising the nginx daemon. Here's my configuration for nginx.

Caveat emptor

You should always test the configuration with nginx -t to see if everything is correct. Only after a successful should you reload nginx. On Debian and any of its derivatives you can also test the configuration by invoking the init script as: /etc/init.d/nginx testconfig.

My other nginx configs on github

Securing your PHP configuration

I have created a small shell script that parses your php.ini and sets a sane environment, be it for development or production settings.

Grab it here.

TODO

  • Improve the documentation. It's too vague and needs to be more elaborate.

  • Add AgrCache support. (D7)

Acknowledgments

The great bunch at the Nginx group on groups.drupal.org. They've helped me sort out the snafus on this config and offered insights on how to improve it.

Thanks to Richard for setting me down the path of image hotlinking protection.

drupal-with-nginx's People

Contributors

calipzo avatar colans avatar deminy avatar estum avatar grooverdan avatar iryston avatar javdl avatar kkomelin avatar perusio avatar pprishchepa avatar redcrate avatar ruzniki avatar smerrill avatar smoneyan avatar tempo22 avatar visualfox avatar wismoyo avatar yveslaroche avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

drupal-with-nginx's Issues

images still showing in access log

I have the following location with access_log off in drupal_boost6.conf, however jpg / png images are still showing in the logs:

location ~* ^.+\.(?:css|js|jpe?g|gif|htc|jpg|ico|png|html)$ {
    access_log off;
    expires 30d;
    ## No need to bleed constant updates. Send the all shebang in one
    ## fell swoop.
    tcp_nodelay off;
    ## Set the OS file cache.
    open_file_cache max=3000 inactive=120s;
    open_file_cache_valid 45s;
    open_file_cache_min_uses 2;
    open_file_cache_errors off;
}

LOG:

x.x.x.x - - [08/Mar/2012:11:46:38 +0000] "GET /sites/default/files/imagecache/ts_homepage_secondary_story/image.png HTTP/1.1" 200 21017 "http:///" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11"

x.x.x.x - - [08/Mar/2012:12:52:26 +0000] "GET /sites/default/files/imagecache/ts_homepage_secondary_story/image.jpg HTTP/1.1" 200 3989 "http:///" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11"

Including missing file on nginx.conf

On line 136 of nginx.conf, you are including include fastcgi_cache_zone.conf;

This file doesn't exist.

Is this meant to include fastcgi_microcache_zone.conf ?

Limit Available HTTP Methods

As a follow up to the hot linking protection of our Drupal installations I think it’s also wise to limit the supported HTTP Methods to the ones that we really need and refuse the rest completely. This time I directly have a map for you.

blacklist.conf

## Add here all allowed request methods.
map $request_method $bad_request {
    default 1;
    ~(?i)(GET|HEAD|POST) 0;
}

example.conf

    ## Only allow certain requests.
    if ($bad_request) {
        return 444;
    }

Regards
Richard

fastcgi_params ending ;

Please, change in fastcgi_params
fastcgi_param HTTPS $https
to
fastcgi_param HTTPS $https;

drupal_boost6.conf "try_files" directive is duplicate

Hi,

There is a problem in drupal_boost6.conf.
The line:
try_files /cache/normal/$host${uri}${args}.html /cache/perm/$host${uri}.css /cache/perm/$host${uri}_.js /cache/$host/0$uri.html /cache/$host/0${uri}/index.html /index.php?q=$no_slash_uri&$args;

Appears twice (1 for the "location = / " and another for the "location @cache" and nginx show the error: "try_files" directive is duplicate.

Any help?

Thanks

minor problems with proxy to apache

Hello,

Thanks for adding support for proxying to apache. I've tested the config with nginx-0.8.54 and found a few minor bugs.

  • in nginx.conf, a ; is missing in #include reverse_proxy.conf
  • in upstream_phpapache.conf, the server line shouldn't have http://
  • in drupal_boost.conf & drupal_boost_drush.conf, fastcgi_pass line needs to be changed to proxy_pass http://phpapache;

Other than that, it's working great!!

Ampersand in URL causes truncated URL

Using the latest version of drupal-with-nginx and the latest dev version of nginx, a url like the following does not make it through to drupal correctly:
http://www.example.com/path/to/url & clipped

This is true if the URL is escaped or raw.

To test this, create a path in drupal that simply echos the argument, like

function test_menu() {
  return array(
    'test/%' => array(
      'page callback'     => 'echo_this',
      'page arguments'    => array(1),
      'access arguments'  => TRUE,
    );
}

function echo_this($arg) {
  return "$arg";
}

For a URL like http://www.example.com/test/foobarbaz
the result is: foobarbaz

For a URL like http://www.example.com/test/foo&barbaz
the result is: foo

I believe this is due to a problem with the rewrite rule, but I'm new to nginx and haven't been able to figure out the exact problem.

I'm using fastcgi with a unix socket, and have only made the necessary modifications to the conf files as noted in the installation notes.

Please note that the same drupal code works under Apache, so I'm fairly certain this is an nginx config issue.

Disable image hotlinking

Hi perusio!

Just implemented this in my own website and thought you might be interested to include this as an optional (or standard) part of your nginx configuration. It works with Imagecache and AJAX field UI of Drupal 7. I only tested it with a Drupal 7 installation, Drupal 6 might need some adoptions.

blacklist-hotlinking.conf

### This file implements a blacklist for certain referrers. It's used to
### prevent hotlinking of your images. Must be included in server context.


## Initialize our nested if variable. For more information on this
## technique have a look at: http://wiki.nginx.org/RewriteMultiCondExample
set $invalid "";

## If the file exists set our variable to 1.
if (-f $request_filename) {
    set $invalid 1;
}

## Add here all valid referrers, use the RegEx pattern
## ~(mydomain.com) do include all possible subdomains and the
## pattern ~(mydomain.) to include all possible subdomains and
## TLDs as well. You can separate many hosts with a pipe.
## ~(mydomain.com|google.|bing.|yahoo.)
##
## More info at:
## http://www.cyberciti.biz/tips/linux-unix-bsd-nginx-webserver-security.html
## http://linuxsysadminblog.com/2009/08/using-wildcards-in-nginx-valid_referers/
valid_referers none blocked server_names ~(example.com|google.|bing.|yahoo.);

## Check the actual referer and if it's invalid set our variable to
## the previously set variable + 1.
if ($invalid_referer) {
    set $invalid "${invalid}1";
}

## If the file exists and we have an invalid referer somebody is
## hotlinking our image - prevent it!
if ($invalid = 11) {
    #return 444;
    return 403;
    ## It's wise to redirect to an image hosting service, so your
    ## bandwith won't be used to serve this picture.
    #rewrite ^.*\.(gif|jpe?g|png)$ http://example-imagehoster.com/hotlinking.jpg last;
}

static-files.conf

### This template can be included in location contexts where static
### files are going to be served.

access_log off;
expires max;
## No need to bleed constant updates. Send the all shebang in one fell
## swoop.
tcp_nodelay off;
## Set the OS file cache.
open_file_cache max=3000 inactive=120s;
open_file_cache_valid 45s;
open_file_cache_min_uses 2;
open_file_cache_errors off;

Implementation example in sites-available/drupal.conf

    ## We allow hotlinking of our banners!
    location ~* /files/banner/ {
        ## Include configuration for static files.
        include static-files.conf;
    }

    ## Drupal 7 generated image handling, i.e., imagecache in core. See:
    ## https://drupal.org/node/371374.
    location ~* /files/styles/ {
        ## Prevent hotlinking!
        include blacklist-hotlinking.conf;

        ## Include configuration for static files.
        include static-files.conf;

        ## Delegate to Drupal if file doesn't exist for Imagecache
        ## generation of the image.
        try_files $uri @drupal;
    }

    ## All static files will be served directly.
    location ~* ^.+\.(?:css|js|jpe?g|gif|ico|png|html|xml)$ {
        ## Prevent hotlinking!
        include blacklist-hotlinking.conf;

        ## Include configuration for static files.
        include static-files.conf;
    }

By default I allow no referers (valid users might not submit one), blocked (if users try to to stay anonymous) our server names, our domain including all subdomains and of course the big search engines including all subdomains and TLDs.

Hope you like it and keep up the great work!

Regards
Richard

404 with boost config

try_files /cache/normal/$host/_${args}.html /cache/perm/$host/_.css /cache/perm/$host/_.js /cache/$host/0/.html /cache/$host/0/index.html /index.php?q=$no_slash_uri&$args /index.html;

The homepage only works when I change the final /index.html to /index.php

php-fpm crashing every few day

Good Morning,

I understand this is probably not related to this config, however you seem to be a wealthy source of information on nginx / php-fpm and drupal. Perhaps you have seen this problem before...

Every few days at exactly the same times 08:04, 20:04 (approx.) The php-fpm children of all of my web servers increase dramatically until the max_children is reached, the servers then come under heavy load and syslog show kernel messages related to oomkiller. php-fpm then appears to crash/restart all processes and the site then loads fine again for another few days.

This cycle repeats every few days at the same time, it also occurs whether I set max_children to 10, 50, 100 etc. what ever the value, they spawn more until php-fpm crashes, some kind of memory leak or infinite loop?

Site traffic is also minimal at these times and the site can handle 200% more traffic at other peak times without problems.

Versions:
Ubuntu 11.10 - 3.0.0-12-server x86_64
nginx 1.0.5-1
php 5.3 5.3.6-13ubuntu3.3
drupal6

Any ideas would be well appreciated.

Regards,

Alun.

Drupal 6 boost config is broken

Hi,

I think is really broken.

First: there is no link to fastcgi_drupal.conf;
In other configs there is: include fastcgi_drupal.conf, but not in drupal_boost6.conf. So, it doesn't works by default.

Second: this line looks like that:
## Restrict access to the strictly necessary PHP files. Reducing the
## scope for exploits. Handling of PHP code and the Drupal event loop.
location = /index.php {
...

And it caused WSOD (even if I comment "internal").

In drupal_boost.conf it looks:
## Restrict access to the strictly necessary PHP files. Reducing the
## scope for exploits. Handling of PHP code and the Drupal event loop.
location @drupal {
## Include the FastCGI config.
include fastcgi_drupal.conf;

When I change index.php to something else (like a index.php?q=$uri&$args) it works fine.

In fastcgi_drupal.conf there is a line:
fastcgi_param QUERY_STRING q=$uri&$args;

With this line everything works fine except the front page (The page you requested does not exist). To make it work I changed it to:
fastcgi_param QUERY_STRING $query_string;

With drupal_boost6_escaped.conf I got the front page in any page, no matter what is the URL.

Thanks

map_hash size

I have been testing nginx for one of our high profile drupal project. I came across your configuration in g.d.o, needless to say it is much saner. Thanks for sharing it.

Every time I configure nginx it throws me map_hash size error. The error message reads as below,

[emerg]: could not build the map_hash, you should increase map_hash_bucket_size: 64

Adding map_hash_bucket_size 192; in blacklist.conf seems to solve the issue for me however i'm not sure whether it is a right fix or not.

I would love to hear from you about the issue and fix I have applied. Sharing it with an intend to make your configuration still saner. Thanks.

boost cache clearing

Can anyone help regarding boost cache not clearing for submenu items/pages. When new items are published the root _.html files get cleared and a new page is generate, however its not working for sub pages e.g. www.site.com/page1/ - these boost pages become stale.

For now we have a cron delete the boost cache, however sometimes this is giving 404 errors in the logs as the _.html file has been deleted just before the request for the page.

Any experience with similar issues/ideas?

Thanks,

boost pages never get served

I have configured NginX / Drupal6 / Boost. The boost cache is being generated, however the .html files are never getting served to users. I am using the latest code from your git repo.

It seems it always passes directly to Drupal, not serving the cache.

If I comment out the following in drupal_boost6.conf, then the cache files DO get served as expected. No cookie/session is set, I am an anonymous user, however always seem to get sent to @no_cache.

location @cache {

error_page 418 = @no_cache;

if ($no_cache) {

return 418; # I'm a teapot/I can't get no cachifaction

}

If the above is commented out, then the cache works!

Also the frontpage is not getting cached. Could this be related?

Any ideas?

Authenticated users getting cached pages

My apologies if this is the wrong place for this issue, but using centos5.6+nginx0.8.4+php-fpm+drupal7+boost with the drupal_boost config, authenticated users are being served the cached versions of the page.

The only modification I have made to the stock config is applying this patch [https://github.com//issues/14] to the beginning of map_cache.conf to allow caching of the homepage.

I have also read through this discussion [http://www.ruby-forum.com/topic/3302927] and tried the suggestions in the 2nd post, but it made no difference.

If it helps the available cookies are:
has_js=1; __utma=16729588.1676405263.1325874996.1325874996.1325874996.1; __utmb=16729588.11.10.1325874996; __utmc=16729588; __utmz=16729588.1325874996.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); SESS0b787746165e40414fa69ee6aa29f572=vCI9hDndfAoEjLj7xs0KI5H0i2u_OvrzpQJJlDJOBRo; DRUPAL_UID=1; Drupal.toolbar.collapsed=0

Thanks for any help.

Leading slash in language prefix results in 404 error

I tried this configuration with a bilingual site and when I use the language prefix, Drupal returns a 404 error. With the help of some good old print_r() "debugging", I saw that the URL variable 'q' was being passed '/pt' instead of 'pt' (the latter being what Drupal's .htaccess gives you) and after some digging I found out that for some reason Drupal doesn't like that.

The solution proposed by brianmercer did work, and I implemented it by adding another location directive to drupal.conf, like this:

location @drupal6_rewrite {
    rewrite ^/(.*)$ /index.php?q=$1 last;
}

and then adding it to the necessary try_files directives. For example, instead of having just try_files $uri @cache;, I have try_files $uri @cache @drupal6_rewrite;.

This appears to be a Drupal 6-only issue, and since the goal is to have a rewrite-free nginx configuration, I'm not sure how this could be added. Maybe with some comments, telling people to uncomment it to enable the fix, if they need it.

duplicate location "/" in /etc/nginx/sites-available/drupal_boost.conf:16

Hi thanks for the config learned a lot from it.
I got nginx php-fpm and drupal6 working with your config, but can't seem to get it working with boost module.
When i uncomment "include sites-available/drupal_boost.conf;" i get that error duplicate location "/" in /etc/nginx/sites-available/drupal_boost.conf:16

windows title contains query strings

Not sure if this is related to this config or boost or drupal..

We are having an issue where the browser windows title when on the homepage, seems to randomly diplay query strings etc.

Other pages show the correct page title in browser windows title, but homepage some times not.

Has anyone had similar issues?

minor issues

I've found some more minor issues:

  • the sample limit_conn of 10 is way too small. A page with lots of pictures could easily create more than 10 connections (especially when the domain has many aliases to speedup parallel download).
  • location /sites/all/modules/ad/serve.php , which is used by the Ad module http://drupal.org/project/ad to show ads, could be allowed by default.
  • since most images are already compressed, perhaps image/png image/gif image/jpeg shouldn't be in gzip_types?

Is fastcgi_ignore_headers used correctly?

Per Nginx docs: http://wiki.nginx.org/HttpFcgiModule#fastcgi_ignore_headers it is used to ignore them, not "to deliver untouched from the upstream to the client":

This directive forbids processing of the named headers from the FastCGI-server reply. It is possible to specify headers like "X-Accel-Redirect", "X-Accel-Expires", "Expires" or "Cache-Control".

This means also that by adding Set-Cookie to this list, you could easily break the setup, since this header shouldn't be ignored. However, it appears that it is not supported in fastcgi_ignore_headers, so it may go unnoticed.

404 on module update from admin interface(drupal 7)

When using admin interface for module updates - nginx returns 404 (authorize.php)
(Because of "## Any other attempt to access PHP files returns a 404." rule in drupal.conf)

Can be fixed by adding something like this to drupal_cron_update.conf:
location = /authorize.php {
fastcgi_pass phpcgi;
}

502 errors in parts of site:

Dear perusio, using your full setup with a few modifications, i get a super lightning fast site, but in some parts of it i receive 502 errors (which i don't get with plain install). my setup is nginx+php-fpm+apc+boost, and by using included drupal_boost the site loads fine, but goes bork in:

  • a few books and their childs
  • drupal commerce: adding an item to the cart, or any part of checkout process.
    when clicking on the above i immediately receive 502 error, but the rest of the site is still operational. I have looked inside nginx.conf, drupal_boost, php and fastcgi_drupal.conf but nothin managed to get me over this issue. I would really like to use this setup, since on all other parts it is lightning.

Block .test files along with .module, etc

I used this config on a fresh install of Debian w/ the nginx.org package, and dotdeb.org PHP packages. After commenting out enough configuration to get it to run on this version of Nginx, I used a script like the following to check every file in the Drupal 7 download for accessibility:

cd /var/www/sites/example.com/
find . | cut -b2- | while read path; do
  curl --silent --head "http://example.com$path" | head -1 | tr "\r\n" "\t"
  echo $path
done | sort 

It's probably not too big an issue, but the *.test files are not blocked in the same way as the *.module, *.install, etc. are.

Third fallback pool in upstream_phpcgi_unix.conf unused?

The configuration file for upstream unix sockets has to upstream configs:

upstream phpcgi {
## If your version of Nginx doesn't have the fair load balancer:
## https://github.com/gnosek/nginx-upstream-fair comment out the
## following line.
fair;
server unix:/var/run/php-fpm.sock;
server unix:/var/run/php-fpm-zwei.sock;
## Create a backend connection cache. Note that this requires
## Nginx version greater or equal to 1.1.4.
## Cf. http://nginx.org/en/CHANGES. Comment out the following
## line if that's not the case.
keepalive 5;
}

Add a third pool as a fallback.

upstream phpcgi_backup {
server unix:/var/run/php-fpm-drei.sock;
## Create a backend connection cache. Note that this requires
## Nginx version greater or equal to 1.1.4.
## Cf. http://nginx.org/en/CHANGES. Comment out the
## following line if that's not the case.
keepalive 1;
}

However, I can't find how the backup upstream is ever used. From http://wiki.nginx.org/HttpUpstreamModule it looks like the way to indicate a backup server is through the 'backup' parameter.

Shouldn't this config be:
upstream phpcgi {
## If your version of Nginx doesn't have the fair load balancer:
## https://github.com/gnosek/nginx-upstream-fair comment out the
## following line.
fair;
server unix:/var/run/php-fpm.sock;
server unix:/var/run/php-fpm-zwei.sock;
server unix:/var/run/php-fpm-drei.sock backup;
## Create a backend connection cache. Note that this requires
## Nginx version greater or equal to 1.1.4.
## Cf. http://nginx.org/en/CHANGES. Comment out the following
## line if that's not the case.
keepalive 5;
}

Otherwise, could you tell me what I'm missing?

Thanks

Logging in with drupal_boost.conf

Hello,

First off, I'm an nginx noob so your project has been invaluable in getting me up and running with nginx.

As to my problem, when I try to use the drupal_boost.conf, I seem to lose the ability to login (running Drupal 7 here). Accessing user/login works, but when I complete the form and log in it just goes back to user/login with no error messages, I'm just not logged in.

Have you experienced anything like this?

Thanks,
Anthony

Cache file has md5 collision

My error.log get flooded with critical messages like 2012/03/24 23:59:51 [crit] 132141#0: *1 cache file "/var/cache/nginx/microcache/b/91/3a5a2fd6670d736d24925954984de91b" has md5 collision, client: 0.0.0.0, server: example.com, request: "GET / HTTP/1.1", host: "example.com", referrer: "https://example.com/". I couldn’t figure out what the reason is for this. Maybe you can help me?

405 not allowed

Hi Perusio,

Thank you for your configs, really usefull.
I'm using nginx-1.0.11, php5-fpm, memcached, apc and drupal7 + boost.

I'm receiving this error :

"405 not allowed."

This issue happening only when i change an exposed faceted filter with min-max value (with jquery plugin) that doing a redirect to another page.
Without boost your config working perfectly also with all faceted search filters that i have tryed.

And adding these lines in drupal_boost.conf on location /{ :

if ($request_method = POST) {
return 405;
}
error_page 405 = @drupal;

Working as expected.
I'm a newbie of nginx, and i'm not sure if this is the right solution..

Obrigado pela ajuda:)

boost cache pages always regenerated

I just installed nginx and ported my drupal 7.14 installation from an apache environment to nginx.
The I configured nginx using the perusio drupal-with-nginx pacake.

The site is working but all the pages are always generated via php and never served from the boost cache.

Looking into the boost cache I see that the file inside are recreated every time a page is accessed.

Any idea?

Thanks

frontpage not using boost cache

For some reason i can't get the frontpage to load from boost cache. Other pages load from boost cache quite happily it's just the frontpage that doesn't.
The config is pretty much default.

blacklisted referers

So, first, forgive me if this question isn't very informed.

I had a problem tonight where I was receiving empty js/css files for my site, and finally tracked it down to the blacklisted referers part of my configuration.

I have aliased urls and a forum topic title had the word "love" in it, causing requests for css/js it to be blocked by the bad referer check.

My question is, with aliased urls, the current implementation of the bad referer check seems really prone to failure. Does it not make sense to always allow requests coming from the current host?

Misspeling in example.com config

Path in sites-available/example.com:

include sites-available/drupal_update_cron.conf;

Real path:
sites-available/drupal_cron_update.conf

Enable microcache options on a per-vhost basis

The use case that I want to fill is something like this:

All sites live in /var/www. Let's talk about example.com.

So, in /var/www, there is a directory called "example.com". Inside that directory, there are three more directories: "dev", "stage", and "prod". Each of those directories contains a complete Drupal installation. It would be very nice to only enable the microcache for the prod installation, and not dev or stage.

A little fix for README.MD

I think, there should be

  • On drupal 7 use the drupal_boost.conf config in your vhost (server block): include sites-availables/drupal_boost.conf;.
    instead of
  • On drupal 7 use the drupal_boost.conf config in your vhost (server block): include sites-availables/drupal.conf;.

Boost on homepage

Homepage: eg.
site.com/home will get boosted
site.com won't get boosted

I believe it is because of the internal redirect caused by:
index index.php;
and
locations = /index.php
getting matched before anything, so the cache never gets checked.

I can't think of a good workaround for this however...

IPV6

listen [::]:80;

This won't work servers where IPV6 is not properly configured (most servers these days).
It would be nice to document this on the README.md

Suggestion:
Create a troubleshooting section on the readme, starting with this:

Your server's IPV6 is not configured properly. Remove the line
listen [::]:80;
from your server configuration blocks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.