We know that Nginx is more faster than Apache and most of us prefer to replace Apache with Nginx as their web server. Nginx is known to serve faster static content and run with less RAM. As of this writing, Virtualmin supports Apache as its web server. To take advantage of Nginx, we will install it as reverse proxy for Apache and continue using Virtualmin to manage your domains (Note: this article will assume that the Nginx and Apache are running on same server). This guide also applies to Nginx+PHP FPM setup just skip the "Configure Apache" section and skip the "Configure Virtualmin" section if you are not using Virtualmin. Nginx configurations for virtual host are tailored for Drupal site and the following are the features:
-
Support for Virtualmin to manage domains.
-
Microcache support for anonymous and authenticated users.
-
Seamless upstream switch between reverse proxy to Apache and PHP FPM backends.
-
Script that aids to generate Nginx configuration from template for your web site domain (for those who don't use Virtualmin).
-
Protections from: MIME type deviation, DoS attacks, bad bot/referrer user agents, clickjacking attacks, unauthorized access to private file directory and hotlinking.
-
Disabled access to any code files and known Drupal files and directories.
-
Better handling of static resources: css, cur, json, js, jpg/jpeg, gif, htc, ico, png, htm, html, xml, txt, otf, ttf, eot, woff, svg, webp, webm, zip, gz, tar, rar, pdf, pptx, mp3, ogg, flv, mp4, mpa.
-
Nginx PageSpeed support.
-
Boost module support.
-
Drupal 6, 7 and 8 clean URL support.
-
Advanced CSS/JS Aggregation module support.
-
RobotsTxt module support.
-
XML Sitemap module support.
-
Advanced Help module support.
-
imagecache module support.
-
File Force Download module support.
-
Provision to support Filefield Nginx Progress module.
-
RSS feed support.
-
Supports Drupal 8, Drupal 7 and Durpal 6.
-
The configurations observes Nginx's inheritance rules for add_header directives.
-
Protection against illegal HTTP methods (HEAD, GET and POST are only allowed).
-
The error_log is set to "error" level and access_log is disabled in this Nginx configurations to avoid spending disk IO time.
-
Implements Nginx PageSpeed module's Shard domains technique for non-SSL sites.
-
Uses the Let's Encrypt free SSL/TLS certificates.
The following procedures are tested on Linode server running Centos 7 64-bit Linux distribution.
Install Nginx
If you need to install Nginx with PageSpeed module please follow the steps here instead then jump to configure Nginx section.
-
In able to install the latest Nginx server we will need to register Nginx repository:
vi /etc/yum.repos.d/nginx.repo
Have the following codes as its content:
name=nginx repo baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/ gpgcheck=0 priority=1 enabled=0
Note: if just in case the nginx does not install try to hard code the $releasever with value of 7
-
Install Nginx using yum:
yum --enablerepo=nginx -y install nginx
-
Make Nginx auto-start upon reboot:
chkconfig nginx on
Configure Nginx
-
We will not need the native Nginx configurations provided because we will create new configurations. Lets backup the original Nginx configurations first:
mv /etc/nginx /etc/nginx.bak
-
Create the folders following the directory structure shown below:
In the next steps, we will populate these folders with Nginx configurations. We will start populating each folder from bottom folder (utils) to top folder (apps).
-
Create the main Nginx file
/etc/nginx/nginx.conf
and copy the following scripts to this file:user apache; ## This number should be, at maximum, the number of CPU cores on your system. ## (since nginx doesn't benefit from more than one worker per CPU.) worker_processes auto; ## Only log errors error_log /var/log/nginx/error.log error; pid /var/run/nginx.pid; ## Number of file descriptors used for Nginx. ## This is set in the OS with 'ulimit -n 200000' ## or using /etc/security/limits.conf worker_rlimit_nofile 200000; events { ## Determines how many clients will be served by each worker process. ## (worker_connections = 256 * worker_processes) ## worker_processes can be identified by `cat /proc/cpuinfo | grep processor` ## (Max clients = worker_connections * worker_processes) ## "Max clients" is also limited by the number of socket connections ## available on the system (~64k) worker_connections 1024; ## Accept as many connections as possible, ## after nginx gets notification about a new connection. ## May flood worker_connections, if that option is set too low. multi_accept on; } http { ## MIME types. include lib/mime.types; default_type application/octet-stream; ## Logs log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; ## Default log and error files. log_not_found off; error_log /var/log/nginx/error.log error; ## Buffer log writes to speed up IO, or disable them altogether #access_log /var/log/nginx/access.log main buffer=16k; #access_log /var/log/nginx/access.log; access_log off; ## Use sendfile() syscall to speed up I/O operations and speed up ## static file serving. ## Sendfile copies data between one FD and other from within the kernel. ## More efficient than read() + write(), since the requires transferring ## data to and from the user space. sendfile on; ## Handling of IPs in proxied and load balancing situations. set_real_ip_from 0.0.0.0/32; # all addresses get a real IP. real_ip_header X-Forwarded-For; # the ip is forwarded from the load balancer/proxy ## Limit Request/Connection ## Limit number of requests to mitigate DDoS attack limit_req_zone $binary_remote_addr zone=reqlimit:10m rate=60r/s; ## Define a zone for limiting the number of simultaneous ## connections nginx accepts. 1m means 32000 simultaneous ## sessions. We need to define for each server the limit_conn ## value referring to this or other zones. limit_conn_zone $binary_remote_addr zone=connlimit:5m; ## Timeouts. client_body_timeout 60s; client_header_timeout 60s; ## Timeout for keep-alive connections. ## Server will close connections after this time. keepalive_timeout 75 75; send_timeout 60s; ## Reset lingering timed out connections. Deflect DDoS. reset_timedout_connection on; ## TCP options. ## don't buffer data-sends (disable Nagle algorithm). ## Good for sending frequent small bursts of data in real time. tcp_nodelay on; ## Optimization of socket handling when using sendfile. ## Tcp_nopush causes nginx to attempt to send its HTTP response head in one packet, ## instead of using partial frames. This is useful for prepending headers ## before calling sendfile, or for throughput optimization. tcp_nopush on; ## Compression. ## Reduces the amount of data that needs to be transferred over the network gzip on; gzip_buffers 16 8k; gzip_comp_level 1; gzip_http_version 1.1; gzip_min_length 10; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/x-icon application/vnd.ms-fontobject font/opentype application/x-javascript application/x-font-ttf text/x-js; gzip_vary on; gzip_proxied any; # Compression for all requests. ## No need for regexps. See ## http://wiki.nginx.org/NginxHttpGzipModule#gzip_disable gzip_disable "msie6"; ## SSL ## Use a SSL/TLS cache for SSL session resume. This needs to be ## here (in this context, for session resumption to work. See this ## thread on the Nginx mailing list: ## http://nginx.org/pipermail/nginx/2010-November/023736.html. ## 1MB store about 4000 sessions: ## In this case, it store about 80000 sessions in 1 day ssl_session_cache shared:SSL:20m; ssl_session_timeout 1d; ## The server dictates the choice of cipher suites. ssl_prefer_server_ciphers on; ## Use only Perfect Forward Secrecy Ciphers. Fallback on non ECDH ## for crufty clients. ## Modern Mozilla SSL Configuration #ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256'; #ssl_protocols TLSv1.2; ## Intermediate Mozilla SSL Configuration ## https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=nginx-1.10.2&openssl=1.0.1e&hsts=no&profile=intermediate #ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS'; ## No SSLv3 support (SSLv3 POODLE Vulnerability) ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ## Old Mozilla SSL Configuration ## https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=nginx-1.10.2&openssl=1.0.1e&hsts=no&profile=old ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:DES-CBC3-SHA:HIGH:SEED:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!RSAPSK:!aDH:!aECDH:!EDH-DSS-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!SRP'; #ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2; ## Pregenerated Diffie-Hellman parameters 2048. ssl_dhparam key/dh_param.pem; ## Curve to use for ECDH. ssl_ecdh_curve prime256v1; ## Enable OCSP stapling. A better way to revocate server certificates. ssl_stapling on; ## Enable verification of OCSP stapling responses by the server. ssl_stapling_verify on; ## Server certificate and key (using Let's Encrypt free SSL certificate). ssl_certificate /etc/letsencrypt/live/yourwebsite.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/yourwebsite.com/privkey.pem; ## Verify chain of trust of OCSP response using Root CA and Intermediate certs ssl_trusted_certificate /etc/letsencrypt/live/yourwebsite.com/chain.pem; ## Use Google's DNS resolver 8.8.8.8 8.8.4.4; ## Body size. client_max_body_size 50m; ## To build optimal server_names_hash server_names_hash_bucket_size 72; ## If start getting [emerg]: could not build the map_hash, ## you should increase map_hash_bucket_size: 64 in your ## logs. Cf. http://wiki.nginx.org/NginxOptimizations. #map_hash_bucket_size 192; ## Uncomment one of the lines below if you start getting this message: ## "[emerg] could not build the variables_hash, you should increase ## either variables_hash_max_size: 512 or variables_hash_bucket_size: 64" ## You only need to increase one. Increasing variables_hash_max_size to 1024 ## was recommended in nginx forum by developers. ## See this forum topic and responses ## http://forum.nginx.org/read.php?2,192277,192286#msg-192286 ## See http://wiki.nginx.org/HttpCoreModule#variables_hash_bucket_size ## The line variables_hash_bucket_size was added for completeness but not ## changed from default. #variables_hash_max_size 1024; # default 512 #variables_hash_bucket_size 64; # default is 64 ## For the filefield_nginx_progress module to work. From the ## README. Reserve 1MB under the name 'uploads' to track uploads. #upload_progress uploads 1m; ## Modify HTTP header include utils/mod_header.conf; ## Hide the Nginx version number. server_tokens off; ## Map ## Include the map to block HTTP methods. include map/block_http_methods.conf; ## Support the X-Forwarded-Proto header for fastcgi. include map/x_forwarded_proto.conf; ## Include blacklist for bad bot and referer blocking. include map/blacklist.conf; ## Identify old browsers include map/old_browser.conf; ## Include the Nginx stub status allowed hosts configuration block. include map/nginx_status_allowed_hosts.conf; ## Include list of allowed hosts to run cron include map/cron_allowed_hosts.conf; ## Include the php-fpm status allowed hosts configuration block. include map/php_fpm_status_allowed_hosts.conf; ## Include the caching setup. ## Needed for using Drupal with an external cache. include map/drupal_external_cache.conf; ## Needed for Drupal Boost module. include map/drupal_boost_parse.conf; ## Drupal miscellaneous map include map/drupal_misc.conf; ## Include the upstream servers. include utils/service/upstream.conf; ## Microcache zone definition. include utils/service/microcache_zone.conf; ## Handle all undefined server_name include utils/undefined_server_name_handler.conf; ## Google PageSpeed module ## Uncomment the line below if Google PageSpeed module is present #include apps/pagespeed/core.conf; ## Include all vhosts. include sites-enabled/*.conf; }
Note: To generate the following SSL certificate files:
ssl_certificate /etc/letsencrypt/live/yourwebsite.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/yourwebsite.com/privkey.pem; ssl_trusted_certificate /etc/letsencrypt/live/yourwebsite.com/chain.pem;
... follow steps in this article: Using Let's Encrypt free SSL/TLS certificates with Nginx.
-
Lets populate
/etc/nginx/utils
:Create the file
/etc/nginx/utils/letsencrypt.conf
and copy the following scripts to this file:## Allow Let's Encrypt to access the temporary file location ^~ /.well-known/acme-challenge/ { allow all; root /var/www/letsencrypt; default_type "text/plain"; try_files $uri =404; }
Create the file
/etc/nginx/utils/undefined_server_name_handler.conf
and copy the following scripts to this file:## Prevent processing requests with undefined server names (HTTPS) server { listen XXX.XXX.XXX.XXX:443 ssl; ## IPv4 listen [XXXX:XXXX::XXXX:XXXX:XXXX:XXXX]:443 ssl; ## IPv6 server_name _; return 444; } ## Prevent processing requests with undefined server names (HTTP) server { listen XXX.XXX.XXX.XXX:80; ## IPv4 listen [XXXX:XXXX::XXXX:XXXX:XXXX:XXXX]:80; ## IPv6 server_name _; return 444; } ## Prevent processing requests with undefined server names (HTTPS) server { listen XXX.XXX.XXX.XXX:443 ssl; ## IPv4 listen [XXXX:XXXX::XXXX:XXXX:XXXX:XXXX]:443 ssl; ## IPv6 server_name ""; return 444; } ## Prevent processing requests with undefined server names (HTTP) server { listen XXX.XXX.XXX.XXX:80; ## IPv4 listen [XXXX:XXXX::XXXX:XXXX:XXXX:XXXX]:80; ## IPv6 server_name ""; return 444; }
Note: Replace all the occurrence of
XXX.XXX.XXX.XXX
with your server's IPv4 address andXXXX:XXXX::XXXX:XXXX:XXXX:XXXX
with your server's IPv6 address.Create the file
/etc/nginx/utils/mod_header.conf
and copy the following scripts to this file:## Modify HTTP header ## Enable the builtin cross-site scripting (XSS) filter available ## in modern browsers. Usually enabled by default we just ## reinstate in case it has been somehow disabled for this ## particular server instance. ## https://www.owasp.org/index.php/List_of_useful_HTTP_headers. add_header X-XSS-Protection '1; mode=block'; ## Enable clickjacking protection in modern browsers. Available in ## IE8 also. See ## https://developer.mozilla.org/en/The_X-FRAME-OPTIONS_response_header ## This may conflicts with pseudo streaming (at least with Nginx version 1.0.12). ## Uncomment the line below if you're not using media streaming. ## For sites being framing on the same domain uncomment the line below. add_header X-Frame-Options SAMEORIGIN; ## For sites accepting to be framed in any context comment the ## line below. #add_header X-Frame-Options DENY; ## When serving user-supplied content, include a X-Content-Type-Options: nosniff header along with the Content-Type: header, ## to disable content-type sniffing on some browsers. ## https://www.owasp.org/index.php/List_of_useful_HTTP_headers ## currently suppoorted in IE > 8 http://blogs.msdn.com/b/ie/archive/2008/09/02/ie8-security-part-vi-beta-2-update.aspx ## http://msdn.microsoft.com/en-us/library/ie/gg622941(v=vs.85).aspx ## 'soon' on Firefox https://bugzilla.mozilla.org/show_bug.cgi?id=471020 ## Block MIME type sniffing on IE. add_header X-Content-Options nosniff; ## Add a cache miss/hit status header. This can be disabled if not including ## any of the apps/drupal/microcache* files. add_header X-Micro-Cache $upstream_cache_status;
Create the file
/etc/nginx/utils/nginx_status_vhost.conf
and copy the following scripts to this file:## The configuration for Nginx status page. As described in ## http://wiki.nginx.org/HttpStubStatusModule. ## php-fpm provides a status and a heartbeat page that is served through the web server. ## Here's an example configuration for them. ## Get the nginx status. location /nginx_status { if ($dont_show_nginx_status) { return 404; } stub_status on; access_log off; }
Create the file
/etc/nginx/utils/apache/microcache.conf
and copy the following scripts to this file:## The cache zone referenced. proxy_cache microcache; ## The cache key. proxy_cache_key $scheme$host$request_uri; ## For 200 and 301 make the cache valid for 10 seconds. proxy_cache_valid 200 301 10s; ## For 302 make it valid for 1 minute. proxy_cache_valid 302 1m; ## For 404 make it valid 1 second. proxy_cache_valid 404 1s; ## If there are any upstream errors or the item has expired use ## whatever it is available. proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504 off; ## The Cache-Control and Expires headers should be delivered untouched ## from the upstream to the client. proxy_ignore_headers Cache-Control Expires; ## Bypass the cache. proxy_cache_bypass $no_cache; proxy_no_cache $no_cache; ## To avoid any interaction with the cache control headers we expire ## everything on this location immediately. expires epoch; ## Cache locking mechanism for protecting the backendof too many ## simultaneous requests. proxy_cache_lock on; ## The default timeout, i.e., the time to way before forwarding the ## second request upstream if no reply as arrived in the meantime is 5s. proxy_cache_lock_timeout 5000; # in miliseconds.
Create the file
/etc/nginx/utils/apache/microcache_auth.conf
and copy the following scripts to this file:## The cache zone referenced. proxy_cache microcache; ## The cache key. proxy_cache_key $cache_uid@$scheme$host$request_uri; ## For 200 and 301 make the cache valid for 10 seconds. proxy_cache_valid 200 301 10s; ## For 302 make it valid for 1 minute. proxy_cache_valid 302 1m; ## For 404 make it valid 1 second. proxy_cache_valid 404 1s; ## If there are any upstream errors or the item has expired use ## whatever it is available. proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504 off; ## The Cache-Control and Expires headers should be delivered untouched ## from the upstream to the client. proxy_ignore_headers Cache-Control Expires; proxy_pass_header Set-Cookie; proxy_pass_header Cookie; ## Bypass the cache. proxy_cache_bypass $no_auth_cache; proxy_no_cache $no_auth_cache; ## To avoid any interaction with the cache control headers we expire ## everything on this location immediately. expires epoch; ## Cache locking mechanism for protecting the backendof too many ## simultaneous requests. proxy_cache_lock on; ## The default timeout, i.e., the time to way before forwarding the ## second request upstream if no reply as arrived in the meantime is 5s. proxy_cache_lock_timeout 5000; # in miliseconds.
Create the file
/etc/nginx/utils/apache/microcache_zone.conf
and copy the following scripts to this file:## Defining the proxy cache zone for the microcache as presented at: ## http://fennb.com/microcaching-speed-your-app-up-250x-with-no-n. ## If youre using a Nginx version greater than 1.1.1 then you can ## tweak the Tweaking of the cache loader parameters. ## Cf. http://forum.nginx.org/read.php?21,213197,213209#msg-213209 for ## rationale. proxy_cache_path /var/cache/nginx/microcache levels=1:2 keys_zone=microcache:5M max_size=1G loader_threshold=2592000000 loader_sleep=1 loader_files=100000;
Create the file
/etc/nginx/utils/apache/php_fpm_status_vhost.conf
and copy the following scripts to this file:## This should be empty. Serves as dummy to prevent nginx non-existing file error.
Create the file
/etc/nginx/utils/apache/php_pass.conf
and copy the following scripts to this file:## Apache configuration ## Configuration for reverse proxy. Passing the necessary headers to ## the backend. Nginx doesn't tunnel the connection, it opens a new ## one. Hence we need to send these headers to the backend so that ## the client(s) IP is available to them. The host is also sent. proxy_pass http://phpapache; proxy_http_version 1.1; # keep alive to the Apache upstream proxy_set_header Connection ''; ## Referrer proxy_set_header Visitor-referrer $http_referer; ## Rewrite the 'Host' header to the value in the client request, ## or primary server name proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; ## Hide the X-Drupal-Cache header provided by Pressflow. proxy_hide_header 'X-Drupal-Cache'; ## Hide the Drupal 7 header X-Generator. proxy_hide_header 'X-Generator';
Create the file
/etc/nginx/utils/apache/upstream.conf
and copy the following scripts to this file:## Upstream configuration for Apache functioning has a PHP handler. ## Add as many servers as needed. ## Cf. http://wiki.nginx.org/HttpUpstreamModule. ## Note that this configuration assumes by default that keepalive ## upstream connections are supported and that you have a Nginx ## version with the fair load balancer. upstream phpapache { ## Use the least connection algorithm for load balancing. This ## algorithm was introduced in versions 1.3.1 and 1.2.2. least_conn; server 127.0.0.1:8080; #server 127.0.0.1:8081; ## Create a backend connection cache. Note that this requires ## Nginx version greater or equal to 1.1.4. ## Cf. http://nginx.org/en/CHANGES. keepalive 5; }
Populate the
/etc/nginx/utils/fastcgi
folder under this guide: Setup PHP FPM for Nginx. -
The
/etc/nginx/sites-enabled
folder is used as container for enabled websites which are soft link to physical file Nginx configuration of each of your website virtual host stored at/etc/nginx/sites-available/prod
. -
Lets populate
/etc/nginx/sites-available
:Create the file
/etc/nginx/sites-available/template.conf
and copy the following scripts to this file:## Nginx configuration for {DOM}. ## Redirect HTTPS to HTTP (Domains used for static resource). server { listen XXX.XXX.XXX.XXX:443 ssl; ## IPv4 listen [XXXX:XXXX::XXXX:XXXX:XXXX:XXXX]:443 ssl; ## IPv6 server_name s1.{DOM} s2.{DOM} s3.{DOM} s4.{DOM}; return 301 http://$server_name$request_uri; } ## Domains used for static resource. server { listen XXX.XXX.XXX.XXX:80; ## IPv4 listen [XXXX:XXXX::XXXX:XXXX:XXXX:XXXX]:80; ## IPv6 server_name s1.{DOM} s2.{DOM} s3.{DOM} s4.{DOM}; ## Access and error logs. #access_log /var/log/virtualmin/{DOM}_nginx_access_log; access_log off; log_not_found off; error_log /var/log/virtualmin/{DOM}_nginx_error_log error; ## Let's Encrypt domain verification temporary file include utils/letsencrypt.conf; ## Filesystem root of the site. root {HOME}; ## Set no HTTP Strict Transport Security set $hsts ""; ## Common Nginx configuration for server context include apps/drupal/common_server_context.conf; ## Named location include apps/drupal/named_location.conf; ## The 'default' location. location / { ## Redirect web content to main domain. location ~* \.(html?|xml)$ { return 301 $scheme://www.{DOM}$request_uri; } ## Accept static files only. ## Drupal generated static files. include apps/drupal/static_files_handler.conf; } } ## Redirect HTTPS to HTTP (Main server). server { listen XXX.XXX.XXX.XXX:443 ssl; ## IPv4 listen [XXXX:XXXX::XXXX:XXXX:XXXX:XXXX]:443 ssl; ## IPv6 server_name {DOM} www.{DOM}; return 301 http://$server_name$request_uri; } ## Redirect domain with prefixed www sub-domain. server { ## This is to avoid the spurious if for sub-domain name ## "rewriting". listen XXX.XXX.XXX.XXX:80; ## IPv4 listen [XXXX:XXXX::XXXX:XXXX:XXXX:XXXX]:80; ## IPv6 server_name {DOM}; if ($letsencrypt = 0) { return 301 http://www.{DOM}$request_uri; } ## Let's Encrypt domain verification temporary file include utils/letsencrypt.conf; } ## Main server. server { listen XXX.XXX.XXX.XXX:80; ## IPv4 listen [XXXX:XXXX::XXXX:XXXX:XXXX:XXXX]:80; ## IPv6 server_name www.{DOM}; ## PageSpeed ## Uncomment the line below if Google PageSpeed module is present #pagespeed ShardDomain $scheme://$server_name $scheme://s1.{DOM},$scheme://s2.{DOM}; ## Access and error logs. #access_log /var/log/virtualmin/{DOM}_nginx_access_log; access_log off; log_not_found off; error_log /var/log/virtualmin/{DOM}_nginx_error_log error; ## Let's Encrypt domain verification temporary file include utils/letsencrypt.conf; ## Filesystem root of the site and index. root {HOME}; index index.php; ## Set no HTTP Strict Transport Security set $hsts ""; ## Configuration for Drupal. include apps/drupal/core.conf; ## Installation handling. If an already installed site there's ## no need to touch it. Uncomment the line below if you want to ## enable Drupal install PHP script and comment out after ## installation. Note that there's a basic auth in front as ## secondary line of defense. #include apps/drupal/drupal_install.conf; ## Configuration for updating the site via update.php and running ## cron externally. Uncomment the line below if you want to ## enable Drupal xmlrpc, update and cron PHP script #include apps/drupal/drupal_cron_update.conf; ## Support for upload progress bar. Configurations differ for ## Drupal 6 and Drupal 7. #include apps/drupal/drupal_upload_progress.conf; ## Including the php-fpm status and ping pages config. #include utils/service/php_fpm_status_vhost.conf; ## Including the Nginx stub status page for having stats about ## Nginx activity: http://wiki.nginx.org/HttpStubStatusModule. #include utils/nginx_status_vhost.conf; {TARGETED_SERVER_CONFIG} }
Note: Replace all the occurrence of
XXX.XXX.XXX.XXX
with your server's IPv4 address andXXXX:XXXX::XXXX:XXXX:XXXX:XXXX
with your server's IPv6 address.Create the file
/etc/nginx/sites-available/template_ssl.conf
and copy the following scripts to this file:## Nginx configuration for {DOM}. ## Redirect HTTP to HTTPS. server { listen XXX.XXX.XXX.XXX:80; ## IPv4 listen [XXXX:XXXX::XXXX:XXXX:XXXX:XXXX]:80; ## IPv6 server_name {DOM} www.{DOM}; if ($nossl = 0){ ## Redirect to HTTPS. return 301 https://$server_name$request_uri; } ## Let's Encrypt domain verification temporary file include utils/letsencrypt.conf; } ## HTTPS (Redirect domain with prefixed www sub-domain). server { listen XXX.XXX.XXX.XXX:443 ssl; ## IPv4 listen [XXXX:XXXX::XXXX:XXXX:XXXX:XXXX]:443 ssl; ## IPv6 server_name {DOM}; ## Access and error logs. #access_log /var/log/virtualmin/{DOM}_nginx_access_log; access_log off; log_not_found off; error_log /var/log/virtualmin/{DOM}_nginx_error_log error; ## Check if the device is old not to support SSL if ($nossl) { ## Device is old. Redirect to non-SSL. return 302 http://$server_name$request_uri; } ## Else serve the HTTPS version for supported devices ## Config to enable HSTS (HTTP Strict Transport Security) ## https://developer.mozilla.org/en-US/docs/Security/HTTP_Strict_Transport_Security ## to avoid ssl stripping https://en.wikipedia.org/wiki/SSL_stripping#SSL_stripping ## Strict Transport Security header for enhanced security. See ## http://www.chromium.org/sts. Enables HTTP to HTTPS redirects via browser level. set $hsts "max-age=31536000"; add_header Strict-Transport-Security $hsts; ## Inheritance Rules for add_header Directives ## Because this 'server' block contains another 'add_header' directive, ## we must redeclare the 'add_header' from 'http' context include utils/mod_header.conf; return 301 $scheme://www.{DOM}$request_uri; } ## HTTPS (Main server). server { listen XXX.XXX.XXX.XXX:443 ssl http2; ## IPv4 listen [XXXX:XXXX::XXXX:XXXX:XXXX:XXXX]:443 ssl http2; ## IPv6 server_name www.{DOM}; ## Access and error logs. #access_log /var/log/virtualmin/{DOM}_nginx_access_log; access_log off; log_not_found off; error_log /var/log/virtualmin/{DOM}_nginx_error_log error; ## Check if the device is old not to support SSL if ($nossl) { ## Device is old. Redirect to non-SSL. return 302 http://$server_name$request_uri; } ## Else serve the HTTPS version for supported devices ## Config to enable HSTS (HTTP Strict Transport Security) ## https://developer.mozilla.org/en-US/docs/Security/HTTP_Strict_Transport_Security ## to avoid ssl stripping https://en.wikipedia.org/wiki/SSL_stripping#SSL_stripping ## Strict Transport Security header for enhanced security. See ## http://www.chromium.org/sts. Enables HTTP to HTTPS redirects via browser level. set $hsts "max-age=31536000"; add_header Strict-Transport-Security $hsts; ## Inheritance Rules for add_header Directives ## Because this 'server' block contains another 'add_header' directive, ## we must redeclare the 'add_header' from 'http' context include utils/mod_header.conf; ## Filesystem root of the site and index. root {HOME}; index index.php; ## Configuration for Drupal. include apps/drupal/core.conf; ## Installation handling. If an already installed site there's ## no need to touch it. Uncomment the line below if you want to ## enable Drupal install PHP script and comment out after ## installation. Note that there's a basic auth in front as ## secondary line of defense. #include apps/drupal/drupal_install.conf; ## Configuration for updating the site via update.php and running ## cron externally. Uncomment the line below if you want to ## enable Drupal xmlrpc, update and cron PHP script #include apps/drupal/drupal_cron_update.conf; ## Support for upload progress bar. Configurations differ for ## Drupal 6 and Drupal 7. #include apps/drupal/drupal_upload_progress.conf; ## Including the php-fpm status and ping pages config. #include utils/service/php_fpm_status_vhost.conf; ## Including the Nginx stub status page for having stats about ## Nginx activity: http://wiki.nginx.org/HttpStubStatusModule. #include utils/nginx_status_vhost.conf; {TARGETED_SERVER_CONFIG} }
Note: Replace all the occurrence of
XXX.XXX.XXX.XXX
with your server's IPv4 address andXXXX:XXXX::XXXX:XXXX:XXXX:XXXX
with your server's IPv6 address.The two scripts above
/etc/nginx/sites-available/template.conf
and/etc/nginx/sites-available/template_ssl.conf
will be used by the Virtualmin to generate Nginx configuration for your website virtual host when created using Virtualmin. By default, these configurations utilizes the use of Drush for site maintenance. If you wanted the original Drupal behavior in installing new site, uncomment the line:include apps/drupal/drupal_install.conf;
For original Drupal cron and update behavior, uncomment the line:
include apps/drupal/drupal_cron_update.conf;
Note: This uses Basic Authentication so it will challenge you for password.
If you are not using Virtualmin, you can use the following bash script to create Nginx configuration for your website virtual host. Create the file
/etc/nginx/sites-available/buildsitesconf.sh
and add the following to it:#!/bin/bash rm -rf prod mkdir prod SITES=('yourwebsite.com' 'yourotherwebsite.com') SITEHOME='\/home\/drupal\/public_html' for SITEDOM in "${SITES[@]}" do sed "s/{DOM}/$SITEDOM/g" template.conf > buffer.conf sed "s/{HOME}/$SITEHOME/g" buffer.conf > "prod/${SITEDOM}.conf" sed "s/{DOM}/$SITEDOM/g" template_ssl.conf > buffer.conf sed "s/{HOME}/$SITEHOME/g" buffer.conf > "prod/${SITEDOM}_ssl.conf" if [ -f "targeted_server_config/${SITEDOM}.conf" ] then sed "s/{TARGETED_SERVER_CONFIG}/include sites-available\/targeted_server_config\/${SITEDOM}.conf;/g" "prod/${SITEDOM}.conf" > buffer.conf cat buffer.conf > "prod/${SITEDOM}.conf" sed "s/{TARGETED_SERVER_CONFIG}/include sites-available\/targeted_server_config\/${SITEDOM}.conf;/g" "prod/${SITEDOM}_ssl.conf" > buffer.conf cat buffer.conf > "prod/${SITEDOM}_ssl.conf" else sed "s/{TARGETED_SERVER_CONFIG}//g" "prod/${SITEDOM}.conf" > buffer.conf cat buffer.conf > "prod/${SITEDOM}.conf" sed "s/{TARGETED_SERVER_CONFIG}//g" "prod/${SITEDOM}_ssl.conf" > buffer.conf cat buffer.conf > "prod/${SITEDOM}_ssl.conf" fi done rm -f buffer.conf
Note: Replace the
'yourwebsite.com' 'yourotherwebsite.com'
with your own website domains and'\/home\/drupal\/public_html'
with your websites' root path (eg. if your websites' root path is/var/www
then change it to'\/var\/www'
).Make it executable:
chmod +x /etc/nginx/sites-available/buildsitesconf.sh
When you executed this script, it will generate non-SSL and SSL versions of Nginx configuration for your website virtual hosts that you defined at
/etc/nginx/sites-available/buildsitesconf.sh
. The generated Nginx configuration will be saved at/etc/nginx/sites-available/prod
.To enable a non-SSL version virtual host Nginx configuration, just create a soft link of this configuration file from /etc/nginx/sites-available/prod to /etc/nginx/sites-enabled example:
ln -s /etc/nginx/sites-available/prod/yourwebsite.com.conf /etc/nginx/sites-enabled/yourwebsite.com.conf
... or if SSL version is desired:
ln -s /etc/nginx/sites-available/prod/yourwebsite_ssl.com.conf /etc/nginx/sites-enabled/yourwebsite_ssl.com.conf
This is easy and good approach to disable and enable a virtual host.
The
/etc/nginx/sites-available/prod
folder will be used by the/etc/nginx/sites-available/template.conf
and/etc/nginx/sites-available/template_ssl.conf
scripts as container for the generated Nginx configuration of your website virtual host.The
/etc/nginx/sites-available/admin
folder will be used for Admin UI Nginx configurations like:The
/etc/nginx/sites-available/targeted_server_config
folder will be used by the/etc/nginx/sites-available/template.conf
and/etc/nginx/sites-available/template_ssl.conf
scripts to look for the filename that will match the domain under process. e.g. if the template script processing the domain "webfoobar.com", it will look for a filename "webfoobar.com.conf" and this should only contain your custom Nginx configuration for "webfoobar.com" domain inserver
context. Domains that don't have custom Nginx configuration need not to create file under this folder. -
Lets populate
/etc/nginx/map
:Create the file
/etc/nginx/map/php_fpm_status_allowed_hosts.conf
and add the following to it:## Configuration of php-fpm status and ping pages. Here we define the ## allowed hosts using the Geo Module. http://wiki.nginx.org/HttpGeoModule geo $dont_show_fpm_status { default 1; 127.0.0.1 0; # allow on the loopback 192.168.1.0/24 0; # allow on an internal network }
Create the file
/etc/nginx/map/nginx_status_allowed_hosts.conf
and add the following to it:## Configuration of nginx stub status page. Here we define the ## allowed hosts using the Geo Module. http://wiki.nginx.org/HttpGeoModule geo $dont_show_nginx_status { default 1; 127.0.0.1 0; # allow on the loopback 192.168.1.0/24 0; # allow on an internal network }
Create the file
/etc/nginx/map/hotlinking_protection_allowed_hosts.conf
and add the following to it:## Hotlinking protection for images. Include it in any context you ## want. Adjust the list of allowed referrers to your liking. valid_referers none blocked www.yahoo.com www.google.com webfoobar.com www.webfoobar.com ## Add your domains here; if ($invalid_referer) { return 200 "No image hotlinking allowed!\n"; }
Create the file
/etc/nginx/map/drupal_external_cache.conf
and add the following to it:## Testing if we should be serving content from cache or not. This is ## needed for any Drupal setup that uses an external cache. ## Let Ajax calls go through. map $uri $no_cache_ajax { default 0; /system/ajax 1; } ## Test Boost session cookie being present. If there is, then no ## caching is to be done. map $http_cookie $no_boost_cache_cookie { default 0; ~DRUPAL_UID 1; #~nocache=1 1; # Custom logged in/out indicator } ## Boost URI watch list map $request_uri $no_boost_cache_uri { default 0; ~*^/(admin|cache|misc|modules|sites|system|openid|themes|node/add|comment/reply)|(/(edit|user|user/(login|password|register)))$ 1; } ## Combine both results to get the cache bypassing mapping. map $no_boost_cache_cookie$no_boost_cache_uri $no_boost_cache { default 1; 00 0; } ## Testing for the session cookie being present. If there is, then no ## caching is to be done. Note that this is for someone using either ## Drupal 7 pressflow or stock Drupal 6 core with no_anon ## (https://drupal.org/project/no_anon). map $http_cookie $no_cache_cookie { default 0; ~SESS 1; # PHP session cookie #~nocache=1 1; # Custom logged in/out indicator } ## Combine both results to get the cache bypassing mapping. map $no_cache_ajax$no_cache_cookie $no_auth_cache { default 1; 00 0; } ## Cache bypassing mapping (auth). map $no_cache_ajax $no_cache { default 0; 1 1; } ## Set a cache_uid variable for authenticated users. map $http_cookie $cache_uid { default nil; ~SESS[[:alnum:]]+=(?<session_id>[[:graph:]]+) $session_id; }
Note: You can also use the Method 1 mentioned here: Methods to disable Nginx cache when user is authenticated in Drupal as I find it more reliable indicator for user status: anonymous or authenticated.
Create the file
/etc/nginx/map/drupal_boost_parse.conf
and add the following to it:## Drupal Boost Nginx support ## Parse $uri and $args to correctly match the static Boost generated files ## Remove the trailing slash and "/index.php" map $uri $boost_uri { default $uri; ~^/(.*)/$ $1; ~^/(.*) $1; ~(.*)/$ $1; /index.php ''; } ## Remove the trailing slash in "q" query variable parameter map $arg_q $boost_argq { default $arg_q; ~^/(.*) $1; }
Create the file
/etc/nginx/map/drupal_misc.conf
and add the following to it:## Drupal miscellaneous map ## Fix for blocked by CORS policy: No Access-Control-Allow-Origin header map $http_origin $cors_fix { default *; $scheme://$host ""; "" ""; }
Create the file
/etc/nginx/map/old_browser.conf
and add the following to it:## Override redirection to HTTPS if location is /.well-known/acme-challenge ## For Let's Encrypt. map $request_uri $letsencrypt { default 0; ~*/\.well\-known/acme\-challenge/.+ 1; } ## Force redirect visitors with old browser to non-SSL site. map $http_user_agent $nossl { default $letsencrypt; "~MSIE [1-7]\." 1; ## Internet Explorer 1-7 "~Windows NT [1-5]\." 1; ## Windows Server 2003; Windows XP x64 Edition; Windows XP; Windows 2000; Service Pack 1 (SP1); Windows 2000; Windows NT 4.0 "~Windows 98" 1; ## Windows 98; Windows Millennium Edition (Windows Me) "~Windows 95" 1; ## Windows 95 "~Windows CE" 1; ## Windows CE "~Android [1-3]\." 1; ## Cupcake, Donut, Éclair, Froyo, Gingerbread, Honeycomb "~Android 4\.0" 1; ## Ice Cream Sandwich }
Create the file
/etc/nginx/map/cron_allowed_hosts.conf
and add the following to it:## Configuration file for specifying which hosts can invoke Drupal's ## cron. This only applies if you're not using drush to run cron. geo $not_allowed_cron { default 1; ## Add your set of hosts. 127.0.0.1 0; # allow the localhost 192.168.1.0/24 0; # allow on an internal network }
Create the file
/etc/nginx/map/block_http_methods.conf
and add the following to it:## This file contains a map directive that is used to block the ## invocation of HTTP methods. Out of the box it allows for HEAD, GET and POST. map $request_method $not_allowed_method { default 1; GET 0; HEAD 0; POST 0; }
Create the file
/etc/nginx/map/x_forwarded_proto.conf
and add the following to it:## Support the X-Forwarded-Proto header for fastcgi. map $http_x_forwarded_proto $fastcgi_https { default $https; http ''; https on; }
Create the file
/etc/nginx/map/blacklist.conf
and add the following to it:## This file implements a blacklist for certain user agents and ## referrers. It's a first line of defence. It must be included ## inside a http block. ## Add here all user agents that are to be blocked. map $http_user_agent $bad_bot { default 0; ~*^Lynx 0; # Let Lynx go through libwww-perl 1; ~*(?i)(360Spider|80legs|Abonti|Aboundex|^AIBOT|^Alexibot|almaden|^Anarchie|^ASPSeek|^asterias|^attach|^autoemailspider|^BackWeb|Baiduspider|^Bandit|^BatchFTP|BBBike|^BackDoorBot|^Bigfoot|^Black.Hole|^BlackWidow|^BlowFish|^Bot\ mailto:[email protected]|^BotALot|^Buddy|^BuiltBotTough|^Bullseye|^bumblebee|^BunnySlippers|^Cegbfeieh|^CheeseBot|^CherryPicker|^ChinaClaw|^CICC|Cogentbot|^Collector|^Copier|^CopyRightCheck|^cosmos|CPython|^Crescent|^Custo|^DA|^DIIbot|^DISCo|^DISCo\ Pump|^Download\ Demon|^Download\ Wonder|^Downloader|^Drip|^DSurf15a|^eCatch|^EasyDL/2.99|^EirGrabber|email|^EmailCollector|^EmailSiphon|^EmailWolf|^Express\ WebPictures|^ExtractorPro|^EyeNetIE|facebookexternalhit|^FileHound|^FlashGet|FlipboardProxy|FrontPage|^GetRight|^GetSmart|^GetWeb!|^gigabaz|^Go\!Zilla|^Go!Zilla|^Go-Ahead-Got-It|^gotit|^Grabber|^GrabNet|^Grafula|^grub-client|^HMView|htmlparser|^HTTrack|^httpdown|.*httrack.*|^ia_archiver|^Image\ Stripper|^Image\ Sucker|^Indy*Library|Indy\ Library|^InterGET|^InternetLinkagent|^Internet\ Ninja|^InternetSeer.com|^Iria|^Java|^JBH*agent|^JetCar|^JOC\ Web\ Spider|JikeSpider|^JustView|^larbin|^LeechFTP|^LexiBot|^lftp|libwww|^Link*Sleuth|^likse|^Link|^LinkWalker|^Mag-Net|^Magnet|^Mass\ Downloader|mediawords|MegaIndex|^Memo|MetaURI|^Microsoft.URL|^MIDown\ tool|^Mirror|^Mister\ PiX|MJ12bot|Mozilla/4.0|^Mozilla.*Indy|^Mozilla.*NEWT|^Mozilla*MSIECrawler|^MS\ FrontPage*|^MSFrontPage|^MSIECrawler|msnbot|^MSProxy|^Navroad|^NearSite|^NetAnts|^NetMechanic|^NetSpider|^Net\ Vampire|^NetZIP|^NICErsPRO|^Ninja|^Octopus|^Offline\ Explorer|^Offline\ Navigator|^Openfind|OpenLinkProfiler|^PageGrabber|^Papa\ Foto|^pavuk|^pcBrowser|^Ping|^PingALink|Pixray|^Pockey|proximic|^psbot|^Pump|^QRVA|^RealDownload|^Reaper|^Recorder|^ReGet|^Scooter|^Seeker|^Siphon|^sitecheck.internetseer.com|Siteimprove|^SiteSnagger|^SlySearch|^SmartDownload|^Snake|Sosospider|^SpaceBison|spbot|Spinn3r|^sproose|^Stripper|^Sucker|^SuperBot|^SuperHTTP|^Surfbot|^Szukacz|^tAkeOut|^Teleport\ Pro|Twitterbot|^URLSpiderPro|^Vacuum|^VoidEYE|^Web\ Image\ Collector|^Web\ Sucker|^WebAuto|^[Ww]eb[Bb]andit|^webcollage|^WebCopier|^Web\ Downloader|^WebEMailExtrac.*|^WebFetch|^WebGo\ IS|^WebHook|^WebLeacher|^WebMiner|^WebMirror|^WebReaper|^WebSauger|^Website|^Website\ eXtractor|^Website\ Quester|^Webster|^WebStripper|WebWhacker|^WebZIP|^Wget|^Whacker|^Widow|^WWWOFFLE|^x-Tractor|^Xaldon\ WebSpider|^Xenu|^Zeus.*Webster|^Zeus|ZmEu) 1; } ## Add here all referrers that are to blocked. map $http_referer $bad_referer { default 0; ~(?i)(adult|babes|click|diamond|forsale|girl|jewelry|love|nudit|organic|poker|porn|poweroversoftware|sex|teen|webcam|zippo|casino|replica|en.savefrom.net|7makemoneyonline.com|acunetix-referrer.com|adcash.com|bithack.ru|buttons-for-website.com|cenokos.ru|cenoval.ru|cityadspix.com|darodar.com|econom.co|edakgfvwql.ru|gobongo.info|iedit.ilovevitaly.com|ilovevitaly.com|ilovevitaly.co|ilovevitaly.info|ilovevitaly.org|ilovevitaly.ru|iskalko.ru|luxup.ru|make-money-online.7makemoneyonline.com|maps.ilovevitaly.com|myftpupload.com|savefrom.net|savetubevideo.com|screentoolkit.com|semalt.com|seoexperimenty.ru|shopping.ilovevitaly.ru|slftsdybbg.ru|socialseet.ru|srecorder.com|st3.cwl.yahoo.com|superiends.org|vodkoved.ru|websocial.me|ykecwqlixx.ru|yougetsignal.com|priceg.com|responsinator.com|o-o-6-o-o.ru|o-o-8-o-o.ru) 1; } ## Add here all hosts that should be spared any referrer checking. geo $bad_referer { ## Add your set of hosts. 127.0.0.1 0; 192.168.1.0/24 0; }
-
Lets populate
/etc/nginx/lib
:Create the file
/etc/nginx/lib/win-utf
and add the following to it:## This map is not a full windows-1251 utf8 map: it does not ## contain Serbian and Macedonian letters. If you need a full map, ## use contrib/unicode2nginx/win-utf map instead. charset_map windows-1251 utf-8 { 82 E2809A ; ## single low-9 quotation mark 84 E2809E ; ## double low-9 quotation mark 85 E280A6 ; ## ellipsis 86 E280A0 ; ## dagger 87 E280A1 ; ## double dagger 88 E282AC ; ## euro 89 E280B0 ; ## per mille 91 E28098 ; ## left single quotation mark 92 E28099 ; ## right single quotation mark 93 E2809C ; ## left double quotation mark 94 E2809D ; ## right double quotation mark 95 E280A2 ; ## bullet 96 E28093 ; ## en dash 97 E28094 ; ## em dash 99 E284A2 ; ## trade mark sign A0 C2A0 ; ## A1 D18E ; ## capital Byelorussian short U A2 D19E ; ## small Byelorussian short u A4 C2A4 ; ## currency sign A5 D290 ; ## capital Ukrainian soft G A6 C2A6 ; ## borken bar A7 C2A7 ; ## section sign A8 D081 ; ## capital YO A9 C2A9 ; ## (C) AA D084 ; ## capital Ukrainian YE AB C2AB ; ## left-pointing double angle quotation mark AC C2AC ; ## not sign AD C2AD ; ## soft hypen AE C2AE ; ## (R) AF D087 ; ## capital Ukrainian YI B0 C2B0 ; ## ° B1 C2B1 ; ## plus-minus sign B2 D086 ; ## capital Ukrainian I B3 D196 ; ## small Ukrainian i B4 D291 ; ## small Ukrainian soft g B5 C2B5 ; ## micro sign B6 C2B6 ; ## pilcrow sign B7 C2B7 ; ## · B8 D191 ; ## small yo B9 E28496 ; ## numero sign BA D194 ; ## small Ukrainian ye BB C2BB ; ## right-pointing double angle quotation mark BF D197 ; ## small Ukrainian yi C0 D090 ; ## capital A C1 D091 ; ## capital B C2 D092 ; ## capital V C3 D093 ; ## capital G C4 D094 ; ## capital D C5 D095 ; ## capital YE C6 D096 ; ## capital ZH C7 D097 ; ## capital Z C8 D098 ; ## capital I C9 D099 ; ## capital J CA D09A ; ## capital K CB D09B ; ## capital L CC D09C ; ## capital M CD D09D ; ## capital N CE D09E ; ## capital O CF D09F ; ## capital P D0 D0A0 ; ## capital R D1 D0A1 ; ## capital S D2 D0A2 ; ## capital T D3 D0A3 ; ## capital U D4 D0A4 ; ## capital F D5 D0A5 ; ## capital KH D6 D0A6 ; ## capital TS D7 D0A7 ; ## capital CH D8 D0A8 ; ## capital SH D9 D0A9 ; ## capital SHCH DA D0AA ; ## capital hard sign DB D0AB ; ## capital Y DC D0AC ; ## capital soft sign DD D0AD ; ## capital E DE D0AE ; ## capital YU DF D0AF ; ## capital YA E0 D0B0 ; ## small a E1 D0B1 ; ## small b E2 D0B2 ; ## small v E3 D0B3 ; ## small g E4 D0B4 ; ## small d E5 D0B5 ; ## small ye E6 D0B6 ; ## small zh E7 D0B7 ; ## small z E8 D0B8 ; ## small i E9 D0B9 ; ## small j EA D0BA ; ## small k EB D0BB ; ## small l EC D0BC ; ## small m ED D0BD ; ## small n EE D0BE ; ## small o EF D0BF ; ## small p F0 D180 ; ## small r F1 D181 ; ## small s F2 D182 ; ## small t F3 D183 ; ## small u F4 D184 ; ## small f F5 D185 ; ## small kh F6 D186 ; ## small ts F7 D187 ; ## small ch F8 D188 ; ## small sh F9 D189 ; ## small shch FA D18A ; ## small hard sign FB D18B ; ## small y FC D18C ; ## small soft sign FD D18D ; ## small e FE D18E ; ## small yu FF D18F ; ## small ya }
Create the file
/etc/nginx/lib/mime.types
and add the following to it:types { text/html html htm shtml; text/css css; text/xml xml; image/gif gif; image/jpeg jpeg jpg; application/javascript js; application/atom+xml atom; application/rss+xml rss; text/mathml mml; text/plain txt; text/vnd.sun.j2me.app-descriptor jad; text/vnd.wap.wml wml; text/x-component htc; image/png png; image/tiff tif tiff; image/vnd.wap.wbmp wbmp; image/x-icon ico; image/x-jng jng; image/x-ms-bmp bmp; image/svg+xml svg svgz; image/webp webp; application/java-archive jar war ear; application/json json; application/mac-binhex40 hqx; application/msword doc; application/pdf pdf; application/postscript ps eps ai; application/rtf rtf; application/vnd.apple.mpegurl m3u8; application/vnd.ms-excel xls; application/vnd.ms-powerpoint ppt; application/vnd.wap.wmlc wmlc; application/vnd.wap.xhtml+xml xhtml; application/vnd.google-earth.kml+xml kml; application/vnd.google-earth.kmz kmz; application/x-7z-compressed 7z; application/x-cocoa cco; application/x-java-archive-diff jardiff; application/x-java-jnlp-file jnlp; application/x-makeself run; application/x-perl pl pm; application/x-pilot prc pdb; application/x-rar-compressed rar; application/x-redhat-package-manager rpm; application/x-sea sea; application/x-shockwave-flash swf; application/x-stuffit sit; application/x-tcl tcl tk; application/x-x509-ca-cert der pem crt; application/x-xpinstall xpi; application/xspf+xml xspf; application/zip zip; application/vnd.oasis.opendocument.chart odc; application/vnd.oasis.opendocument.chart-template otc; application/vnd.oasis.opendocument.database odb; application/vnd.oasis.opendocument.formula odf; application/vnd.oasis.opendocument.formula-template odft; application/vnd.oasis.opendocument.graphics odg; application/vnd.oasis.opendocument.graphics-template otg; application/vnd.oasis.opendocument.image odi; application/vnd.oasis.opendocument.image-template oti; application/vnd.oasis.opendocument.presentation odp; application/vnd.oasis.opendocument.presentation-template otp; application/vnd.oasis.opendocument.spreadsheet ods; application/vnd.oasis.opendocument.spreadsheet-template ots; application/vnd.oasis.opendocument.text-master otm; application/vnd.oasis.opendocument.text odt; application/vnd.oasis.opendocument.text-template ott; application/vnd.oasis.opendocument.text-web oth; application/vnd.openofficeorg.extension oxt; application/vnd.openxmlformats-officedocument.presentationml.presentation pptx; application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx; application/vnd.openxmlformats-officedocument.presentationml.slide sldx; application/vnd.openxmlformats-officedocument.presentationml.template potx; application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx; application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx; application/vnd.openxmlformats-officedocument.wordprocessingml.document docx; application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx; application/vnd.sun.xml.calc sxc; application/vnd.sun.xml.calc.template stc; application/vnd.sun.xml.draw sxd; application/vnd.sun.xml.draw.template std; application/vnd.sun.xml.impress sxi; application/vnd.sun.xml.impress.template sti; application/vnd.sun.xml.math sxm; application/vnd.sun.xml.writer.global sxg; application/vnd.sun.xml.writer sxw; application/vnd.sun.xml.writer.template stw; ## Mime types for web fonts. Stolen from here: ## http://seconddrawer.com.au/blog/ in part. application/x-font-ttf ttf; font/opentype otf; application/vnd.ms-fontobject eot; application/font-woff woff; application/octet-stream bin exe dll; application/octet-stream deb; application/octet-stream dmg; application/octet-stream iso img; application/octet-stream msi msp msm; application/octet-stream vcf; audio/midi mid midi kar; audio/mpeg mpga mpega mp2 mp3; audio/ogg ogg; audio/x-m4a m4a; audio/x-realaudio ra; audio/webm weba; video/3gpp 3gpp 3gp; video/mp2t ts; video/mp4 mp4; video/mpeg mpeg mpg mpe; video/ogg ogv; video/quicktime mov; video/webm webm; video/x-flv flv; video/x-m4v m4v; video/x-mng mng; video/x-ms-asf asx asf; video/x-ms-wmv wmv; video/x-msvideo avi; }
Create the file
/etc/nginx/lib/koi-win
and add the following to it:charset_map koi8-r windows-1251 { 80 88 ; ## euro 95 95 ; ## bullet 9A A0 ; ## 9E B7 ; ## · A3 B8 ; ## small yo A4 BA ; ## small Ukrainian ye A6 B3 ; ## small Ukrainian i A7 BF ; ## small Ukrainian yi AD B4 ; ## small Ukrainian soft g AE A2 ; ## small Byelorussian short u B0 B0 ; ## ° B3 A8 ; ## capital YO B4 AA ; ## capital Ukrainian YE B6 B2 ; ## capital Ukrainian I B7 AF ; ## capital Ukrainian YI B9 B9 ; ## numero sign BD A5 ; ## capital Ukrainian soft G BE A1 ; ## capital Byelorussian short U BF A9 ; ## (C) C0 FE ; ## small yu C1 E0 ; ## small a C2 E1 ; ## small b C3 F6 ; ## small ts C4 E4 ; ## small d C5 E5 ; ## small ye C6 F4 ; ## small f C7 E3 ; ## small g C8 F5 ; ## small kh C9 E8 ; ## small i CA E9 ; ## small j CB EA ; ## small k CC EB ; ## small l CD EC ; ## small m CE ED ; ## small n CF EE ; ## small o D0 EF ; ## small p D1 FF ; ## small ya D2 F0 ; ## small r D3 F1 ; ## small s D4 F2 ; ## small t D5 F3 ; ## small u D6 E6 ; ## small zh D7 E2 ; ## small v D8 FC ; ## small soft sign D9 FB ; ## small y DA E7 ; ## small z DB F8 ; ## small sh DC FD ; ## small e DD F9 ; ## small shch DE F7 ; ## small ch DF FA ; ## small hard sign E0 DE ; ## capital YU E1 C0 ; ## capital A E2 C1 ; ## capital B E3 D6 ; ## capital TS E4 C4 ; ## capital D E5 C5 ; ## capital YE E6 D4 ; ## capital F E7 C3 ; ## capital G E8 D5 ; ## capital KH E9 C8 ; ## capital I EA C9 ; ## capital J EB CA ; ## capital K EC CB ; ## capital L ED CC ; ## capital M EE CD ; ## capital N EF CE ; ## capital O F0 CF ; ## capital P F1 DF ; ## capital YA F2 D0 ; ## capital R F3 D1 ; ## capital S F4 D2 ; ## capital T F5 D3 ; ## capital U F6 C6 ; ## capital ZH F7 C2 ; ## capital V F8 DC ; ## capital soft sign F9 DB ; ## capital Y FA C7 ; ## capital Z FB D8 ; ## capital SH FC DD ; ## capital E FD D9 ; ## capital SHCH FE D7 ; ## capital CH FF DA ; ## capital hard sign }
Create the file
/etc/nginx/lib/koi-utf
and add the following to it:## This map is not a full koi8-r utf8 map: it does not contain ## box-drawing and some other characters. Besides this map contains ## several koi8-u and Byelorussian letters which are not in koi8-r. ## If you need a full and standard map, use contrib/unicode2nginx/koi-utf ## map instead. charset_map koi8-r utf-8 { 80 E282AC ; ## euro 95 E280A2 ; ## bullet 9A C2A0 ; ## 9E C2B7 ; ## · A3 D191 ; ## small yo A4 D194 ; ## small Ukrainian ye A6 D196 ; ## small Ukrainian i A7 D197 ; ## small Ukrainian yi AD D291 ; ## small Ukrainian soft g AE D19E ; ## small Byelorussian short u B0 C2B0 ; ## ° B3 D081 ; ## capital YO B4 D084 ; ## capital Ukrainian YE B6 D086 ; ## capital Ukrainian I B7 D087 ; ## capital Ukrainian YI B9 E28496 ; ## numero sign BD D290 ; ## capital Ukrainian soft G BE D18E ; ## capital Byelorussian short U BF C2A9 ; ## (C) C0 D18E ; ## small yu C1 D0B0 ; ## small a C2 D0B1 ; ## small b C3 D186 ; ## small ts C4 D0B4 ; ## small d C5 D0B5 ; ## small ye C6 D184 ; ## small f C7 D0B3 ; ## small g C8 D185 ; ## small kh C9 D0B8 ; ## small i CA D0B9 ; ## small j CB D0BA ; ## small k CC D0BB ; ## small l CD D0BC ; ## small m CE D0BD ; ## small n CF D0BE ; ## small o D0 D0BF ; ## small p D1 D18F ; ## small ya D2 D180 ; ## small r D3 D181 ; ## small s D4 D182 ; ## small t D5 D183 ; ## small u D6 D0B6 ; ## small zh D7 D0B2 ; ## small v D8 D18C ; ## small soft sign D9 D18B ; ## small y DA D0B7 ; ## small z DB D188 ; ## small sh DC D18D ; ## small e DD D189 ; ## small shch DE D187 ; ## small ch DF D18A ; ## small hard sign E0 D0AE ; ## capital YU E1 D090 ; ## capital A E2 D091 ; ## capital B E3 D0A6 ; ## capital TS E4 D094 ; ## capital D E5 D095 ; ## capital YE E6 D0A4 ; ## capital F E7 D093 ; ## capital G E8 D0A5 ; ## capital KH E9 D098 ; ## capital I EA D099 ; ## capital J EB D09A ; ## capital K EC D09B ; ## capital L ED D09C ; ## capital M EE D09D ; ## capital N EF D09E ; ## capital O F0 D09F ; ## capital P F1 D0AF ; ## capital YA F2 D0A0 ; ## capital R F3 D0A1 ; ## capital S F4 D0A2 ; ## capital T F5 D0A3 ; ## capital U F6 D096 ; ## capital ZH F7 D092 ; ## capital V F8 D0AC ; ## capital soft sign F9 D0AB ; ## capital Y FA D097 ; ## capital Z FB D0A8 ; ## capital SH FC D0AD ; ## capital E FD D0A9 ; ## capital SHCH FE D0A7 ; ## capital CH FF D0AA ; ## capital hard sign }
-
Lets populate
/etc/nginx/key
:Generate DH parameters file with 2048 bit long safe prime:
openssl dhparam 2048 -out /etc/nginx/key/dh_param.pem
Generate HTTP Authentication:
htpasswd /etc/nginx/key/.htpasswd-users admin chown apache. /etc/nginx/key/.htpasswd-users
This command will prompt password for the new user with the name
admin
. -
Lets populate
/etc/nginx/apps
:Create the file
/etc/nginx/drupal/static_files_handler.conf
and add the following to it:## Pagespeed optimized resources that returns 404, redirect to original resource location ~* (.+)/x(.+),(.+)\.pagespeed\.[\.\-_[:alnum:]]+$ { ## Handle resources with query string and Pagespeed optimized resources with ## file name prefixed with x (eg. xMyImage.png,qitok=qwer.pagespeed.asdf.webp) error_page 404 = @orig-resource; set $orig_resource_uri $1/$2?$3; try_files $uri $uri/ $orig_resource_uri; } location ~* (.+),q(.+)\.pagespeed\.[\.\-_[:alnum:]]+$ { ## Handle Pagespeed optimized resources with file name qcache_bypass=123 ## (eg. MyImage.png,qcache_bypass=1472891719.pagespeed.ce.asdf.png) error_page 404 = @orig-resource; set $orig_resource_uri $1?$2; try_files $uri $uri/ $orig_resource_uri; } location ~* (.+),(.+)\.pagespeed\.[\.\-_[:alnum:]]+$ { ## Handle resources with query string error_page 404 = @orig-resource; set $orig_resource_uri $1?$2; try_files $uri $uri/ $orig_resource_uri; } location ~* (.+)/x(.+)\.pagespeed\.[\.\-_[:alnum:]]+$ { ## Handle Pagespeed optimized resources with file name prefixed with x ## (eg. xMyImage.png.pagespeed.asdf.webp) error_page 404 = @orig-resource; set $orig_resource_uri $1/$2; try_files $uri $uri/ $orig_resource_uri; } location ~* (.+)\.pagespeed\.[\.\-_[:alnum:]]+$ { ## Default handler error_page 404 = @orig-resource; set $orig_resource_uri $1; try_files $uri $uri/ $orig_resource_uri; } ## Regular private file serving. location ^~ /system/files/ { include utils/service/php_pass.conf; ## For not signalling a 404 in the error log whenever the ## system/files directory is accessed add the line below. ## Note that the 404 is the intended behaviour. log_not_found off; } ## Trying to access private files directly returns a 404. location ^~ /sites/[\.\-[:alnum:]]+/files/private/ { internal; } location ^~ /sites/[\.\-[:alnum:]]+/private/ { internal; } ## Support for the file_force module ## https://drupal.org/project/file_force. location ^~ /system/files_force/ { include utils/service/php_pass.conf; ## For not signalling a 404 in the error log whenever the ## system/files directory is accessed add the line below. ## Note that the 404 is the intended behaviour. log_not_found off; } ## If accessing an image generated by Drupal 6 imagecache, serve it ## directly if available, if not relay the request to Drupal to (re)generate ## the image. location ~* /imagecache/ { ## Image hotlinking protection. If you want hotlinking ## protection for your images uncomment the following line. include map/hotlinking_protection_allowed_hosts.conf; access_log off; expires 30d; try_files $uri $uri/ @indexphp; } ## Drupal 7 generated image handling, i.e., imagecache in core. See: ## https://drupal.org/node/371374. location ~* /files/styles/ { ## Image hotlinking protection. If you want hotlinking ## protection for your images uncomment the following line. include map/hotlinking_protection_allowed_hosts.conf; access_log off; expires 30d; try_files $uri $uri/ @indexphp; } ## Advanced Aggregation module CSS/JS ## support. https://drupal.org/project/advagg. location ~ ^/sites/[\.\-[:alnum:]]+/files/advagg_(?:css|js)/ { location ~* (?:css|js)[_\-[:alnum:]]+\.(?:css|js)(\.gz)?$ { access_log off; expires max; gzip_static on; add_header ETag ''; add_header Accept-Ranges ''; ## Set a far future Cache-Control header to 52 weeks and add no-transform ## to make Pagespeed bypass these CSS/JS optimized by advagg module add_header Cache-Control 'max-age=31449600, no-transform, public'; ## Inheritance Rules for add_header Directives ## Because this 'server' block contains another 'add_header' directive, ## we must redeclare the 'add_header' from 'http' context include utils/mod_header.conf; add_header Strict-Transport-Security $hsts; try_files $uri $uri/ @indexphp; } } ## All static files will be served directly. location ~* ^.+\.(?:cur|jpe?g|gif|htc|ico|png|txt|otf|ttf|eot|woff|svg|webp|webm|zip|gz|tar|rar)$ { 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; add_header access-control-allow-origin $cors_fix; try_files $uri $uri/ @indexphp; } ## All static files will be served directly. location ~* ^.+\.(?:css|json|js|xml)$ { 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; add_header access-control-allow-origin $cors_fix; set $no_boost_cache 0; include apps/drupal/boost.conf; } ## PDFs and powerpoint files handling. location ~* ^.+\.(?:pdf|pptx?)$ { access_log off; expires 30d; ## No need to bleed constant updates. Send the all shebang in one ## fell swoop. tcp_nodelay off; try_files $uri $uri/ @indexphp; } ## MP3 and Ogg/Vorbis files are served using AIO when supported. Your OS must support it. location ~ ^/sites/[\.\-[:alnum:]]+/files/audio/mp3 { location ~* .*\.mp3$ { access_log off; directio 4k; ## for XFS ## If you're using ext3 or similar uncomment the line below and comment the above. #directio 512; ## for ext3 or similar (block alignments) tcp_nopush off; aio on; output_buffers 1 2M; try_files $uri $uri/ @indexphp; } } location ~ ^/sites/[\.\-[:alnum:]]+/files/audio/ogg { location ~* .*\.ogg$ { access_log off; directio 4k; # for XFS ## If you're using ext3 or similar uncomment the line below and comment the above. #directio 512; ## for ext3 or similar (block alignments) tcp_nopush off; aio on; output_buffers 1 2M; try_files $uri $uri/ @indexphp; } } ## Pseudo streaming of FLV files: ## http://wiki.nginx.org/HttpFlvStreamModule. ## If pseudo streaming isn't working, try to comment ## out in nginx.conf line with: ## add_header X-Frame-Options SAMEORIGIN; location ~ ^/sites/[\.\-[:alnum:]]+/files/video/flv { location ~* .*\.flv$ { access_log off; flv; try_files $uri $uri/ @indexphp; } } ## Pseudo streaming of H264/AAC files. This requires an Nginx ## version greater or equal to 1.0.7 for the stable branch and ## greater or equal to 1.1.3 for the development branch. ## Cf. http://nginx.org/en/docs/http/ngx_http_mp4_module.html. location ~ ^/sites/[\.\-[:alnum:]]+/files/video/mp4 { # videos location ~* .*\.(?:mp4|mov)$ { access_log off; mp4; mp4_buffer_size 1M; mp4_max_buffer_size 5M; try_files $uri $uri/ @indexphp; } } location ~ ^/sites/[\.\-[:alnum:]]+/files/audio/m4a { # audios location ~* .*\.m4a$ { access_log off; mp4; mp4_buffer_size 1M; mp4_max_buffer_size 5M; try_files $uri $uri/ @indexphp; } } ## Advanced Help module makes each module provided README available. location ^~ /help/ { location ~* ^/help/[^/]*/README\.txt$ { access_log off; include utils/service/php_pass.conf; } } ## Replicate the Apache
directive of Drupal standard ## .htaccess. Disable access to any code files. Return a 404 to curtail ## information disclosure. Hide also the text files. location ~* ^(?:.+\.(?:htaccess|gitignore|txt|engine|inc|info|install|make|module|profile|test|po|sh|.*sql|test|theme|twig|tpl(?:\.php)?|xtmpl|yml)(~|\.sw[op]|\.bak|\.orig|\.save)?$|^(/\.(?!well-known).*|/code-style\.pl|/Entries.*|/Repository|/Root|/Tag|/Template|/composer\.(json|lock))$|^#.*#$|/.*\.php(\.sw[op]|\.bak|\.orig|\.save)+)$ { return 404; } ## Disallow access to .bzr, .git, .hg, .svn, .cvs directories: ## return 404 as not to disclose information. location ^~ /.bzr { return 404; } location ^~ /.git { return 404; } location ^~ /.hg { return 404; } location ^~ /.svn { return 404; } location ^~ /.cvs { return 404; } ## Disallow access to patches directory. location ^~ /patches { return 404; } ## Disallow access to drush backup directory. location ^~ /backup { return 404; } ## Disable access logs for robots.txt. location = /robots.txt { access_log off; ## Add support for the robotstxt module ## https://drupal.org/project/robotstxt. try_files $uri $uri/ @indexphp; } ## RSS feed support. location = /rss.xml { try_files $uri $uri/ @indexphp; } ## XML Sitemap support. location = /sitemap.xml { try_files $uri $uri/ @indexphp; } ## Support for favicon. Return an 1x1 transparent GIF if it ## doesn't exist. location = /favicon.ico { expires 30d; try_files /favicon.png @empty; } Create the file
/etc/nginx/drupal/drupal_bootstrap.conf
and add the following to it:## Handle scripts that runs under Drupal bootstrap include utils/service/php_pass.conf; include utils/service/microcache_auth.conf; #include utils/service/microcache.conf;
Create the file
/etc/nginx/drupal/php_handler.conf
and add the following to it:## Handle PHP scripts that does not run under Drupal bootstrap include apps/drupal/drupal_bootstrap.conf; ## Bypass Drupal bootstrap fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param SCRIPT_FILENAME $request_filename; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
We have two options here:
microcache_auth.conf
which uses the Nginx cache for anonymous users only andmicrocache.conf
which uses the Nginx cache for both anonymous and authenticated users. Themicrocache_auth.conf
is enabled by default. Select between the two according to your requirements.Create the file
/etc/nginx/drupal/named_location.conf
and add the following to it:## 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 apps/drupal/drupal_bootstrap.conf; ## Filefield Upload progress ## http://drupal.org/project/filefield_nginx_progress support ## through the NginxUploadProgress modules. #track_uploads uploads 60s; } ## Support for clean URL location @indexphp { #rewrite ^/(.*)$ /index.php?q=$1 last; ## Uncomment this line for Drupal 6 sites and comment this line for Drupal 7 and above sites rewrite ^/(.*)$ /index.php?$query_string last; ## Comment this line for Drupal 6 sites and uncomment this line for Drupal 7 and above sites } ## We define a named location for the Boost cache. location @cache { ## Boost configuration gzip_static on; ## Now for some header tweaking. We use a date that differs ## from stock Drupal. add_header Expires "Tue, 25 Dec 1977 03:45:00 GMT"; ## We bypass all delays in the post-check and pre-check ## parameters of Cache-Control. Both set to 0. add_header Cache-Control "must-revalidate, post-check=0, pre-check=0"; add_header X-DCache "Boost"; ## Inheritance Rules for add_header Directives ## Because this 'server' block contains another 'add_header' directive, ## we must redeclare the 'add_header' from 'http' context include utils/mod_header.conf; add_header Strict-Transport-Security $hsts; ## Boost doesn't set a charset. charset utf-8; ## We try each boost URI in succession, if every one of them ## fails then hand it to Drupal. try_files /cache/normal/$host/$boost_uri${boost_argq}_.html /cache/normal/$host/$boost_uri${boost_argq}_.xml /cache/normal/$host/$boost_uri${boost_argq}_.json /cache/perm/$host/$boost_uri${boost_argq}_.js /cache/perm/$host/$boost_uri${boost_argq}_.css; } ## Return an in memory 1x1 transparent GIF. location @empty { expires 30d; empty_gif; } ## Redirect Pagespeed optimized resources that returns 404 to ## original resource. location @orig-resource { return 302 $scheme://$server_name$orig_resource_uri; }
Create the file
/etc/nginx/drupal/drupal_upload_progress.conf
and add the following to it:## Drupal 7 configuration for the Nginx Upload Progress module: ## https://github.com/masterzen/nginx-upload-progress-module ## This requires the Filefield Nginx Progress module: ## https://drupal.org/project/filefield_nginx_progress. ## The Nginx module wants ?X-Progress-ID query parameter so ## that it report the progress of the upload through a GET ## request. But the drupal form element makes use of clean ## URLs in the POST. location ~ (?
.*)/x-progress-id:(? \d*) { rewrite ^ $upload_form_uri?X-Progress-ID=$upload_id; } ## Now the above rewrite must be matched by a location that ## activates it and references the above defined upload ## tracking zone. location ^~ /progress { upload_progress_json_output; report_uploads uploads; } Create the file
/etc/nginx/drupal/drupal_install.conf
and add the following to it:## Directives for installing drupal. This is for drupal 6 and 7. location = /install.php { auth_basic "Restricted Access"; # auth realm auth_basic_user_file key/.htpasswd-users; # htpasswd file include apps/drupal/php_handler.conf; } ## This is for drupal 8. location = /core/install.php { auth_basic "Restricted Access"; # auth realm auth_basic_user_file key/.htpasswd-users; # htpasswd file include apps/drupal/php_handler.conf; }
Create the file
/etc/nginx/drupal/drupal_cron_update.conf
and add the following to it:## Configuration file for Drupal if you're not using drush to update your site ## or run cron. ## XMLRPC. Comment out if not enabled. location = /xmlrpc.php { include apps/drupal/php_handler.conf; } ## Restrict cron access to a specific host. location = /cron.php { ## If not allowed to run cron then issue a 404 and redirect to the ## site root. if ($not_allowed_cron) { return 404 /; } include apps/drupal/php_handler.conf; } ## Run the update from the web interface with Drupal 7. location = /authorize.php { include apps/drupal/php_handler.conf; } location = /update.php { auth_basic "Restricted Access"; # auth realm auth_basic_user_file key/.htpasswd-users; # htpasswd file include apps/drupal/php_handler.conf; }
Create the file
/etc/nginx/drupal/core.conf
and add the following to it:## Nginx configuration for Drupal ## Common Nginx configuration for server context include apps/drupal/common_server_context.conf; ## Named location include apps/drupal/named_location.conf; ## The 'default' location. location / { ## Let Drupal handle 404. error_page 404 /index.php; ## Drupal generated static files include apps/drupal/static_files_handler.conf; ## Determine if Drupal Boost may apply include apps/drupal/boost.conf; } ## Drupal index, install, update, boost stats. location ~* ^/(?:index|boost_stats)\.php { include apps/drupal/php_handler.conf; } ## Uncomment the line below if you want to enable basic auth for ## access to all /admin URIs. Note that this provides much better ## protection if use HTTPS. Since it can easily be eavesdropped if you ## use HTTP. #include apps/drupal/admin_basic_auth.conf; ## Any other attempt to access PHP files returns a 404. location ~* ^.+\.php$ { return 404; }
Create the file
/etc/nginx/drupal/common_server_context.conf
and add the following to it:## Common to all hosts Nginx configurations for server context ## See the blacklist.conf file at the parent dir: /etc/nginx. ## Deny access based on the User-Agent header. if ($bad_bot) { return 444; } ## Deny access based on the Referer header. if ($bad_referer) { return 444; } ## Protection against illegal HTTP methods. Out of the box only HEAD, ## GET and POST are allowed. if ($not_allowed_method) { return 405; } ## Limits ## limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=60r/s + limit_req zone=req_limit_per_ip burst=5 nodelay ## - Set shared memory as 10MB ## - Limit requests per IP as following ## - Set maximum requests as rate * burst in burst seconds ## For example, maximum value is 300(=60*5) requests in 5 seconds in this case ## - With nodelay option : Nginx would return 503 response and not handle excessive requests ## - Without nodelay option : Nginx would wait (no 503 response) and handle excessive requests with some delay ## limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m + limit_conn conn_limit_per_ip 30 ## - Set shared memory as 10MB ## - Limit connections per IP as 30 in this case ## - Note that normal browser makes 2~8 connections and SPDY protocol split each connections ## - Nginx would return 503 response if connection exceeds this value limit_conn connlimit 32; limit_req zone=reqlimit burst=5 nodelay; ## PageSpeed filters ## Uncomment the line below if Google PageSpeed module is present #include apps/pagespeed/optimize.conf;
Create the file
/etc/nginx/drupal/boost.conf
and add the following to it:## Error page handler for the case where $no_boost_cache is 1, POST ## request or authenticated. error_page 419 = @indexphp; ## If $no_boost_cache is 1 then it means that Boost session cookie ## is present or uri has wrong dir. So serve the dynamic page. if ($no_boost_cache) { return 419; ## I'm a teapot/I can't get no cachifaction } ## No caching for POST requests. if ($request_method = POST) { return 419; } ## Handler to redirect to boost cache named location. error_page 420 = @cache; ## Check if static boost cache file already generated. if (-f $document_root/cache/normal/$host/$boost_uri${boost_argq}_.html) { ## Redirect to boost cache named location. return 420; } if (-f $document_root/cache/normal/$host/$boost_uri${boost_argq}_.xml) { ## Redirect to boost cache named location. return 420; } if (-f $document_root/cache/normal/$host/$boost_uri${boost_argq}_.json) { ## Redirect to boost cache named location. return 420; } if (-f $document_root/cache/perm/$host/$boost_uri${boost_argq}_.js) { ## Redirect to boost cache named location. return 420; } if (-f $document_root/cache/perm/$host/$boost_uri${boost_argq}_.css) { ## Redirect to boost cache named location. return 420; } ## No Boost cache file generated yet. try_files $uri $uri/ @indexphp;
Populate the
/etc/nginx/apps/pagespeed
folder under this guide.To enable Google PageSpeed in your Nginx configuration (make sure first that your Nginx is compiled with PageSpeed module), uncomment the line seen below at
/etc/nginx/nginx.conf
:include apps/pagespeed/core.conf;
... also uncomment the line seen below at
/etc/nginx/apps/drupal/common_server_context.conf
:include apps/pagespeed/optimize.conf;
... and uncomment the line seen below at
/etc/nginx/site-available/template.conf
:pagespeed ShardDomain $scheme://$server_name $scheme://s1.{DOM},$scheme://s2.{DOM};
-
To enable this Nginx reverse proxy for Apache setup, execute the following:
ln -s /etc/nginx/utils/apache /etc/nginx/utils/service
On the other hand, if PHP FPM backend is your setup, execute the following:
ln -s /etc/nginx/utils/fastcgi /etc/nginx/utils/service
-
Set permission:
chmod -R -x /etc/nginx chmod +x /etc/nginx/lib/ /etc/nginx/apps/ /etc/nginx/apps/drupal/ /etc/nginx/apps/pagespeed/ /etc/nginx/key/ /etc/nginx/sites-available/ /etc/nginx/sites-available/admin/ /etc/nginx/sites-available/dev/ /etc/nginx/sites-available/targeted_server_config/ /etc/nginx/sites-enabled/ /etc/nginx/utils/ /etc/nginx/utils/apache/ /etc/nginx/utils/fastcgi/ /etc/nginx/map/ /etc/nginx/
-
Restart Nginx:
systemctl restart nginx
Setup Nginx requirements
-
In this tutorial the Apache will use port 8080 and lets open this port to become accessible:
iptables -I INPUT -p tcp -m tcp --dport 8080 -j ACCEPT iptables --line -vnL service iptables save service iptables restart
-
Create the Nginx cache path folder:
mkdir /var/cache/nginx/microcache chown apache:root /var/cache/nginx/microcache chmod 700 /var/cache/nginx/microcache
-
Create Nginx logrotate script:
vi /etc/logrotate.d/websites_nginx_logs.conf
Content:
/var/log/virtualmin/*nginx_access_log /var/log/virtualmin/*nginx_error_log { rotate 10 missingok daily compress postrotate service httpd graceful ; sleep 5 endscript sharedscripts }
Configure Apache
-
Since Nginx is reverse proxy to Apache, the IP address that Apache will get is the IP of the server and we need to correct that. Apache 2.4 and above do have mod_remoteip and we will use that module. Open mod_remoteip's configuration file:
vi /etc/httpd/conf.d/remoteip.conf
Add the following codes:
# mod_remoteip settings RemoteIPHeader X-Real-IP RemoteIPInternalProxy 127.0.0.1 RemoteIPInternalProxy 188.8.8.8
Note: change 188.8.8.8 to your server's IP address.
-
Change the port of Apache:
vi /etc/httpd/conf/httpd.conf
Look for:
Listen 80
... and change to:
Listen 8080
-
Restart Apache:
systemctl restart httpd
Configure Virtualmin
-
Set the virtual server template to listen to 8080. Login to Virtualmin, go to "System Settings" -> "Server Templates" -> "Default Settings" and select from the dropdown "Apache Website". Change the "Port number for virtual hosts" from 80 to 8080. Restart webmin:
systemctl restart webmin
-
Lets build the script that will automate the creation of website virtual host Nginx configuration file each time Virtualmin created a new server.
Create the file
/usr/local/bin/virtualmin.sh
and add the following to it:#!/bin/sh function update_nginx_conf { cat /etc/nginx/sites-available/${TEMPLATE_FILENAME} > $NGINX_CONF_FILE perl -pi -e "s#{DOM}#${VIRTUALSERVER_DOM}#g" $NGINX_CONF_FILE perl -pi -e "s#{HOME}#${VIRTUALSERVER_HOME}#g" $NGINX_CONF_FILE cat /etc/nginx/sites-available/${TEMPLATE_FILENAME_SSL} > $NGINX_CONF_FILE_SSL perl -pi -e "s#{DOM}#${VIRTUALSERVER_DOM}#g" $NGINX_CONF_FILE_SSL perl -pi -e "s#{HOME}#${VIRTUALSERVER_HOME}#g" $NGINX_CONF_FILE_SSL if [ -f "/etc/nginx/sites-available/targeted_server_config/${VIRTUALSERVER_DOM}.conf" ] then perl -pi -e "s#{TARGETED_SERVER_CONFIG}#include sites-available/targeted_server_config/${VIRTUALSERVER_DOM}.conf;#g" $NGINX_CONF_FILE perl -pi -e "s#{TARGETED_SERVER_CONFIG}#include sites-available/targeted_server_config/${VIRTUALSERVER_DOM}.conf;#g" $NGINX_CONF_FILE_SSL else perl -pi -e "s#{TARGETED_SERVER_CONFIG}##g" $NGINX_CONF_FILE perl -pi -e "s#{TARGETED_SERVER_CONFIG}##g" $NGINX_CONF_FILE_SSL fi } NGINX_CONF_FILENAME="${VIRTUALSERVER_DOM}.conf" NGINX_CONF_FILE="/etc/nginx/sites-available/prod/${NGINX_CONF_FILENAME}" NGINX_CONF_FILENAME_SSL="${VIRTUALSERVER_DOM}_ssl.conf" NGINX_CONF_FILE_SSL="/etc/nginx/sites-available/prod/${NGINX_CONF_FILENAME_SSL}" TEMPLATE_FILENAME=template.conf TEMPLATE_FILENAME_SSL=template_ssl.conf if [ "$VIRTUALSERVER_ACTION" = "CREATE_DOMAIN" ] then if [ "${VIRTUALSERVER_WEB}" = "1" ] then update_nginx_conf if [ "${VIRTUALSERVER_SSL}" = "1" ] then ln -s $NGINX_CONF_FILE_SSL /etc/nginx/sites-enabled/${NGINX_CONF_FILENAME_SSL} else ln -s $NGINX_CONF_FILE /etc/nginx/sites-enabled/${NGINX_CONF_FILENAME} fi if [ -f "/home/${VIRTUALSERVER_USER}/etc/dav.digest.passwd" ] then cat /home/$VIRTUALSERVER_USER/etc/dav.digest.passwd >> /etc/nginx/key/.htpasswd-users fi /usr/sbin/nginx -s reload fi elif [ "$VIRTUALSERVER_ACTION" = "DELETE_DOMAIN" ] then if [ "${VIRTUALSERVER_WEB}" = "1" ] then rm -f /etc/nginx/sites-enabled/${VIRTUALSERVER_DOM}.conf /etc/nginx/sites-enabled/${VIRTUALSERVER_DOM}_ssl.conf rm -f /etc/nginx/sites-available/prod/${VIRTUALSERVER_DOM}.conf /etc/nginx/sites-available/prod/${VIRTUALSERVER_DOM}_ssl.conf rm -f /var/log/virtualmin/${VIRTUALSERVER_DOM}_nginx_* /usr/sbin/nginx -s reload fi elif [ "$VIRTUALSERVER_ACTION" = "MODIFY_DOMAIN" ] then if [ "${VIRTUALSERVER_WEB}" = "1" ] then if [ ! -f $NGINX_CONF_FILE ] then update_nginx_conf fi fi if [ "$VIRTUALSERVER_DOM" != "$VIRTUALSERVER_OLDSERVER_DOM" ] then if [ "${VIRTUALSERVER_WEB}" = "1" ] then rm -f /etc/nginx/sites-available/prod/${VIRTUALSERVER_OLDSERVER_DOM}.conf /etc/nginx/sites-available/prod/${VIRTUALSERVER_OLDSERVER_DOM}_ssl.conf rm -f /etc/nginx/sites-enabled/${VIRTUALSERVER_OLDSERVER_DOM}.conf /etc/nginx/sites-enabled/${VIRTUALSERVER_OLDSERVER_DOM}_ssl.conf update_nginx_conf if [ "${VIRTUALSERVER_SSL}" = "1" ] then ln -s $NGINX_CONF_FILE_SSL /etc/nginx/sites-enabled/${NGINX_CONF_FILENAME_SSL} else ln -s $NGINX_CONF_FILE /etc/nginx/sites-enabled/${NGINX_CONF_FILENAME} fi fi fi if [ "${VIRTUALSERVER_WEB}" = "1" ] then /usr/sbin/nginx -s reload fi fi
Make the script executable:
chmod u+x /usr/local/bin/virtualmin.sh
-
Let Virtualmin know about the virtualmin.sh. Login to Virtualmin, go to "System Settings" -> "Virtualmin Configuration" and select from dropdown "Actions upon server and user creation". Populate the "Command to run after making changes to a server" field with:
/usr/local/bin/virtualmin.sh
For PHP FPM setup, follow this guide: Setup PHP FPM for Nginx.
Comments
Yes, change it to your…
Yes, change it to your server's IP address. Thank you for pointing that out.
Followed you guide, Nginx 403 error
Hello, thanks for this guide, i followed it and have error Nginx error 403 (forbidden) on any virtual server. Apache is running on port 8000 and the document root is ok, but Nginx can't access any file (403 forbidden). Any suggestion?
arpeggio
Tue, 03/15/2016 - 07:33
In reply to Followed you guide, Nginx 403 error by Mark (not verified)
Two optional solutions
Hi, you're welcome. We have two options:
Option 1:
Edit the main Nginx file /etc/nginx/nginx.conf
and change the upstream IP address from 127.0.0.1
to your server's assigned IP address (as example lets use 188.8.8.8
), below is the part of the script that contains "upstream":
upstream phpapache {
## Use the least connection algorithm for load balancing
least_conn;
server 188.8.8.8:8000;
keepalive 5;
}
... and make sure that your website's domain have the server's assigned IP address in /etc/hosts
, example:
188.8.8.8 webfoobar.com
188.8.8.8 www.webfoobar.com
Option 2:
Please check the permission of every parent directory of the file(s) that nginx trying to access, eg. if the file is at /home/dev/public_html/index.php execute:
namei -om /home/dev/public_html
... it will show all the permissions on that path. Make sure that the each parent directory has x permission. For example if you see the /home directory permission is 754, try to:
chmod o+x /home
not using drupal
hi,
i came across your post while researching installing nginx as a reverse proxy to apache using virtualmin. i'm pretty new to vps.
if i'm not using drupal, can i omit all the drupal references and file structures? For example:
/etc/nginx/nginx.conf: # include map/drupal_external_cache.conf;
/etc/nginx/utils/apache/php_pass.conf: #proxy_hide_header 'X-Drupal-Cache';
#proxy_hide_header 'X-Generator';
/etc/nginx/sites-available/template_ssl.conf: #include apps/drupal/core.conf;
Re: not using drupal
Hi,
Yes, you can omit all the drupal reference.
/etc/nginx/nginx.conf: # include map/drupal_external_cache.conf;
/etc/nginx/utils/apache/php_pass.conf: #proxy_hide_header 'X-Drupal-Cache';
#proxy_hide_header 'X-Generator';
/etc/nginx/sites-available/template_ssl.conf: #include apps/drupal/core.conf; include apps/drupal/common_server_context.conf; include apps/drupal/named_location.conf;
If you wish to get the full performance of this nginx application, use the scripts under apps/drupal/
as reference to create support for your CMS or other application.
WordPress
boss how about for WordPress ?
You can omit all the Drupal references…
You can omit all the Drupal references.
/etc/nginx/nginx.conf: # include map/drupal_external_cache.conf;
/etc/nginx/utils/apache/php_pass.conf: #proxy_hide_header 'X-Drupal-Cache';
#proxy_hide_header 'X-Generator';
/etc/nginx/sites-available/template_ssl.conf: #include apps/drupal/core.conf; include apps/drupal/common_server_context.conf; include apps/drupal/named_location.conf;
But if you are keen in customizing nginx configurations and want to get the full performance of this nginx application, use the scripts under apps/drupal/
as reference to develop nginx configuration support for WordPress.
Jango (not verified)
Fri, 12/16/2016 - 13:52
In reply to You can omit all the Drupal references… by arpeggio
Thanks
Thank you boss i will try this setup
nginx for remote download servers
hi what would be the best configuration for setting a server for remote download hosts..
admin
Sun, 12/25/2016 - 01:11
In reply to nginx for remote download servers by Amanat (not verified)
Hi, you can use as reference…
Hi, you can use as reference the following code snippet which is in nginx configuration static_files_handler.conf
above.
## PDFs and powerpoint files handling.
location ~* ^.+\.(?:pdf|pptx?)$ {
access_log off;
expires 30d;
## No need to bleed constant updates. Send the all shebang in one
## fell swoop.
tcp_nodelay off;
try_files $uri $uri/ @drupal;
}
Help in using config
Hi, Ronald!
Hope, you are doing well)
I am trying to use your article to tune nginx(as reverse proxy for apache) on Linode server.
I found configuration inaccuracy in file /etc/nginx/nginx.conf.
String "include utils/service/upstream.conf;" the directory structure doesn't have directory "service", only "apache" and "fastcgi".
And string "include map/x_forwarded_proto.conf;" There is no mention that inside this file.
Can you explain me, please, how to correct this?
Switch between reverse proxy to Apache and PHP FPM backends
Hi Oleg,
Yes, thank you. Hope you're doing well too :)
One of the features of this configuration is "Seamless upstream switch between reverse proxy to Apache and PHP FPM backends."
The /etc/nginx/utils/service
should be a symbolic link that links to either /etc/nginx/utils/apache
or /etc/nginx/utils/fastcgi
so choosing between the two on which to link depends on your setup. Under "Configure Nginx" section on step 11, we have instruction if Nginx reverse proxy for Apache setup execute:
ln -s /etc/nginx/utils/apache /etc/nginx/utils/service
If PHP FPM backend is your setup, execute:
ln -s /etc/nginx/utils/fastcgi /etc/nginx/utils/service
In your case, choose the first one. If happens in the future you have decided to setup PHP FPM as your backend, you can easily switch from Apache to PHP FPM nginx configurations by just deleting the symbolic link /etc/nginx/utils/service
and execute the second one above.
In the case of "include map/x_forwarded_proto.conf;", I have missed the one (thank you for pointing that out). Create /etc/nginx/map/x_forwarded_proto.conf
and add the following to it:
## Support the X-Forwarded-Proto header for fastcgi.
map $http_x_forwarded_proto $fastcgi_https {
default $https;
http '';
https on;
}
Oleg (not verified)
Mon, 01/16/2017 - 15:34
In reply to Switch between reverse proxy to Apache and PHP FPM backends by arpeggio
Switch between reverse proxy to Apache and PHP FPM backends
Thanks for the detailed and timely response.
arpeggio
Mon, 01/16/2017 - 16:20
In reply to Switch between reverse proxy to Apache and PHP FPM backends by Oleg (not verified)
You are welcome Oleg :)
You are welcome Oleg :)
apps/pagespeed/core.conf
Hello and Thank You Lot for your useful article.
after doing instructions in this article: https://www.webfoobar.com/node/27 (setup pagespeed module), I test my configuration of nginx and find error: core.conf not exist in /etc/nginx/apps/pagespeed/
[root@ns ~]# nginx -t -c /etc/nginx/nginx.conf
nginx: [emerg] open() "/etc/nginx/apps/pagespeed/core.conf" failed (2: No such file or directory) in /etc/nginx/nginx.conf:204
nginx: configuration file /etc/nginx/nginx.conf test failed
arpeggio
Sat, 10/07/2017 - 12:54
In reply to apps/pagespeed/core.conf by Hamid Araghi (not verified)
Skipped "Using Pagespeed with Nginx" instructions
Hi, you're welcome. You must have skipped to follow the steps in Using Pagespeed with Nginx.
PHP files
Hello,
Thanks for this guide.
Files with php extension are downloading instead of displaying.
Setup is with FPM.
Can you help?
Thanks
Nginx fails to start
good day, hope you are well. I have followed your guide, however nginx fails to start
● nginx.service - The nginx HTTP and reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
Active: failed (Result: exit-code) since Tue 2019-01-15 20:47:17 EST; 28s ago
Process: 25182 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=1/FAILURE)
Process: 25181 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS)
Main PID: 29339 (code=exited, status=0/SUCCESS)
Jan 15 20:47:17 vps220319.vps.ovh.ca systemd[1]: Starting The nginx HTTP and reverse proxy server...
Jan 15 20:47:17 vps220319.vps.ovh.ca nginx[25182]: nginx: [emerg] pcre_compile() failed: unrecognized character after (? or (?- in "SESS[[:alnum:]]+=....conf:53
Jan 15 20:47:17 vps220319.vps.ovh.ca nginx[25182]: nginx: configuration file /etc/nginx/nginx.conf test failed
Jan 15 20:47:17 vps220319.vps.ovh.ca systemd[1]: nginx.service: control process exited, code=exited status=1
Jan 15 20:47:17 vps220319.vps.ovh.ca systemd[1]: Failed to start The nginx HTTP and reverse proxy server.
Jan 15 20:47:17 vps220319.vps.ovh.ca systemd[1]: Unit nginx.service entered failed state.
Jan 15 20:47:17 vps220319.vps.ovh.ca systemd[1]: nginx.service failed.
Hint: Some lines were ellipsized, use -l to show in full.
[root@vps220319 ~]# systemctl restart nginx
Job for nginx.service failed because the control process exited with error code . See "systemctl status nginx.service" and "journalctl -xe" for details.
In your file /etc/nginx/map…
In your file /etc/nginx/map/drupal_external_cache.conf
, you have missed <session_id>
in ~SESS[[:alnum:]]+=(?<session_id>[[:graph:]]+) $session_id;
. Here is the content of /etc/nginx/map/drupal_external_cache.conf
should look like:
## Testing if we should be serving content from cache or not. This is
## needed for any Drupal setup that uses an external cache.
## Let Ajax calls go through.
map $uri $no_cache_ajax {
default 0;
/system/ajax 1;
}
## Test Boost session cookie being present. If there is, then no
## caching is to be done.
map $http_cookie $no_boost_cache_cookie {
default 0;
~DRUPAL_UID 1;
#~nocache=1 1; # Custom logged in/out indicator
}
## Boost URI watch list
map $request_uri $no_boost_cache_uri {
default 0;
~*^/(admin|cache|misc|modules|sites|system|openid|themes|node/add|comment/reply)|(/(edit|user|user/(login|password|register)))$ 1;
}
## Combine both results to get the cache bypassing mapping.
map $no_boost_cache_cookie$no_boost_cache_uri $no_boost_cache {
default 1;
00 0;
}
## Testing for the session cookie being present. If there is, then no
## caching is to be done. Note that this is for someone using either
## Drupal 7 pressflow or stock Drupal 6 core with no_anon
## (https://drupal.org/project/no_anon).
map $http_cookie $no_cache_cookie {
default 0;
~SESS 1; # PHP session cookie
#~nocache=1 1; # Custom logged in/out indicator
}
## Combine both results to get the cache bypassing mapping.
map $no_cache_ajax$no_cache_cookie $no_auth_cache {
default 1;
00 0;
}
## Cache bypassing mapping (auth).
map $no_cache_ajax $no_cache {
default 0;
1 1;
}
## Set a cache_uid variable for authenticated users.
map $http_cookie $cache_uid {
default nil;
~SESS[[:alnum:]]+=(?<session_id>[[:graph:]]+) $session_id;
}
I get forbidden error for wp-login.php
Hi,
I am getting forbidden error (403) on wp-login.php page after using nginx as reverse proxy with apache in wordpress.
can you please help me fix it?
Thank you very much.
arpeggio
Tue, 11/26/2019 - 18:42
In reply to I get forbidden error for wp-login.php by S Roy (not verified)
Check error log
First of all, let me say that I don't have experience in wordpress but I will try to help in nginx/apache side. I suggest to check the error log generated by nginx and apache to get clue to solve this. Btw, only the wp-login.php page is getting this forbidden error (403)?
Questions in 2020
Hello, thank you very much for this article. I'm trying to config Virtualmin + Apache + Nginx Pack (nginx + PHP-FPM + PageSpeed) as Reverse proxy. But I'm stuck. To understand why I'm stuck I need first to clarify some questions. So, please can you explain me those questions?
1) I'm installing Nginx Reverse Proxy over a already working Virtualmin+Apache system with SSL. So, I generated the Nginx SSL according to this article and the other one you mention on this article. Now I need to understand what I need to make with the old SSL generated in the Apache+Virtualmin system. Do I need to revoke it? Do I need to generate it again - now in port 8080?
NOTE: If I try to run the Virtualmin Apache SSL Certificate again over port 8080 I get this:
DNS-based validation failed : Failed to request certificate :
usage: acme_tiny.py [-h] --account-key ACCOUNT_KEY --csr CSR --acme-dir
ACME_DIR [--quiet] [--disable-check]
[--directory-url DIRECTORY_URL] [--ca CA]
[--contact [CONTACT [CONTACT ...]]]
acme_tiny.py: error: argument --acme-dir is required
Zero tutorials cover this. Maybe it is something very easy to understand that I coldn't yet.
2) I saw some Nginx Reverse Proxy tutorials that uses the proxy-pass command inside the "sites-available **domains**.conf". And they change from the port 80 to 8080 for non-ssl sites, as from the 433 to 8433 for ssl sites as well. I can't see this on this tutorial code. Is because it is an old code, or is this just another way to do this - that keep working those days?
Cheers.
Reverse proxy
You're welcome. The answers:
-
You don't need to generate SSL for Apache as this article assumed that Nginx and Apache are running on same server so SSL is only needed on Nginx. The communication between Nginx and Apache need not be encrypted.
-
When you created the
/etc/nginx/utils/apache/upstream.conf
as instructed in this article, you will see the 8080:## Upstream configuration for Apache functioning has a PHP handler. ## Add as many servers as needed. ## Cf. http://wiki.nginx.org/HttpUpstreamModule. ## Note that this configuration assumes by default that keepalive ## upstream connections are supported and that you have a Nginx ## version with the fair load balancer. upstream phpapache { ## Use the least connection algorithm for load balancing. This ## algorithm was introduced in versions 1.3.1 and 1.2.2. least_conn; server 127.0.0.1:8080; #server 127.0.0.1:8081; ## Create a backend connection cache. Note that this requires ## Nginx version greater or equal to 1.1.4. ## Cf. http://nginx.org/en/CHANGES. keepalive 5; }
Hello, thank you for the…
Hello, thank you for the answers.
I wasgetting conflict btween nginx and httpd service under the port 443, so what I did was:
- Went to Virtualmin and turned off SSL on every virtual server.
- In Virtualmin I changed the PHP script from Apache PHP-FPM to mod_php on every virtual server.
But when I run nginx status service I see:
Mar 22 02:53:22 gullis nginx[6273]: nginx: [warn] conflicting server name "fuzzyexpress.com" on my-ipv4-ip:80, ignored
So, what I did was:
● nginx.service - nginx - high performance web server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
Active: active (running) since Sun 2020-03-22 02:53:23 CET; 10min ago
Docs: http://nginx.org/en/docs/
Process: 6268 ExecStop=/bin/kill -s TERM $MAINPID (code=exited, status=0/SUCCESS)
Process: 6273 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=0/SUCCESS)
Main PID: 6276 (nginx)
CGroup: /system.slice/nginx.service
├─6276 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.con
├─6277 nginx: worker process
├─6278 nginx: worker process
└─6279 nginx: cache manager process
Mar 22 02:53:22 gullis nginx[6273]: nginx: [warn] conflicting server name "page2.com" on my-ipv4-ip:80, ignored
Mar 22 02:53:22 gullis nginx[6273]: nginx: [warn] conflicting server name "page1.com" on my-ipv4-ip:80, ignored
Mar 22 02:53:22 gullis nginx[6273]: nginx: [warn] conflicting server name "page1.com" on my-ipv4-ip:80, ignored
Mar 22 02:53:22 gullis nginx[6273]: nginx: [warn] conflicting server name "page3.com" on [my-ipv6-ip]:80, ignored
Mar 22 02:53:22 gullis nginx[6273]: nginx: [warn] conflicting server name "page3.com" on [my-ipv6-ip]:80, ignored
Mar 22 02:53:22 gullis nginx[6273]: nginx: [warn] conflicting server name "page2.com" on [my-ipv6-ip]:80, ignored
Mar 22 02:53:22 gullis nginx[6273]: nginx: [warn] conflicting server name "page2.com" on [my-ipv6-ip]:80, ignored
Mar 22 02:53:22 gullis nginx[6273]: nginx: [warn] conflicting server name "page1.com" on [my-ipv6-ip]:80, ignored
Mar 22 02:53:22 gullis nginx[6273]: nginx: [warn] conflicting server name "page1.com" on [my-ipv6-ip]:80, ignored
Mar 22 02:53:23 gullis systemd[1]: Started nginx - high performance web server.
All the websites are offiline
The strange item I get in the nginx error log was
2020/03/21 17:26:54 [error] 9043#9258: [ngx_pagespeed 1.13.35.2-0] AprMemCache::Get error: Connection refused (111) on key rname/aj_jBlhBdvgCjkNGMsXy08p/http://fuzzyexpress.com/@@_
2020/03/21 17:26:54 [error] 9043#9259: [ngx_pagespeed 1.13.35.2-0] AprMemCache::Put error: Could not find specified socket in poll list. (70015) on key prop_page/http://fuzzyexpress.com/_jBlhBdvgCj@Desktop@beacon_cohort, value-size 71
I can't understand what is happening.
memcached service
Hello, please check if your memcached service is running. Thanks.
Hello, yes, the memcache was…
Hello, yes, the memcache was not intalled. Sorry about that. I just installed it and it is running ok now. The memcache issue just stopped.
But the nginx issue name server conflict I said before still exist.
When I try to run the pages (1 in wordpress, the orther 2 pages are just a simple index.html or index.php for now) - i already commented the drupal includes
and i got this browser error message:
The page isn’t redirecting properly
Firefox has detected that the server is redirecting the request for this address in a way that will never complete.
This problem can sometimes be caused by disabling or refusing to accept cookies.
arpeggio
Mon, 03/23/2020 - 17:32
In reply to Hello, yes, the memcache was… by still offline (not verified)
Review
Please review all your Nginx configuration files that contains server_name
directive. You must have some duplicate domain entries.
As for the "The page isn’t redirecting properly" issue, please review the article above you might have missed the part creating the /etc/nginx/drupal/php_handler.conf
. Or please check this article that I have created last month.
Thank you again for the…
Thank you again for the answers.
THe handler config is ok.
Abour the server_name, i read a little and the solution I see is if we have "server_name example.com www.example.com;" we need to change decide witch one we want.
So, I took one of my simples pages and force all the 2 options domain to just "server_name example.com;", even the non-ssl file first server-names lines with server_name s1.{DOM} s2.{DOM} s3.{DOM} s4.{DOM}; I had force it to "server_name example.com;"
When I do this, stop the many redirects error and I got 403 Forbiden (I I already did the 403 forbidden steps you said on the comments above - I already did both options) and still the 403 forbidden
About the article you created last month, sorry I didnt understand where to put the new location code.
You're welcome. The "server…
You're welcome. The "server_name example.com www.example.com;" is fine because example.com is different from www.example.com. What I mean is please review your Nginx configuration files that you might have declared exactly same domain name that you might have missed out like you have declared "server_name example.com" and on other file you declared "server_name example.com" again for the second time.
Please try this out, temporarily append the following at your php_pass.conf
file:
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
If this works, it means your HTTP requests are all trying to serve under Drupal bootstrap even if those don't need it. The codes above should bypass the Drupal bootstrap setup so all you need to do is to add the above codes to where Drupal bootstrap setup not needed like sites that are not Drupal.
On the other hand if the codes above does not work, please check your logs for hints to solve your issue.
Anonymous (not verified)
Wed, 03/25/2020 - 03:10
In reply to You're welcome. The "server… by arpeggio
Thank you again. I added…
Thank you again. I added these lines to /etc/nginx/utils/fastcgi/php_pass.conf - restarted nginx - nothing happned. Same browser error.
The nginx error log just show me the name server conflict.
I look all the files and the only one that have name server code is the available-site/*domains*.conf
This is the main name server structure in the domains.conf and domains_ssl.conf (just change {DOM} for each domain on each domain file):
NON-SSL File
------------
------------
## Redirect HTTPS to HTTP (Domains used for static resource).
server {
...
server_name s1.{DOM} s2.{DOM} s3.{DOM} s4.{DOM};
...
}
## Domains used for static resource.
server {
...
server_name s1.{DOM} s2.{DOM} s3.{DOM} s4.{DOM};
...
}
## Redirect HTTPS to HTTP (Main server).
server {
...
server_name {DOM} www.{DOM};
...
}
## Redirect domain with prefixed www sub-domain.
server {
...
server_name {DOM};
...
}
## Main server.
server {
...
server_name {DOM};
...
}
SSL File
------------
------------
## Nginx configuration for {DOM}.
## Redirect HTTP to HTTPS.
server {
...
server_name {DOM} www.{DOM};
...
}
## HTTPS (Redirect domain with prefixed www sub-domain).
server {
...
server_name {DOM};
...
}
## HTTPS (Main server).
server {
...
server_name {DOM};
...
}
I have no clue how to make it to work.
Check for helpful logs
No prob. Note: the server name issue you have is not an error but it is a warning meaning your configuration will still work without fixing it.
Mar 22 02:53:22 gullis nginx[6273]: nginx: [warn] conflicting server name "page2.com" on my-ipv4-ip:80, ignored
Anyway, please make sure in all your configuration files that your SSL blocks has server names specified.
As for your other issue, the nginx log is not the only log that you can look for hint. You can check the PHP log or your CMS log. Please explore, most issue are fixed with the helpful logs.
Do i need to install these…
Do i need to install these virtualmin modules to make it to work: webmin-virtualmin-nginx webmin-virtualmin-nginx-ssl ?
Cheers
You don't need to install…
You don't need to install those virtualmin modules.
You are The Boss
Hi
I just migrated from Plesk/ ISPConfig to VirtualMin. Was looking for Litespeed as its event-based and supports .htaccess but their license is shared hosting oriented. So I think nginx+apache will be better though there is no official support via Virtualmin for reverse proxy, I came to your guide, and it looks superb.
I have some questions:
When I create a new domain in VirtualMin, will this automatically create Nginx vhost?
If I issue SSL (Letsencrypt) via Virtualmin, then will your script updates Nginx vhost for new SSL settings too?
Thanks :)
Answers
Hello, here are the answers:
-
Yes. It will automatically create Nginx vhost configuration.
-
No. You will need to manually update the Nginx vhost configuration.
Need a clarification
Drupal running in apache and wordpress running Nginx, after installing the Nginx the drupal getting conflict like file is not able to upload. before that there is no issue, let me know how to fix it.
Change the port
The article above is about setting up Nginx as web server and as reverse proxy for Apache. Based on the article above your Apache server needs its port changed from 80 to 8080 as the Nginx is already listening to port 80.
Hi…
Hi
# mod_remoteip settings
RemoteIPHeader X-Real-IP
RemoteIPInternalProxy 127.0.0.1
RemoteIPInternalProxy 188.8.8.8
Should i change the last ip to my servers ip?