├── vars └── main.yml ├── handlers └── main.yml ├── templates ├── nginx_status_allowed_hosts.j2 ├── php_fpm_status_allowed_hosts.j2 ├── upstream_php.j2 ├── php_fpm_status_vhost.j2 ├── nginx.j2 ├── sites-available │ └── drupal-site.j2 └── apps │ └── drupal │ └── drupal.j2 ├── tasks ├── main.yml ├── git-checkout.yml └── sites.yml ├── meta └── main.yml ├── defaults └── main.yml ├── README.md └── LICENSE /vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # vars file for nginx-drupal 3 | -------------------------------------------------------------------------------- /handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # handlers file for nginx-drupal 3 | - name: validate nginx-drupal configuration 4 | shell: nginx -t -------------------------------------------------------------------------------- /templates/nginx_status_allowed_hosts.j2: -------------------------------------------------------------------------------- 1 | # -*- mode: nginx; mode: flyspell-prog; ispell-local-dictionary: "american" -*- 2 | ## {{ ansible_managed }} 3 | ## Git ref: 81aa86d03f80e8f97d433cb541f63ee292531658 4 | ### Configuration of nginx stub status page. Here we define the 5 | ### allowed hosts using the Geo Module. http://wiki.nginx.org/HttpGeoModule 6 | 7 | geo $dont_show_nginx_status { 8 | default 1; 9 | {% for host in nginx_drupal_nginx_status_allowed_hosts %} 10 | {{host}} 0; 11 | {%- endfor %} 12 | } 13 | -------------------------------------------------------------------------------- /templates/php_fpm_status_allowed_hosts.j2: -------------------------------------------------------------------------------- 1 | # -*- mode: nginx; mode: flyspell-prog; ispell-local-dictionary: "american" -*- 2 | ## {{ ansible_managed }} 3 | ## Git ref: 81aa86d03f80e8f97d433cb541f63ee292531658 4 | ### Configuration of php-fpm status and ping pages. Here we define the 5 | ### allowed hosts using the Geo Module. http://wiki.nginx.org/HttpGeoModule 6 | 7 | geo $dont_show_fpm_status { 8 | default 1; 9 | {%- for host in nginx_drupal_php_fpm_status_allowed_hosts -%} 10 | {{host}} 0; 11 | {%- endfor %} 12 | } 13 | -------------------------------------------------------------------------------- /tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # tasks file for nginx-drupal 3 | - include: git-checkout.yml 4 | - name: "Create microcache directory" 5 | file: path=/var/cache/nginx/microcache state=directory 6 | when: nginx_drupal_microcache 7 | - name: "Override parametrized configuration files" 8 | template: src={{item}}.j2 dest={{nginx_drupal_config_path}}/{{item}}.conf 9 | with_items: 10 | - apps/drupal/drupal 11 | - php_fpm_status_allowed_hosts 12 | - nginx_status_allowed_hosts 13 | - nginx 14 | - upstream_php 15 | notify: 16 | - reload nginx 17 | - validate nginx-drupal configuration 18 | - include: sites.yml 19 | when: nginx_drupal_sites|lower != 'none' -------------------------------------------------------------------------------- /tasks/git-checkout.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "Get configuration directory's .git stats" 3 | stat: path={{nginx_drupal_config_path}}/.git 4 | register: nginx_drupal_config_path_dot_git 5 | - name: "Remove existing configurarion directory" 6 | file: path={{nginx_drupal_config_path}} state=absent 7 | when: not nginx_drupal_config_path_dot_git.stat.exists 8 | - name: "Checkout configuration directory" 9 | git: dest={{nginx_drupal_config_path}} repo={{nginx_drupal_git.repo}} version={{nginx_drupal_git.version}} force=yes 10 | when: (not nginx_drupal_config_path_dot_git.stat.exists) or (nginx_drupal_git.force_checkout|default(False)) 11 | notify: 12 | - reload nginx 13 | - name: "Remove example.com configuration file" 14 | file: path={{nginx_drupal_config_path}}/sites-available/example.com.conf state=absent -------------------------------------------------------------------------------- /tasks/sites.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "Create sites-enabled configuration directory" 3 | file: path={{nginx_drupal_config_path}}/sites-enabled state=directory 4 | - name: "Create available sites configuration files" 5 | template: src=sites-available/drupal-site.j2 dest={{nginx_drupal_config_path}}/sites-available/{{item.file_name}}.conf 6 | with_items: nginx_drupal_sites 7 | - name: "Create enabled sites symlinks" 8 | file: path={{nginx_drupal_config_path}}/sites-enabled/{{item.file_name}}.conf src={{nginx_drupal_config_path}}/sites-available/{{item.file_name}}.conf state=link 9 | with_items: nginx_drupal_sites 10 | when: item.enabled|default(True) 11 | notify: 12 | - validate nginx-drupal configuration 13 | - name: "Remove disabled sites symlinks" 14 | file: path={{nginx_drupal_config_path}}/sites-enabled/{{item.file_name}}.conf state=absent 15 | with_items: nginx_drupal_sites 16 | when: item.enabled|default(True) == False 17 | notify: 18 | - validate nginx-drupal configuration -------------------------------------------------------------------------------- /meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | author: Pierre Buyle 4 | description: Ansible role to configure Nginx for running Drupal 5 | company: Floe design + technologies 6 | license: Apache v2 7 | min_ansible_version: 1.2 8 | platforms: 9 | - name: GenericUNIX 10 | versions: 11 | - any 12 | - name: Fedora 13 | versions: 14 | - all 15 | - name: opensuse 16 | versions: 17 | - all 18 | - name: GenericBSD 19 | versions: 20 | - all 21 | - name: FreeBSD 22 | versions: 23 | - all 24 | - name: Ubuntu 25 | versions: 26 | - all 27 | - name: SLES 28 | versions: 29 | - all 30 | - name: GenericLinux 31 | versions: 32 | - all 33 | - name: Debian 34 | versions: 35 | - all 36 | galaxy_tags: 37 | - system 38 | - web 39 | - drupal 40 | dependencies: [] 41 | # List your role dependencies here, one per line. Only 42 | # dependencies available via galaxy should be listed here. 43 | # Be sure to remove the '[]' above if you add dependencies 44 | # to this list. 45 | 46 | -------------------------------------------------------------------------------- /templates/upstream_php.j2: -------------------------------------------------------------------------------- 1 | # -*- mode: nginx; mode: flyspell-prog; ispell-local-dictionary: "american" -*- 2 | ## {{ ansible_managed }} 3 | ## Git ref: 81aa86d03f80e8f97d433cb541f63ee292531658 4 | {%- if not nginx_drupal_php_handling == 'proxy' %} 5 | ### Upstream configuration for PHP FastCGI. 6 | {%- else %} 7 | ### Upstream configuration for Apache functioning has a PHP handler. 8 | {% endif %} 9 | 10 | ## Add as many servers as needed: 11 | ## Cf. http://wiki.nginx.org/HttpUpstreamModule. 12 | ## Note that this configuration assumes by default that keepalive 13 | ## upstream connections are supported and that you have a Nginx 14 | ## version with the fair load balancer. 15 | 16 | {% set has_backup = False %} 17 | 18 | {% if nginx_drupal_php_handling == 'proxy' %} 19 | upstream phpapache { 20 | {% else %} 21 | upstream phpcgi { 22 | {% endif %} 23 | 24 | ## Use the least connection algorithm for load balancing. This 25 | ## algorithm was introduced in versions 1.3.1 and 1.2.2. 26 | least_conn; 27 | 28 | {% for server in nginx_drupal_upstream_servers -%} 29 | server {{server}}; 30 | {% set has_backup = has_backup and server.backup %} 31 | {%- endfor %} 32 | 33 | ## Create a backend connection cache. Note that this requires 34 | ## Nginx version greater or equal to 1.1.4. 35 | ## Cf. http://nginx.org/en/CHANGES. Comment out the following 36 | ## line if that's not the case. 37 | keepalive 5; 38 | } 39 | 40 | {% if nginx_drupal_upstream_backup_servers %} 41 | {% if nginx_drupal_php_handling == 'proxy' %} 42 | upstream phpapache_backuo { 43 | {% else %} 44 | upstream phpcgi_backup { 45 | {% endif %} 46 | {% for server in nginx_drupal_upstream_backup_servers -%} 47 | server {{server}}; 48 | {%- endfor %} 49 | 50 | ## Create a backend connection cache. Note that this requires 51 | ## Nginx version greater or equal to 1.1.4. 52 | ## Cf. http://nginx.org/en/CHANGES. Comment out the 53 | ## following line if that's not the case. 54 | keepalive 1; 55 | } 56 | {% endif %} 57 | 58 | {% if nginx_drupal_php_handling == 'php-fpm' %} 59 | {% for server in nginx_drupal_upstream_servers %} 60 | ## The PHP TCP upstream that corresponds to the first pool: www{{loop.index0}}. 61 | upstream www{{loop.index0}} { 62 | server {{server}}; 63 | } 64 | {%- endfor %} 65 | {% endif %} -------------------------------------------------------------------------------- /defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for nginx-drupal 3 | nginx_drupal_git: 4 | repo: "https://github.com/perusio/drupal-with-nginx.git" 5 | version: "D7" 6 | 7 | nginx_drupal_config_path: "/etc/nginx" 8 | nginx_drupal_log_path: "/var/log/nginx" 9 | nginx_drupal_php_handling: "php-fpm" 10 | nginx_drupal_escape_uri: false 11 | nginx_drupal_use_boost: false 12 | nginx_drupal_use_drush: true 13 | nginx_drupal_allow_install: false 14 | nginx_drupal_use_spdy: false 15 | nginx_drupal_php_fpm_status_allowed_hosts: ["127.0.0.1", "192.168.1.0/24"] 16 | nginx_drupal_nginx_status_allowed_hosts: ["127.0.0.1", "192.168.1.0/24"] 17 | nginx_drupal_hotlinking_protection: false 18 | nginx_drupal_admin_basic_auth: false 19 | nginx_drupal_microcache: true 20 | nginx_drupal_microcache_auth: false 21 | nginx_drupal_upload_progress: true 22 | nginx_drupal_aio: true 23 | nginx_drupal_flv_streaming: false 24 | nginx_drupal_mp4_streaming: false 25 | nginx_drupal_http_core: 26 | client_max_body_size: "10m" 27 | ssl_session_cache: true 28 | nginx_drupal_ssl_protocols: [ "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2" ] 29 | nginx_drupal_ssl_ecdh_curve: "secp521r1" 30 | nginx_drupal_ssl_ciphers: "ECDH+aRSA+AESGCM:ECDH+aRSA+SHA384:ECDH+aRSA+SHA256:ECDH:EDH+CAMELLIA:EDH+aRSA:+CAMELLIA256:+AES256:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4:!SEED:!ECDSA:CAMELLIA256-SHA:AES256-SHA:CAMELLIA128-SHA:AES128-SHA" 31 | nginx_drupal_upstream_servers: ["unix:/var/run/php-fpm.sock", "php-fpm-zwei.sock"] 32 | nginx_drupal_upstream_backup_servers: ["unix:/var/run/php-fpm-bkp.sock"] 33 | nginx_drupal_sites: none 34 | nginx_drupal_http_pre_includes: [] 35 | nginx_drupal_http_post_includes: [] 36 | nginx_drupal_language_path_prefixes: [] 37 | nginx_drupal_x_frame_options: DENY 38 | nginx_drupal_remote_addr_conn_limit: 5 39 | nginx_drupal_remote_addr_conn_limit_zone: per_fastly_client_ip 40 | nginx_drupal_remote_addr_http_req_limit_avg: 5 41 | nginx_drupal_remote_addr_http_req_limit_burst: 5 42 | nginx_drupal_remote_addr_http_req_limit_period: 10m 43 | nginx_drupal_remote_addr_http_req_limit_zone: perip 44 | nginx_drupal_remote_addr_http_req_limit_delay: nodelay 45 | nginx_drupal_server_name_http_req_limit_avg: 40 46 | nginx_drupal_server_name_http_req_limit_burst: 60 47 | nginx_drupal_server_name_http_req_limit_period: 10m 48 | nginx_drupal_server_name_http_req_limit_zone: perserver 49 | nginx_drupal_server_name_http_req_limit_delay: 50 | -------------------------------------------------------------------------------- /templates/php_fpm_status_vhost.j2: -------------------------------------------------------------------------------- 1 | # -*- mode: nginx; mode: flyspell-prog; ispell-current-dictionary: american -*- 2 | ## {{ ansible_managed }} 3 | ## Git ref: 81aa86d03f80e8f97d433cb541f63ee292531658 4 | ### The configuration for the status pages of php-fpm. As described in 5 | ### http://www.php.net/manual/en/install.fpm.configuration.php. 6 | 7 | ### php-fpm provides a status and a heartbeat page that is served through the web server. 8 | ### Here's an example configuration for them. 9 | 10 | ## The status page is at /fpm-status. Only local access is 11 | ## allowed. Non authorized access returns a 404 through the error_page 12 | ## directive. 13 | location = /fpm-status { 14 | if ($dont_show_fpm_status) { 15 | return 404; 16 | } 17 | fastcgi_pass www0; 18 | } 19 | 20 | ## The ping page is at /ping and returns the string configured at the php-fpm level. 21 | ## Also only local network connections (loopback and LAN) are permitted. 22 | location = /ping { 23 | if ($dont_show_fpm_status) { 24 | return 404; 25 | } 26 | fastcgi_pass www0; 27 | } 28 | 29 | ## This is for the second pool. It assumes that you've configured 30 | ## php-fpm to have two pools and the URIs configured for the status 31 | ## and ping pages are as specified below. Zwei is 2 in german. 32 | 33 | ## The status page is at /fpm-status. Only local access is 34 | ## allowed. Non authorized access returns a 404 through the error_page 35 | ## directive. 36 | location = /fpm-status-zwei { 37 | if ($dont_show_fpm_status) { 38 | return 404; 39 | } 40 | fastcgi_pass www1; 41 | } 42 | 43 | ## The ping page is at /ping and returns the string configured at the php-fpm level. 44 | ## Also only local network connections (loopback and LAN) are permitted. 45 | location = /ping-zwei { 46 | if ($dont_show_fpm_status) { 47 | return 404; 48 | } 49 | fastcgi_pass www1; 50 | } 51 | 52 | ## This is for the third pool that acts as backup. It assumes that 53 | ## you've configured php-fpm to have two pools and the URIs configured 54 | ## for the status and ping pages are as specified below. Drei is 3 in 55 | ## german. 56 | 57 | ## The status page is at /fpm-status. Only local access is 58 | ## allowed. Non authorized access returns a 404 through the error_page 59 | ## directive. 60 | location = /fpm-status-drei { 61 | if ($dont_show_fpm_status) { 62 | return 404; 63 | } 64 | fastcgi_pass phpcgi; 65 | } 66 | 67 | ## The ping page is at /ping and returns the string configured at the php-fpm level. 68 | ## Also only local network connections (loopback and LAN) are permitted. 69 | location = /ping-drei { 70 | if ($dont_show_fpm_status) { 71 | return 404; 72 | } 73 | fastcgi_pass phpcgi; 74 | } 75 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Nginx Drupal 2 | ============ 3 | 4 | Ansible role to configure Nginx for running Drupal using [perusio's configuration](https://github.com/perusio/drupal-with-nginx). 5 | 6 | This role only configure Nginx to run Drupal sites, it will not install PHP, 7 | Nginx, Drupal, MySQL, etc. It will however, override the entire content of the 8 | Nginx configuration directory. You can still add file to the Nginx configuration 9 | directory after this role. 10 | 11 | Requirements 12 | ------------ 13 | 14 | - Git 15 | - A `reload nginx` handler is used to reload Nginx after configuration changes 16 | and must be defined in your playbook. 17 | 18 | Role Variables 19 | -------------- 20 | 21 | The following variables are available to configure the role: 22 | 23 | - **nginx_drupal_git** 24 | - **repo**: The URL of the Git repository to checkout the base 25 | configuration from, defaults to https://github.com/perusio/drupal-with-nginx.git 26 | - **version**: The version of the version of the repository to 27 | check out. This can be the full 40-character SHA-1 hash, the literal string 28 | HEAD, a branch name, or a tag name. Defaults to 'D7'. 29 | - **force_checkout**: True to always do a git checkout. Defaults to False. 30 | - **nginx_drupal_config_path**: The path to Nginx configuration folder, 31 | defaults to "/etc/nginx". 32 | - **nginx_drupal_log_path**: The path to Nginx log files, defaults to 33 | "/var/log/nginx" 34 | - **nginx_drupal_php_handling**: The PHP handling method, one of "php-fpm", 35 | "php-cgi" or "proxy", defaults to "php-fpm". 36 | - **nginx_drupal_escape_uri**: Whether or not to escaped URIs, defaults to 37 | false. 38 | - **nginx_drupal_use_boost**: Whether or not [Boost](http://drupal.org/project/boost) 39 | is used, defaults to false. 40 | - **nginx_drupal_use_drush**: Whether or not [Drush](https://github.com/drush-ops/drush) 41 | is used, defaults to true. 42 | - **nginx_drupal_allow_install**: Whether or not to allow access to the 43 | ```install.php``` file, defaults to false. 44 | - **nginx_drupal_use_spdy**: Whether or not to use SPDY, defaults to false. 45 | - **nginx_drupal_nginx_status_allowed_hosts**: The list of host allowed to 46 | access Nginx status page, defaults to ```["127.0.0.1", "192.168.1.0/24"]```. 47 | - **nginx_drupal_php_fpm_status_allowed_hosts**: The list of host allowed to 48 | access PHP-FPM status page, defaults to ```["127.0.0.1", "192.168.1.0/24"]```. 49 | - **nginx_drupal_hotlinking_protection**: Whether or not to prevent image 50 | hotlinking, defaults to false. 51 | - **nginx_drupal_admin_basic_auth**: Whether or not to protect access to admin 52 | pages (```/admin/*```) using HTTP auth, defaults to false. 53 | - **nginx_drupal_microcache**: Whether or not to use microcaching, defaults to 54 | true. 55 | - **nginx_drupal_microcache_auth**: Whether or not to use microcaching for 56 | authenticated users, defaults to false. 57 | - **nginx_drupal_upload_progress**: Whether or not to use upload progress (this 58 | require the [filefield_nginx_progress](http://drupal.org/project/filefield_nginx_progress) 59 | Drupal module and [nginx_uploadprogress_module](https://www.nginx.com/resources/wiki/modules/upload_progress/) 60 | included in your Nginx build. 61 | - **nginx_drupal_aio**: Whether or not to use AIO to server video and audio 62 | file, defaults to true. 63 | - **nginx_drupal_flv_streaming**: Whether or not to use FLV pseudo streaming 64 | (cf. http://wiki.nginx.org/HttpFlvStreamModule), defaults to false. 65 | - **nginx_drupal_mp4_streaming**: Whether or not to use MP4 streaming, (cf. 66 | http://nginx.org/en/docs/http/ngx_http_mp4_module.html) defaults to false. 67 | - **nginx_drupal_ssl_protocols**: List of protocols to enable, defaults to SSLv3, TLSv1, TLSv1.1, TLSv1.2 68 | - **nginx_drupal_ssl_ecdh_curve**: Curve to use for ECDH, defaults to secp521r1 69 | - **nginx_drupal_ssl_ciphers**: Ciphers to use 70 | defaults to "ECDH+aRSA+AESGCM:ECDH+aRSA+SHA384:ECDH+aRSA+SHA256:ECDH:EDH+CAMELLIA:EDH+aRSA:+CAMELLIA256:+AES256:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4:!SEED:!ECDSA:CAMELLIA256-SHA:AES256-SHA:CAMELLIA128-SHA:AES128-SHA" 71 | - **nginx_drupal_http_pre_includes**: A list of file to include in the 72 | ```http``` context (in ```nginx.conf```), before any other directives. 73 | - **nginx_drupal_http_post_includes**: A list of file to include in the 74 | ```http``` context (in ```nginx.conf```), after any other directives except 75 | the enabled 76 | site configuration files. 77 | - **nginx_drupal_upstream_servers**: The list of PHP upstream servers, each 78 | item is a server address (and parameters, see 79 | http://nginx.org/en/docs/http/ngx_http_upstream_module.html#server), defaults 80 | to ```["unix:/var/run/php-fpm.sock", "php-fpm-zwei.sock"]```. 81 | - **nginx_drupal_upstream_backup_servers**: The list of PHP upstream backup 82 | servers, defaults to ```["unix:/var/run/php-fpm-bkp.sock"]```. 83 | - **nginx_drupal_language_path_prefixes**: (optional) The list of enabled 84 | language path prefixes used on the site. 85 | - **nginx_drupal_set_real_ip_from**: (optional) configure real_ip if necessary 86 | - **nginx_drupal_x_frame_options**: (optional) Value of the X-Frame-Options 87 | response header, defaults to `DENY`. If the site uses frames, set to 88 | `SAMEORIGIN`. `DENY` may conflicts with pseudo streaming (at least with Nginx 89 | version 1.0.12) 90 | - **nginx_drupal_sites**: The list of available sites. 91 | Each site uses the following structure: 92 | - **file_name**: The name of the site configuration file. 93 | - **http**: HTTP server configuration (leave empty to disable HTTP) 94 | - **port**: The port to listen on 95 | - **https**: HTTPS server configuration (leave empty to disable HTTPS) 96 | - **port**: The port to listen on. 97 | - **certificate**: Path to the SSL certificate of the server (in the 98 | PEM format). 99 | - **certificate_key**: Path to the SSL secret key of the server (in the 100 | PEM format). 101 | - **server_name**: The (primary) server name. 102 | - **default**: Indicate the virtual host as default (boolean). 103 | - **ipv6**: (optional) IPv6 address of the server 104 | - **alternate_server_name**: (optional) Alternate server name, configured 105 | as redirect to the primary server site. This can be used to remove the 106 | ```www.``` prefix. 107 | - **root**: Path to the root directory for the site. 108 | - **limit_conn**: (optional) The limit_conn for the site (defaults to 109 | ```arbeit 32```). 110 | - **enabled**: Whether or not the site should be enabled (defaults to true). 111 | - **rewrites**: (optional) A list of rewrites directives, using the 112 | following structure: 113 | - **regex**: The regular expression used to match the URI. 114 | - **replacement**: The replacement pattern used for the rewrite. 115 | - **flags**: (optional) The flag parameter for the rewrite. 116 | - **custom_locations**: (optional) A list of locations directives, using the 117 | following structure: 118 | - **operator**: (optional) Operator to match the location path (defaults to '=') 119 | - **path**: Path string to match on 120 | - **allowed_ips**: (optional) List of IP (with or without subnet) allowed to visit this location 121 | - **denied_ips**: (optional) List of IP (with or without subnet) denied to visit this location 122 | - **fastcgi_pass**: (optional) fastcgi socket (or IP) to send to. If not specified, will use the @drupal location as upstream. 123 | - **fastcgi_index**: (optional) fastcgi index 124 | - **includes**: (optional) A list of additional Nginx configuration files 125 | to include for the site. 126 | - **server_name_in_redirect**: (optional) Enables or disables the use of 127 | the primary server name, specified by the server_name directive, in 128 | redirects issued by nginx. 129 | 130 | 131 | Examples 132 | -------- 133 | 134 | Two Drupal 7 sites, one available in HTTP and HTTPS. The other only available in 135 | HTTPS but disabled. 136 | 137 | 138 | - hosts: all 139 | roles: 140 | - role: nginx-drupal 141 | nginx_drupal_sites: 142 | - file_name: foo 143 | server_name: foo.org 144 | alternate_server_name: www.foo.org 145 | root: /var/www/foo 146 | http: 147 | port: 80 148 | https: 149 | port: 443 150 | certificate: /etc/nginx/ssl/foo.cert 151 | certificate_key: /etc/nginx/ssl/foo.key 152 | - file_name: bar 153 | server_name: bar.org 154 | alternate_server_name: www.bar.org 155 | root: /var/www/bar 156 | enabled: false 157 | https: 158 | port: 443 159 | certificate: /etc/nginx/ssl/bar.cert 160 | certificate_key: /etc/nginx/ssl/bar.key 161 | 162 | Nginx as a Reverse Proxy for a single Drupal 6 sites, without microcaching, 163 | with image hot linking protection and a rewrite directive. 164 | 165 | 166 | - hosts: all 167 | roles: 168 | - role: nginx-drupal 169 | nginx_drupal_git: 170 | version: D6 171 | nginx_drupal_hotlinking_protection: true 172 | nginx_drupal_php_handling: proxy 173 | nginx_drupal_microcache: false 174 | nginx_drupal_sites: 175 | - file_name: foo 176 | server_name: foo.org 177 | alternate_server_name: www.foo.org 178 | root: /var/www/foo 179 | http: 180 | port: 80 181 | rewrites: 182 | - regex: '^/foo-bar.htm$' 183 | replacement: '/foo/bar' 184 | flags: 'permanent' 185 | 186 | License 187 | ------- 188 | 189 | Apache v2 190 | 191 | Author Information 192 | ------------------ 193 | 194 | Pierre Buyle 195 | -------------------------------------------------------------------------------- /templates/nginx.j2: -------------------------------------------------------------------------------- 1 | # -*- mode: nginx; mode: flyspell-prog; ispell-local-dictionary: "american" -*- 2 | ## {{ ansible_managed }} 3 | ## Git ref: 81aa86d03f80e8f97d433cb541f63ee292531658 4 | user www-data; 5 | 6 | ## If you're using an Nginx version below 1.3.8 or 1.2. then uncomment 7 | ## the line below and set it to the number of cores of the 8 | ## server. Otherwise nginx will determine it automatically. 9 | #worker_processes 4; 10 | 11 | error_log /var/log/nginx/error.log; 12 | pid /var/run/nginx.pid; 13 | 14 | worker_rlimit_nofile 8192; 15 | 16 | events { 17 | worker_connections 4096; 18 | ## Accept as many connections as possible. 19 | multi_accept on; 20 | } 21 | 22 | http { 23 | {% for include in nginx_drupal_http_pre_includes %} 24 | include {{include}}; 25 | {% endfor %} 26 | 27 | ## MIME types. 28 | include /etc/nginx/mime.types; 29 | default_type application/octet-stream; 30 | 31 | ## FastCGI. 32 | include /etc/nginx/fastcgi.conf; 33 | 34 | ## Default log and error files. 35 | access_log /var/log/nginx/access.log; 36 | error_log /var/log/nginx/error.log; 37 | log_format '$remote_addr [fastly:$http_fastly_client_ip] forwarded for $http_x_forwarded_for - $remote_user [$time_local] ' 38 | '"$request" $status $body_bytes_sent ' 39 | '"$http_referer" "$http_user_agent"'; 40 | 41 | ## Use sendfile() syscall to speed up I/O operations and speed up 42 | ## static file serving. 43 | sendfile on; 44 | ## Handling of IPs in proxied and load balancing situations. 45 | {% if nginx_drupal_set_real_ip_from is defined %} 46 | set_real_ip_from {{ nginx_drupal_set_real_ip_from }}; 47 | {% else %} 48 | set_real_ip_from 0.0.0.0/32; # all addresses get a real IP. 49 | {% endif %} 50 | real_ip_header X-Forwarded-For; # the ip is forwarded from the load balancer/proxy 51 | real_ip_recursive on; 52 | 53 | ## The ngx_http_limit_req_module module is used to limit the request processing rate 54 | ## per a defined key, in particular, the processing rate of requests coming from a single IP address. 55 | ## The limitation is done using the “leaky bucket” method. 56 | limit_req_zone $http_fastly_client_ip zone={{ nginx_drupal_remote_addr_http_req_limit_zone }}:{{ nginx_drupal_remote_addr_http_req_limit_period }} rate={{ nginx_drupal_remote_addr_http_req_limit_avg }}r/s; 57 | limit_req_zone $server_name zone={{ nginx_drupal_server_name_http_req_limit_zone }}:{{ nginx_drupal_server_name_http_req_limit_period }} rate={{ nginx_drupal_server_name_http_req_limit_avg }}r/s; 58 | 59 | ## Define a zone for limiting the number of simultaneous 60 | ## connections nginx accepts. 1m means 32000 simultaneous 61 | ## sessions. We need to define for each server the limit_conn 62 | ## value refering to this or other zones. 63 | ## ** This syntax requires nginx version >= 64 | ## ** 1.1.8. Cf. http://nginx.org/en/CHANGES. If using an older 65 | ## ** version then use the limit_zone directive below 66 | ## ** instead. Comment out this 67 | ## ** one if not using nginx version >= 1.1.8. 68 | limit_conn_zone $binary_remote_addr zone=arbeit:10m; 69 | limit_conn_zone $http_fastly_client_ip zone={{ nginx_drupal_remote_addr_conn_limit_zone }}:10m; 70 | 71 | ## Define a zone for limiting the number of simultaneous 72 | ## connections nginx accepts. 1m means 32000 simultaneous 73 | ## sessions. We need to define for each server the limit_conn 74 | ## value refering to this or other zones. 75 | ## ** Use this directive for nginx versions below 1.1.8. Uncomment the line below. 76 | #limit_zone arbeit $binary_remote_addr 10m; 77 | 78 | ## Timeouts. 79 | client_body_timeout 60; 80 | client_header_timeout 60; 81 | keepalive_timeout 10 10; 82 | send_timeout 60; 83 | 84 | ## Reset lingering timed out connections. Deflect DDoS. 85 | reset_timedout_connection on; 86 | 87 | ## Body size. 88 | client_max_body_size {{nginx_drupal_http_core.client_max_body_size}}; 89 | 90 | ## TCP options. 91 | tcp_nodelay on; 92 | ## Optimization of socket handling when using sendfile. 93 | tcp_nopush on; 94 | 95 | ## Compression. 96 | gzip on; 97 | gzip_buffers 16 8k; 98 | gzip_comp_level 1; 99 | gzip_http_version 1.1; 100 | gzip_min_length 10; 101 | 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-font-ttf; 102 | gzip_vary on; 103 | gzip_proxied any; # Compression for all requests. 104 | ## No need for regexps. See 105 | ## http://wiki.nginx.org/NginxHttpGzipModule#gzip_disable 106 | gzip_disable msie6; 107 | 108 | ## Serve already compressed files directly, bypassing on-the-fly 109 | ## compression. 110 | ## 111 | # Usually you don't make much use of this. It's better to just 112 | # enable gzip_static on the locations you need it. 113 | # gzip_static on; 114 | 115 | ## Hide the Nginx version number. 116 | server_tokens off; 117 | 118 | {% if nginx_drupal_http_core.ssl_session_cache %} 119 | ## Use a SSL/TLS cache for SSL session resume. This needs to be 120 | ## here (in this context, for session resumption to work. See this 121 | ## thread on the Nginx mailing list: 122 | ## http://nginx.org/pipermail/nginx/2010-November/023736.html. 123 | ssl_session_cache shared:SSL:30m; 124 | ssl_session_timeout 1d; 125 | {% endif %} 126 | 127 | ## The server dictates the choice of cipher suites. 128 | ssl_prefer_server_ciphers on; 129 | 130 | ## Use only Perfect Forward Secrecy Ciphers. Fallback on non ECDH 131 | ## for crufty clients. 132 | ssl_ciphers {{nginx_drupal_ssl_ciphers}}; 133 | 134 | ## No SSL2 support. Legacy support of SSLv3. 135 | ssl_protocols {{nginx_drupal_ssl_protocols|join(" ")}}; 136 | 137 | ## Pregenerated Diffie-Hellman parameters. 138 | ssl_dhparam /etc/nginx/dh_param.pem; 139 | 140 | ## Curve to use for ECDH. 141 | ssl_ecdh_curve {{nginx_drupal_ssl_ecdh_curve}}; 142 | 143 | ## Enable OCSP stapling. A better way to revocate server certificates. 144 | ssl_stapling on; 145 | ## Fill in with your own resolver. 146 | resolver 8.8.8.8; 147 | 148 | ## Uncomment to increase map_hash_bucket_size. If start getting 149 | ## [emerg]: could not build the map_hash, you should increase 150 | ## map_hash_bucket_size: 64 in your 151 | ## logs. Cf. http://wiki.nginx.org/NginxOptimizations. 152 | #map_hash_bucket_size 192; 153 | 154 | ## Uncomment one of the lines below if you start getting this message: 155 | ## "[emerg] could not build the variables_hash, you should increase 156 | ## either variables_hash_max_size: 512 or variables_hash_bucket_size: 64" 157 | ## You only need to increase one. Increasing variables_hash_max_size to 1024 158 | ## was recommended in nginx forum by developers. 159 | ## See this forum topic and responses 160 | ## http://forum.nginx.org/read.php?2,192277,192286#msg-192286 161 | ## See http://wiki.nginx.org/HttpCoreModule#variables_hash_bucket_size 162 | ## The line variables_hash_bucket_size was added for completeness but not 163 | ## changed from default. 164 | variables_hash_max_size 1024; # default 512 165 | #variables_hash_bucket_size 64; # default is 64 166 | 167 | {%- if nginx_drupal_upload_progress %} 168 | ## For the filefield_nginx_progress module to work. From the 169 | ## README. Reserve 1MB under the name 'uploads' to track uploads. 170 | upload_progress uploads 1m; 171 | {%- endif -%} 172 | 173 | ## Enable the builtin cross-site scripting (XSS) filter available 174 | ## in modern browsers. Usually enabled by default we just 175 | ## reinstate in case it has been somehow disabled for this 176 | ## particular server instance. 177 | ## https://www.owasp.org/index.php/List_of_useful_HTTP_headers. 178 | add_header X-XSS-Protection '1; mode=block'; 179 | 180 | {% if nginx_drupal_x_frame_options %} 181 | ## Enable clickjacking protection in modern browsers. Available in 182 | ## IE8 also. See 183 | ## https://developer.mozilla.org/en/The_X-FRAME-OPTIONS_response_header 184 | ## This may conflicts with pseudo streaming (at least with Nginx version 1.0.12). 185 | add_header X-Frame-Options {{ nginx_drupal_x_frame_options }}; 186 | {% endif %} 187 | 188 | ## Block MIME type sniffing on IE. 189 | add_header X-Content-Options nosniff; 190 | 191 | {% if nginx_drupal_php_handling != 'proxy' %} 192 | ## Include the upstream servers for PHP FastCGI handling config. 193 | include upstream_php.conf; 194 | {% endif %} 195 | 196 | ## Include the map to block HTTP methods. 197 | include map_block_http_methods.conf; 198 | 199 | ## If using Nginx version >= 1.1.11 then there's a $https variable 200 | ## that has the value 'on' if the used scheme is https and '' if not. 201 | ## See: http://trac.nginx.org/nginx/changeset/4380/nginx 202 | ## http://trac.nginx.org/nginx/changeset/4333/nginx and 203 | ## http://trac.nginx.org/nginx/changeset/4334/nginx. If using a 204 | ## previous version then uncomment out the line below. 205 | #include map_https_fcgi.conf; 206 | 207 | ## Support the X-Forwarded-Proto header for FastCGI. 208 | map $http_x_forwarded_proto $fastcgi_https { 209 | default $https; 210 | http ''; 211 | https on; 212 | } 213 | 214 | ## Include the upstream servers for Apache handling the PHP 215 | ## processes. In this case Nginx functions as a reverse proxy. 216 | {% if nginx_drupal_php_handling == 'proxy' %} 217 | include reverse_proxy.conf; 218 | include upstream_php.conf; 219 | {% endif %} 220 | 221 | ## Include the php-fpm status allowed hosts configuration block. 222 | ## Uncomment to enable if you're running php-fpm. 223 | #include php_fpm_status_allowed_hosts.conf; 224 | 225 | ## Include the Nginx stub status allowed hosts configuration block. 226 | include nginx_status_allowed_hosts.conf; 227 | 228 | {%- if not nginx_drupal_use_drush %} 229 | ## If you want to run cron using Drupal cron.php. i.e., you're not 230 | ## using drush then uncomment the line below. Specify in 231 | ## cron_allowed_hosts.conf which hosts can invole cron. 232 | include apps/drupal/cron_allowed_hosts.conf; 233 | {%- endif -%} 234 | 235 | ## Include blacklist for bad bot and referer blocking. 236 | include blacklist.conf; 237 | 238 | ## Include the caching setup. Needed for using Drupal with an external cache. 239 | include apps/drupal/map_cache.conf; 240 | 241 | {% if nginx_drupal_microcache -%} 242 | {% if nginx_drupal_php_handling == 'php-fpm' or nginx_drupal_php_handling == 'php-cgi' %} 243 | ## Microcache zone definition for FastCGI. 244 | include fastcgi_microcache_zone.conf; 245 | {% else %} 246 | ## Microcache zone definition for Proxy. 247 | include proxy_microcache_zone.conf 248 | {%- endif -%} 249 | {%- endif -%} 250 | 251 | {% for include in nginx_drupal_http_post_includes %} 252 | include {{include}}; 253 | {% endfor %} 254 | 255 | ## Include all vhosts. 256 | include /etc/nginx/sites-enabled/*; 257 | } 258 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /templates/sites-available/drupal-site.j2: -------------------------------------------------------------------------------- 1 | # -*- mode: nginx; mode: flyspell-prog; ispell-current-dictionary: american -*- 2 | ## {{ ansible_managed }} 3 | ## Git ref: 81aa86d03f80e8f97d433cb541f63ee292531658 4 | {% if item.http is defined %} 5 | {% if item.alternate_server_name is defined %} 6 | ## Return (no rewrite) server block. 7 | server { 8 | ## This is to avoid the spurious if for sub-domain name 9 | ## "rewriting". 10 | listen {{item.http.port}}; # IPv4 11 | {% if item.ipv6 is defined %} 12 | listen [{{item.ipv6}}]:{{item.http.port}} ipv6only=on; 13 | {% endif %} 14 | server_name {{item.alternate_server_name}}; 15 | return 301 $scheme://{{item.server_name}}$request_uri; 16 | 17 | } # server domain return. 18 | {% endif %} 19 | 20 | ## HTTP server. 21 | server { 22 | listen {{item.http.port}}; # IPv4 23 | {% if item.ipv6 is defined %} 24 | listen [{{item.ipv6}}]:{{item.http.port}} ipv6only=on; 25 | {% endif %} 26 | 27 | server_name {{item.server_name}}{% if item.default|default(false) %} default{% endif %}; 28 | {% if item.limit_conn|default('None') != 'None' %} 29 | limit_conn {{item.limit_conn|default('arbeit 32')}}; 30 | {% endif %} 31 | 32 | ## HTTP Request Limits 33 | limit_req zone={{ nginx_drupal_remote_addr_http_req_limit_zone }} burst={{ nginx_drupal_remote_addr_http_req_limit_burst }} {{ nginx_drupal_remote_addr_http_req_limit_delay }}; 34 | limit_req zone={{ nginx_drupal_server_name_http_req_limit_zone }} burst={{ nginx_drupal_server_name_http_req_limit_burst }} {{ nginx_drupal_server_name_http_req_limit_delay }}; 35 | limit_conn {{ nginx_drupal_remote_addr_conn_limit_zone }} {{ nginx_drupal_remote_addr_conn_limit }}; 36 | 37 | ## Access and error logs. 38 | access_log {{nginx_drupal_log_path}}/{{item.server_name}}_{{item.file_name}}_access.log; 39 | error_log {{nginx_drupal_log_path}}/{{item.server_name}}_{{item.file_name}}_drupal_error.log; 40 | 41 | ## See the blacklist.conf file at the parent dir: /etc/nginx. 42 | ## Deny access based on the User-Agent header. 43 | if ($bad_bot) { 44 | return 444; 45 | } 46 | ## Deny access based on the Referer header. 47 | if ($bad_referer) { 48 | return 444; 49 | } 50 | 51 | ## Protection against illegal HTTP methods. Out of the box only HEAD, 52 | ## GET and POST are allowed. 53 | if ($not_allowed_method) { 54 | return 405; 55 | } 56 | 57 | ## Filesystem root of the site and index. 58 | root {{item.root}}; 59 | index index.php; 60 | 61 | ## If you're using a Nginx version greater or equal to 1.1.4 then 62 | ## you can use keep alive connections to the upstream be it 63 | ## FastCGI or Apache. If that's not the case comment out the line below. 64 | fastcgi_keep_conn on; # keep alive to the FCGI upstream 65 | 66 | {% if nginx_drupal_php_handling == 'proxy' %} 67 | proxy_http_version 1.1; # keep alive to the Apache upstream 68 | {% endif %} 69 | 70 | server_name_in_redirect {{'on' if item.server_name_in_redirect|default(false) else 'off'}}; 71 | 72 | {% if item.rewrites is defined %} 73 | ## URL rewriting 74 | {% for rewrite in item.rewrites %} 75 | rewrite {{rewrite.regex}} {{rewrite.replacement}} {{rewrite.flags|default('')}}; 76 | {% endfor %} 77 | {%- endif %} 78 | 79 | {% if item.includes is defined %} 80 | ## Custom include(s) 81 | {% for include in item.includes %} 82 | include {{ include }}; 83 | {% endfor %} 84 | {% endif %} 85 | 86 | {% if item.custom_locations is defined -%} 87 | ## Custom location(s) 88 | {% for location in item.custom_locations -%} 89 | location {{ location.operator|default('=') }} "{{ location.path }}" { 90 | {% if location.allowed_ips is defined -%} 91 | {% for allowed_ip in location.allowed_ips %} 92 | allow {{ allowed_ip }}; 93 | {% endfor %} 94 | deny all; 95 | {% endif %} 96 | {%- if location.denied_ips is defined -%} 97 | {%- for denied_ip in location.denied_ips %} 98 | deny {{ denied_ip }}; 99 | {% endfor %} 100 | {% endif -%} 101 | {%- if location.fastcgi_pass is defined -%} 102 | include fastcgi_params; 103 | fastcgi_pass {{ location.fastcgi_pass }}; 104 | {%- if location.fastcgi_index is defined -%} 105 | fastcgi_index {{ location.fastcgi_index }}; 106 | {% endif %} 107 | {% else %} 108 | try_files $uri @drupal; 109 | {% endif %} 110 | } 111 | {% endfor %} 112 | {% endif %} 113 | 114 | include apps/drupal/drupal.conf; 115 | 116 | {%- if not nginx_drupal_use_drush %} 117 | ################################################################# 118 | ### Configuration for updating the site via update.php and running 119 | ### cron externally. If you don't use drush for running cron use 120 | ### the configuration below. 121 | ################################################################# 122 | include apps/drupal/drupal_cron_update.conf; 123 | {%- endif -%} 124 | 125 | ################################################################ 126 | ### Installation handling. This should be commented out after 127 | ### installation if on an already installed site there's no need 128 | ### to touch it. If on a yet to be installed site. Uncomment the 129 | ### line below and comment out after installation. Note that 130 | ### there's a basic auth in front as secondary ligne of defense. 131 | ################################################################ 132 | {% if nginx_drupal_allow_install -%} 133 | include apps/drupal/drupal_install.conf; 134 | {% else -%} 135 | #include apps/drupal/drupal_install.conf; 136 | {%- endif %} 137 | 138 | {% if nginx_drupal_upload_progress -%} 139 | ################################################################# 140 | ### Support for upload progress bar. Configurations differ for 141 | ### Drupal 6 and Drupal 7. 142 | ################################################################# 143 | include apps/drupal/drupal_upload_progress.conf; 144 | {%- endif %} 145 | 146 | {%- if nginx_drupal_php_handling == 'proxy' %} 147 | ## Including the php-fpm status and ping pages config. 148 | include php_fpm_status_vhost.conf; 149 | {%- endif %} 150 | 151 | ## Including the Nginx stub status page for having stats about 152 | ## Nginx activity: http://wiki.nginx.org/HttpStubStatusModule. 153 | include nginx_status_vhost.conf; 154 | 155 | } # HTTP server 156 | {% endif %} 157 | 158 | {% if item.https is defined %} 159 | {% if item.alternate_server_name is defined %} 160 | ## Return (no rewrite) server block. 161 | server { 162 | ## This is to avoid the spurious if for sub-domain name 163 | ## "rewriting". 164 | {% if nginx_drupal_use_spdy %} 165 | listen {{item.https.port}} ssl spdy; # IPv4 166 | {% else %} 167 | listen {{item.https.port}} ssl; # IPv4 168 | {% endif %} 169 | 170 | {% if item.ipv6 is defined %} 171 | {% if nginx_drupal_use_spdy %} 172 | listen [{{item.ipv6}}]:{{item.https.port}} ssl spdy ipv6only=on; 173 | {% else %} 174 | listen [{{item.ipv6}}]:{{item.https.port}} ssl ipv6only=on; 175 | {% endif %} 176 | {% endif %} 177 | 178 | server_name {{item.alternate_server_name}}; 179 | 180 | ## Keep alive timeout set to a greater value for SSL/TLS. 181 | keepalive_timeout 75 75; 182 | 183 | ## See the keepalive_timeout directive in nginx.conf. 184 | ## Server certificate and key. 185 | ssl_certificate {{item.https.certificate}}; 186 | ssl_certificate_key {{item.https.certificate_key}}; 187 | 188 | return 301 $scheme://{{item.server_name}}$request_uri; 189 | 190 | } # server domain return. 191 | {% endif %} 192 | 193 | ## HTTPS server. 194 | server { 195 | {% if nginx_drupal_use_spdy %} 196 | listen {{item.https.port}} ssl spdy; # IPv4 197 | {% else %} 198 | listen {{item.https.port}} ssl; # IPv4 199 | {% endif %} 200 | 201 | {% if item.ipv6 is defined %} 202 | {% if nginx_drupal_use_spdy %} 203 | listen [{{item.ipv6}}]:{{item.https.port}} ssl spdy ipv6only=on; 204 | {% else %} 205 | listen [{{item.ipv6}}]:{{item.https.port}} ssl ipv6only=on; 206 | {% endif %} 207 | {% endif %} 208 | 209 | server_name {{item.server_name}}{% if item.default|default(false) %} default{% endif %}; 210 | 211 | {% if item.limit_conn|default('None') != 'None' %} 212 | limit_conn {{item.limit_conn|default('arbeit 32')}}; 213 | {% endif %} 214 | 215 | ## Access and error logs. 216 | access_log {{nginx_drupal_log_path}}/{{item.server_name}}_access.log; 217 | error_log {{nginx_drupal_log_path}}/{{item.server_name}}_error.log; 218 | 219 | ## Keep alive timeout set to a greater value for SSL/TLS. 220 | keepalive_timeout 75 75; 221 | 222 | ## See the keepalive_timeout directive in nginx.conf. 223 | ## Server certificate and key. 224 | ssl_certificate {{item.https.certificate}}; 225 | ssl_certificate_key {{item.https.certificate_key}}; 226 | 227 | ## Strict Transport Security header for enhanced security. See 228 | ## http://www.chromium.org/sts. I've set it to 2 hours; set it to 229 | ## whichever age you want. 230 | add_header Strict-Transport-Security {{item.https.sts|default('max-age=7200')}}; 231 | 232 | root {{item.root}}; 233 | index index.php; 234 | 235 | ## If you're using a Nginx version greater or equal to 1.1.4 then 236 | ## you can use keep alive connections to the upstream be it 237 | ## FastCGI or Apache. If that's not the case comment out the line below. 238 | fastcgi_keep_conn on; # keep alive to the FCGI upstream 239 | 240 | {% if nginx_drupal_php_handling == 'proxy' %} 241 | proxy_http_version 1.1; # keep alive to the Apache upstream 242 | {% endif %} 243 | 244 | ## See the blacklist.conf file at the parent dir: /etc/nginx. 245 | ## Deny access based on the User-Agent header. 246 | if ($bad_bot) { 247 | return 444; 248 | } 249 | ## Deny access based on the Referer header. 250 | if ($bad_referer) { 251 | return 444; 252 | } 253 | 254 | ## Protection against illegal HTTP methods. Out of the box only HEAD, 255 | ## GET and POST are allowed. 256 | if ($not_allowed_method) { 257 | return 405; 258 | } 259 | 260 | server_name_in_redirect {{'on' if item.server_name_in_redirect|default(false) else 'off'}}; 261 | 262 | {% if item.rewrites is defined %} 263 | ## URL rewriting 264 | {% for rewrite in item.rewrites %} 265 | rewrite {{rewrite.regex}} {{rewrite.replacement}} {{rewrite.flags|default('')}}; 266 | {% endfor %} 267 | {%- endif %} 268 | 269 | {% if item.includes is defined %} 270 | ## Custom include(s) 271 | {% for include in item.includes %} 272 | include {{ include }}; 273 | {% endfor %} 274 | {% endif %} 275 | 276 | {% if item.custom_locations is defined %} 277 | ## Custom location(s) 278 | {% for location in item.custom_locations %} 279 | location {{ location.operator }} "{{ location.path }}" { 280 | {% if location.allowed_ips is defined %} 281 | {% for allowed_ip in location.allowed_ips %} 282 | allow {{ allowed_ip }}; 283 | {% endfor %} 284 | deny all; 285 | {% endif %} 286 | {% if location.denied_ips is defined %} 287 | {% for denied_ip in location.denied_ips %} 288 | deny {{ denied_ip }}; 289 | {% endfor %} 290 | {% endif %} 291 | {% if location.fastcgi_pass is defined %} 292 | include fastcgi_params; 293 | fastcgi_pass {{ location.fastcgi_pass }}; 294 | {%- if location.fastcgi_index is defined -%} 295 | fastcgi_index {{ location.fastcgi_index }}; 296 | {% endif %} 297 | {% else %} 298 | try_files $uri @drupal; 299 | {% endif %} 300 | } 301 | {% endfor %} 302 | {% endif %} 303 | 304 | include apps/drupal/drupal.conf; 305 | 306 | {%- if not nginx_drupal_use_drush %} 307 | ################################################################# 308 | ### Configuration for updating the site via update.php and running 309 | ### cron externally. If you don't use drush for running cron use 310 | ### the configuration below. 311 | ################################################################# 312 | include apps/drupal/drupal_cron_update.conf; 313 | {%- endif -%} 314 | 315 | ################################################################ 316 | ### Installation handling. This should be commented out after 317 | ### installation if on an already installed site there's no need 318 | ### to touch it. If on a yet to be installed site. Uncomment the 319 | ### line below and comment out after installation. Note that 320 | ### there's a basic auth in front as secondary ligne of defense. 321 | ################################################################ 322 | {% if nginx_drupal_allow_install -%} 323 | include apps/drupal/drupal_install.conf; 324 | {% else -%} 325 | #include apps/drupal/drupal_install.conf; 326 | {%- endif %} 327 | 328 | {% if nginx_drupal_upload_progress -%} 329 | ################################################################# 330 | ### Support for upload progress bar. Configurations differ for 331 | ### Drupal 6 and Drupal 7. 332 | ################################################################# 333 | include apps/drupal/drupal_upload_progress.conf; 334 | {%- endif %} 335 | 336 | {%- if nginx_drupal_php_handling == 'proxy' %} 337 | ## Including the php-fpm status and ping pages config. 338 | include php_fpm_status_vhost.conf; 339 | {%- endif %} 340 | 341 | ## Including the Nginx stub status page for having stats about 342 | ## Nginx activity: http://wiki.nginx.org/HttpStubStatusModule. 343 | include nginx_status_vhost.conf; 344 | 345 | } # HTTPS server 346 | {% endif %} 347 | -------------------------------------------------------------------------------- /templates/apps/drupal/drupal.j2: -------------------------------------------------------------------------------- 1 | # -*- mode: nginx; mode: flyspell-prog; ispell-local-dictionary: "american" -*- 2 | ## {{ ansible_managed }} 3 | ## Git ref: 81aa86d03f80e8f97d433cb541f63ee292531658 4 | ### Nginx configuration for Drupal. This configuration makes use of 5 | ### drush (http:///drupal.org/project/drush) for site maintenance 6 | ### and like tasks: 7 | ### 8 | ### 1. Run the cronjobs. 9 | ### 2. Run the DB and code updates: drush up or drush upc followed by 10 | ### drush updb to run any DB updates required by the code upgrades 11 | ### that were performed. 12 | ### 3. Disabling of xmlrpc.xml, install.php (needed only for 13 | ### installing the site) and update.php: all updates are now 14 | ### handled through drush. 15 | 16 | {% if nginx_drupal_escape_uri %} 17 | ## To avoid the ugly rewrite we use Lua to escape the URI. 18 | set_by_lua $escaped_uri 'return ngx.escape_uri(ngx.var.uri)'; 19 | {% endif %} 20 | 21 | {% set _nginx_drupal_uri = '$escaped_uri' if nginx_drupal_escape_uri else '$uri' %} 22 | 23 | ## The 'default' location. 24 | location / { 25 | 26 | ## Drupal 404 from can impact performance. If using a module like 27 | ## search404 then 404's *have *to be handled by Drupal. Uncomment to 28 | ## relay the handling of 404's to Drupal. 29 | ## error_page 404 /index.php; 30 | 31 | ## Using a nested location is the 'correct' way to use regexes. 32 | 33 | ## Regular private file serving (i.e. handled by Drupal). 34 | location ^~ /system/files/ { 35 | {%- if nginx_drupal_php_handling == 'php-fpm' or nginx_drupal_php_handling == 'php-cgi' %} 36 | ## Include the specific FastCGI configuration. 37 | include apps/drupal/fastcgi_drupal.conf; 38 | fastcgi_pass phpcgi; 39 | {%- endif -%} 40 | 41 | {%- if nginx_drupal_php_handling == 'proxy' %} 42 | ## Proxy configuration 43 | proxy_pass http://phpapache/index.php?q={{_nginx_drupal_uri}}; 44 | proxy_set_header Connection ''; 45 | {%- endif -%} 46 | 47 | ## For not signaling a 404 in the error log whenever the 48 | ## system/files directory is accessed add the line below. 49 | ## Note that the 404 is the intended behavior. 50 | log_not_found off; 51 | } 52 | 53 | ## Trying to access private files directly returns a 404. 54 | location ^~ /sites/default/files/private/ { 55 | internal; 56 | } 57 | 58 | ## Support for the file_force module 59 | ## http://drupal.org/project/file_force. 60 | location ^~ /system/files_force/ { 61 | {%- if nginx_drupal_php_handling == 'php-fpm' or nginx_drupal_php_handling == 'php-cgi' %} 62 | ## Include the specific FastCGI configuration. 63 | include apps/drupal/fastcgi_drupal.conf; 64 | fastcgi_pass phpcgi; 65 | {% endif %} 66 | 67 | {%- if nginx_drupal_php_handling == 'proxy' %} 68 | ## Proxy configuration 69 | proxy_pass http://phpapache/index.php?q={{_nginx_drupal_uri}}; 70 | proxy_set_header Connection ''; 71 | {% endif %} 72 | 73 | ## For not signaling a 404 in the error log whenever the 74 | ## system/files directory is accessed add the line below. 75 | ## Note that the 404 is the intended behavior. 76 | log_not_found off; 77 | } 78 | 79 | ## If accessing an image generated by Drupal 6 imagecache, serve it 80 | ## directly if available, if not relay the request to Drupal to (re)generate 81 | ## the image. 82 | location ~* /imagecache/ { 83 | {%- if nginx_drupal_hotlinking_protection %} 84 | ## Image hotlinking protection. 85 | include apps/drupal/hotlinking_protection.conf; 86 | {%- endif -%} 87 | 88 | access_log off; 89 | expires 30d; 90 | try_files {{_nginx_drupal_uri}} @drupal; 91 | } 92 | 93 | ## Drupal 7 generated image handling, i.e., imagecache in core. See: 94 | ## http://drupal.org/node/371374. 95 | location ~* /files/styles/ { 96 | {%- if nginx_drupal_hotlinking_protection %} 97 | ## Image hotlinking protection. 98 | include apps/drupal/hotlinking_protection.conf; 99 | {%- endif -%} 100 | 101 | access_log off; 102 | expires 30d; 103 | try_files {{_nginx_drupal_uri}} @drupal; 104 | } 105 | 106 | ## Advanced Aggregation module CSS 107 | ## support. http://drupal.org/project/advagg. 108 | location ^~ /sites/default/files/advagg_css/ { 109 | expires max; 110 | add_header ETag ''; 111 | add_header Last-Modified 'Wed, 20 Jan 1988 04:20:42 GMT'; 112 | add_header Accept-Ranges ''; 113 | 114 | location ~* /sites/default/files/advagg_css/css[_[:alnum:]]+\.css$ { 115 | access_log off; 116 | try_files {{_nginx_drupal_uri}} @drupal; 117 | } 118 | } 119 | 120 | ## Advanced Aggregation module JS 121 | ## support. http://drupal.org/project/advagg. 122 | location ^~ /sites/default/files/advagg_js/ { 123 | {% if nginx_drupal_use_boost %} 124 | add_header Pragma ''; 125 | add_header Cache-Control 'public, max-age=946080000'; 126 | {% else %} 127 | expires max; 128 | add_header ETag ''; 129 | add_header Last-Modified 'Wed, 20 Jan 1988 04:20:42 GMT'; 130 | {% endif %} 131 | add_header Accept-Ranges ''; 132 | 133 | location ~* /sites/default/files/advagg_js/js[_[:alnum:]]+\.js$ { 134 | access_log off; 135 | try_files {{_nginx_drupal_uri}} @drupal; 136 | } 137 | } 138 | 139 | {% if nginx_drupal_language_path_prefixes %} 140 | ## RSS feed support. 141 | location ~* ^(?:\/(?:{{ nginx_drupal_language_path_prefixes|join('|') }}))?\/rss\.xml$ { 142 | try_files {{_nginx_drupal_uri}} @drupal-no-args; 143 | } 144 | 145 | ## XML Sitemap support. 146 | location ~* ^(?:\/(?:{{ nginx_drupal_language_path_prefixes|join('|') }}))?\/sitemap\.xml$ { 147 | try_files {{_nginx_drupal_uri}} @drupal-no-args; 148 | } 149 | 150 | ## Core search support. 151 | location ~* ^(?:\/(?:{{ nginx_drupal_language_path_prefixes|join('|') }}))?\/search/.+/.+ { 152 | try_files {{_nginx_drupal_uri}} @drupal-no-args; 153 | } 154 | {% endif %} 155 | 156 | ## All static files will be served directly. 157 | location ~* ^.+\.(?:css|cur|js|jpe?g|gif|htc|ico|png|html|xml|otf|ttf|eot|woff|svg)$ { 158 | 159 | access_log off; 160 | expires 30d; 161 | ## No need to bleed constant updates. Send the all shebang in one 162 | ## fell swoop. 163 | tcp_nodelay off; 164 | ## Set the OS file cache. 165 | open_file_cache max=3000 inactive=120s; 166 | open_file_cache_valid 45s; 167 | open_file_cache_min_uses 2; 168 | open_file_cache_errors off; 169 | } 170 | 171 | ## Core search support. 172 | location ~* ^/search/.+/.+ { 173 | try_files {{_nginx_drupal_uri}} @drupal-no-args; 174 | } 175 | 176 | ## PDFs and powerpoint files handling. 177 | location ~* ^.+\.(?:pdf|pptx?)$ { 178 | expires 30d; 179 | ## No need to bleed constant updates. Send the all shebang in one 180 | ## fell swoop. 181 | tcp_nodelay off; 182 | } 183 | 184 | {% if nginx_drupal_aio %} 185 | ## MP3 and Ogg/Vorbis files are served using AIO when supported. Your OS must support it. 186 | location ^~ /sites/default/files/audio/mp3 { 187 | location ~* ^/sites/default/files/audio/mp3/.*\.mp3$ { 188 | directio 4k; # for XFS 189 | ## If you're using ext3 or similar uncomment the line below and comment the above. 190 | #directio 512; # for ext3 or similar (block alignments) 191 | tcp_nopush off; 192 | aio on; 193 | output_buffers 1 2M; 194 | } 195 | } 196 | 197 | location ^~ /sites/default/files/audio/ogg { 198 | location ~* ^/sites/default/files/audio/ogg/.*\.ogg$ { 199 | directio 4k; # for XFS 200 | ## If you're using ext3 or similar uncomment the line below and comment the above. 201 | #directio 512; # for ext3 or similar (block alignments) 202 | tcp_nopush off; 203 | aio on; 204 | output_buffers 1 2M; 205 | } 206 | } 207 | {% endif %} 208 | 209 | {% if nginx_drupal_flv_streaming %} 210 | ## Pseudo streaming of FLV files: 211 | ## http://wiki.nginx.org/HttpFlvStreamModule. 212 | ## If pseudo streaming isn't working, try to comment 213 | ## out in nginx.conf line with: 214 | ## add_header X-Frame-Options SAMEORIGIN; 215 | location ^~ /sites/default/files/video/flv { 216 | location ~* ^/sites/default/files/video/flv/.*\.flv$ { 217 | flv; 218 | } 219 | } 220 | {% endif %} 221 | 222 | {% if nginx_drupal_mp4_streaming %} 223 | ## Pseudo streaming of H264/AAC files. This requires an Nginx 224 | ## version greater or equal to 1.0.7 for the stable branch and 225 | ## greater or equal to 1.1.3 for the development branch. 226 | ## Cf. http://nginx.org/en/docs/http/ngx_http_mp4_module.html. 227 | location ^~ /sites/default/files/video/mp4 { # videos 228 | location ~* ^/sites/default/files/video/mp4/.*\.(?:mp4|mov)$ { 229 | mp4; 230 | mp4_buffer_size 1M; 231 | mp4_max_buffer_size 5M; 232 | } 233 | } 234 | 235 | location ^~ /sites/default/files/audio/m4a { # audios 236 | location ~* ^/sites/default/files/audio/m4a/.*\.m4a$ { 237 | mp4; 238 | mp4_buffer_size 1M; 239 | mp4_max_buffer_size 5M; 240 | } 241 | } 242 | {% endif %} 243 | 244 | ## Advanced Help module makes each module provided README available. 245 | location ^~ /help/ { 246 | location ~* ^/help/[^/]*/README\.txt$ { 247 | {%- if nginx_drupal_php_handling == 'php-fpm' or nginx_drupal_php_handling == 'php-cgi' %} 248 | ## Include the specific FastCGI configuration. 249 | include apps/drupal/fastcgi_drupal.conf; 250 | fastcgi_pass phpcgi; 251 | {%- endif -%} 252 | 253 | {%- if nginx_drupal_php_handling == 'proxy' %} 254 | ## Proxy configuration 255 | proxy_pass http://phpapache/index.php?q={{_nginx_drupal_uri}}; 256 | proxy_set_header Connection ''; 257 | {%- endif -%} 258 | } 259 | } 260 | 261 | ## Replicate the Apache directive of Drupal standard 262 | ## .htaccess. Disable access to any code files. Return a 404 to curtail 263 | ## information disclosure. Hide also the text files. 264 | location ~* ^(?:.+\.(?:htaccess|make|txt|engine|inc|info|install|module|profile|po|pot|sh|.*sql|test|theme|tpl(?:\.php)?|xtmpl)|code-style\.pl|/Entries.*|/Repository|/Root|/Tag|/Template)$ { 265 | return 404; 266 | } 267 | 268 | {% if nginx_drupal_use_boost %} 269 | ## First we try the URI and relay to the @cache if not found. 270 | try_files {{_nginx_drupal_uri}} @cache; 271 | {% else %} 272 | ## First we try the URI and relay to the /index.php?q=$uri&$args if not found. 273 | try_files {{_nginx_drupal_uri}} @drupal; 274 | {% endif %} 275 | } 276 | 277 | {% if nginx_drupal_use_boost %} 278 | ## We define a named location for the cache. 279 | location @cache { 280 | ## Boost compresses can the pages so we check it. Comment it out 281 | ## if you don't have it enabled in Boost. 282 | gzip_static on; 283 | 284 | ## Error page handler for the case where $no_cache is 1. POST 285 | ## request or authenticated. 286 | error_page 418 = @drupal; 287 | 288 | ## If $no_cache is 1 then it means that either we have a session 289 | ## cookie or that the request method is POST. So serve the dynamic 290 | ## page. 291 | if ($no_cache) { 292 | return 418; # I'm a teapot/I can't get no cachifaction 293 | } 294 | 295 | ## No caching for POST requests. 296 | if ($request_method = POST) { 297 | return 418; 298 | } 299 | 300 | # Now for some header tweaking. We use a date that differs 301 | # from stock Drupal. Everyone seems to be using their 302 | # birthdate. Why go against the grain? 303 | add_header Expires "Tue, 13 Jun 1977 03:45:00 GMT"; 304 | # We bypass all delays in the post-check and pre-check 305 | # parameters of Cache-Control. Both set to 0. 306 | add_header Cache-Control "must-revalidate, post-check=0, pre-check=0"; 307 | # Funny...perhaps. Egocentric? Damn right!; 308 | add_header X-Header "Boost Helás Avril 1.0"; 309 | ## Boost doesn't set a charset. 310 | charset utf-8; 311 | 312 | # We try each boost URI in succession, if every one of them 313 | # fails then relay to Drupal. 314 | try_files /cache/normal/$host${uri}_${args}.html /cache/perm/$host${uri}_.css /cache/perm/$host${uri}_.js /cache/$host/0$uri.html /cache/$host/0${uri}/index.html @drupal; 315 | } 316 | {% endif %} 317 | 318 | ########### Security measures ########## 319 | 320 | {%- if nginx_drupal_admin_basic_auth %} 321 | ## Enable basic auth for access to all /admin URIs. Note that this provides 322 | ## much better protection if use HTTPS. Since it can easily be eavesdropped if 323 | ## you use HTTP. 324 | include apps/drupal/admin_basic_auth.conf; 325 | {%- endif -%} 326 | 327 | ## Restrict access to the strictly necessary PHP files. Reducing the 328 | ## scope for exploits. Handling of PHP code and the Drupal event loop. 329 | location @drupal { 330 | {%- if nginx_drupal_php_handling == 'php-fpm' or nginx_drupal_php_handling == 'php-cgi' %} 331 | ## Include the FastCGI config. 332 | include apps/drupal/fastcgi_drupal.conf; 333 | fastcgi_pass phpcgi; 334 | 335 | {%- if nginx_drupal_microcache %} 336 | ## FastCGI microcache. 337 | include apps/drupal/microcache_fcgi.conf; 338 | {%- if nginx_drupal_microcache_auth %} 339 | ## FCGI microcache for authenticated users also. 340 | include apps/drupal/microcache_fcgi_auth.conf; 341 | {%- endif -%} 342 | {%- endif -%} 343 | {%- endif -%} 344 | 345 | {%- if nginx_drupal_php_handling == 'proxy' %} 346 | ## Proxy configutation 347 | proxy_pass http://phpapache/index.php?q={{_nginx_drupal_uri}}; 348 | proxy_set_header Connection ''; 349 | {%- if nginx_drupal_microcache %} 350 | ## Proxy microcache. 351 | include apps/drupal/microcache_proxy.conf; 352 | {%- if nginx_drupal_microcache_auth %} 353 | ## Proxy microcache for authenticated users also. 354 | include apps/drupal/microcache_proxy_auth.conf; 355 | {%- endif -%} 356 | {%- endif -%} 357 | {%- endif -%} 358 | 359 | {%- if nginx_drupal_upload_progress %} 360 | ## Filefield Upload progress 361 | ## http://drupal.org/project/filefield_nginx_progress support 362 | ## through the NginxUploadProgress modules. 363 | track_uploads uploads 60s; 364 | {% endif %} 365 | } 366 | 367 | location @drupal-no-args { 368 | {%- if nginx_drupal_php_handling == 'php-fpm' or nginx_drupal_php_handling == 'php-cgi' %} 369 | ## Include the FastCGI config. 370 | include apps/drupal/fastcgi_no_args_drupal.conf; 371 | fastcgi_pass phpcgi; 372 | 373 | {% if nginx_drupal_microcache %} 374 | {% if not nginx_drupal_microcache_auth %} 375 | ## FastCGI microcache. 376 | include apps/drupal/microcache_fcgi.conf; 377 | {% else %} 378 | ## FCGI microcache for authenticated users also. 379 | include apps/drupal/microcache_fcgi_auth.conf; 380 | {%- endif -%} 381 | {%- endif -%} 382 | {%- endif -%} 383 | 384 | {%- if nginx_drupal_php_handling == 'proxy' %} 385 | ## Proxy configutation 386 | proxy_pass http://phpapache/index.php?q={{_nginx_drupal_uri}}; 387 | proxy_set_header Connection ''; 388 | 389 | {%- if nginx_drupal_microcache %} 390 | {%- if not nginx_drupal_microcache_auth %} 391 | ## Proxy microcache. 392 | include apps/drupal/microcache_proxy.conf; 393 | {% else %} 394 | ## Proxy microcache for authenticated users also. 395 | include apps/drupal/microcache_proxy_auth.conf; 396 | {%- endif -%} 397 | {%- endif -%} 398 | {%- endif -%} 399 | } 400 | 401 | ## Disallow access to .bzr, .git, .hg, .svn, .cvs directories: return 402 | ## 404 as not to disclose information. 403 | location ^~ /.bzr { 404 | return 404; 405 | } 406 | 407 | location ^~ /.git { 408 | return 404; 409 | } 410 | 411 | location ^~ /.hg { 412 | return 404; 413 | } 414 | 415 | location ^~ /.svn { 416 | return 404; 417 | } 418 | 419 | location ^~ /.cvs { 420 | return 404; 421 | } 422 | 423 | ## Disallow access to patches directory. 424 | location ^~ /patches { 425 | return 404; 426 | } 427 | 428 | ## Disallow access to drush backup directory. 429 | location ^~ /backup { 430 | return 404; 431 | } 432 | 433 | ## Disable access logs for robots.txt. 434 | location = /robots.txt { 435 | access_log off; 436 | ## Add support for the robotstxt module 437 | ## http://drupal.org/project/robotstxt. 438 | try_files {{_nginx_drupal_uri}} @drupal-no-args; 439 | } 440 | 441 | ## RSS feed support. 442 | location = /rss.xml { 443 | try_files {{_nginx_drupal_uri}} @drupal-no-args; 444 | } 445 | 446 | ## XML Sitemap support. 447 | location = /sitemap.xml { 448 | try_files {{_nginx_drupal_uri}} @drupal-no-args; 449 | } 450 | 451 | ## Support for favicon. Return an 1x1 transparent GIF if it doesn't 452 | ## exist. 453 | location = /favicon.ico { 454 | expires 30d; 455 | try_files /favicon.ico @empty; 456 | } 457 | 458 | ## Return an in memory 1x1 transparent GIF. 459 | location @empty { 460 | expires 30d; 461 | empty_gif; 462 | } 463 | 464 | ## Any other attempt to access PHP files returns a 404. 465 | location ~* ^.+\.php$ { 466 | return 404; 467 | } 468 | 469 | ## Add support for custom monitoring script. 470 | location = /monitor/index.php { 471 | fastcgi_pass phpcgi; 472 | } 473 | 474 | ## Rewrite legacy requests with /index.php to extension-free URL. 475 | if ( $args ~* "^q=(?.*)" ) { 476 | rewrite ^/index.php$ $scheme://$host/?q=$query_value? permanent; 477 | } 478 | 479 | {% if nginx_drupal_use_boost %} 480 | ## Boost stats. 481 | location = /boost_stats.php { 482 | {%- if nginx_drupal_php_handling == 'php-fpm' or nginx_drupal_php_handling == 'php-cgi' %} 483 | fastcgi_pass phpcgi; 484 | {% endif %} 485 | 486 | {%- if nginx_drupal_php_handling == 'proxy' %} 487 | ## Proxy configuration 488 | proxy_pass http://phpapache 489 | {% endif %} 490 | } 491 | {% endif %} 492 | --------------------------------------------------------------------------------