├── conf.d ├── domain-redirects.conf └── domain-rules.conf ├── README.md └── nginx.conf /conf.d/domain-redirects.conf: -------------------------------------------------------------------------------- 1 | # Other domain rewrites 2 | 3 | # Two formats; uncomment and make more/use as needed 4 | # server { 5 | # listen 80; 6 | # server_name old-domain.com www.old-domain.com; 7 | # return 301 http://www.domain.com/new-page; 8 | # } 9 | 10 | # server { 11 | # listen 80; 12 | # server_name old-domain2.com www.old-domain2.com; 13 | # rewrite ^/feed$ http://feeds2.feedburner.com/domain/feed permanent; 14 | # rewrite ^/(.*)$ http://www.domain.com/path/$1 permanent; 15 | # } 16 | 17 | # Force www 18 | # server { 19 | # listen 80 default_server; 20 | # server_name ""; 21 | # rewrite ^/(.*)$ http://www.domain.com/$1 permanent; 22 | # } -------------------------------------------------------------------------------- /conf.d/domain-rules.conf: -------------------------------------------------------------------------------- 1 | # Start CE Cache static rewrites -- uncomment if using CE Static Caching 2 | 3 | # # Remove trailing slash 4 | # if ($request_method = GET) { 5 | # rewrite ^/(.*)/$ /$1 permanent; 6 | # } 7 | 8 | 9 | # # Makes sure CE Cache won't work for non-GET requests 10 | # if ($request_method !~* GET) { 11 | # set $request_var nonget; 12 | # } 13 | 14 | # # Doesn't trigger CE Cache for a URL containing ACT or URL 15 | # if ($args ~* (ACT|URI)) { 16 | # set $uri_var acturl; 17 | # } 18 | 19 | # if (-e /var/www/html/domain/static/ce_cache/xxxxxx/static/$request_uri$request_var$uri_var/index.html) { 20 | # rewrite ^(.*) /_static_cache_handler.php?$1/index.html last; 21 | # } 22 | 23 | # End CE Cache static rewrites 24 | 25 | # Replace the .htaccess deny from alls EE uses 26 | location ~ /(system/expressionengine/utilities|system/expressionengine/cache|system/codeigniter/system|assets/templates|assets/low_variables|assets/third_party/super_search/language/english|assets/third_party/ce_img/fonts|static) { 27 | deny all; 28 | } 29 | 30 | # Force SSL redirects on certain paths 31 | # if ($server_port = 80) { 32 | # rewrite ^/(account|checkout) https://$host$request_uri permanent; 33 | # } 34 | 35 | 36 | ## Format for redirects where the path is kept, but prepended or put somewhere else in the new site: 37 | # rewrite ^/folder1/folder2(.*)$ /new-folder$1 permanent; 38 | # rewrite ^/articles/(.*).html$ /articles/read/$1/ permanent; 39 | 40 | 41 | ## Format for redirects where you want to redirect a set path, regardless of trailing slash 42 | # rewrite ^/folder1/?$ /new-folder/ permanent; 43 | 44 | ## Format for redirects of files including .html 45 | # rewrite ^/old/path/file.html$ /new-path/ permanent; 46 | 47 | 48 | # Rules for For CORS and caching 49 | # location ~* (\.(ttf|ttc|otf|eot|woff))|fonts.css$ { 50 | # add_header Access-Control-Allow-Origin *; 51 | # add_header Cache-Control 'max-age=2592000'; 52 | # } 53 | 54 | # location ~* \.(gif|jpe?g|png|css|js|ico)$ { 55 | # add_header Cache-Control 'max-age=1209600'; 56 | # } 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nginx configuration for ExpressionEngine 2 | 3 | At [Vector Media Group](http://www.vectormediagroup.com) we're big fans of nginx. It's often a much faster and more stable alternative to Apache -- especially on projects getting heavy concurrent traffic. We use it on as many ExpressionEngine (and other CMS) sites as possible, so have created a template to use as a starting point on our projects. 4 | 5 | This configuration has support and working code for: 6 | 7 | * SSL/TLS (and has been patched to prevent the POODLE attack) 8 | * ExpressionEngine `index.php` rewriting 9 | * CE Cache static caching 10 | * Arbitrary domain and URL path 301 redirects 11 | * Forced SSL on certain sections or all pages of the site 12 | * Cross-origin resource sharing (CORS) 13 | * Far-future `expires` headers on static assets 14 | 15 | ## Instructions to deploy this nginx setup 16 | 17 | * Run `yum install php54-fpm nginx` or its equivalent for your server OS and desired versions to install nginx and PHP-FPM. 18 | * Place this repository's files in `/etc/nginx` and `/etc/nginx/conf.d`, leaving any other existing files. 19 | * Rename `domain-redirects.conf` and `domain-rules.conf` to use your actual domain (e.g. `vectormediagroup.com-rules.conf`) 20 | * Change "domain" in the three files to the main domain of the site 21 | * In `nginx.conf`: 22 | * Update the `server_name` directive for the real domain 23 | * Update the `root` directive to point to the real docroot (e.g. `/var/www/html/vectormediagroup`) 24 | * Update the `include` paths for `domain-redirects.conf` and `domain-rules.conf` to match their new names 25 | * Update the `fastcgi_param SCRIPT_FILENAME` path 26 | * You only need to change the `/domain` part of this line to match the real docroot. Here's a working example of what this line can ultimately look like: 27 | ```fastcgi_param SCRIPT_FILENAME /var/www/html/vectormediagroup$fastcgi_script_name;``` 28 | * If you're using SSL: 29 | * Update the SSL certificate paths 30 | * Uncomment `listen 443 ssl` and the SSL certificate paths 31 | * Replace `ssl_certificate` with your SSL certificate file. If you have a CA Bundle, [concatenate it after your main certificate file](http://nginx.org/en/docs/http/configuring_https_servers.html#chains) 32 | * Replace `ssl_certificate_key` with your SSL private key. 33 | * In `domain-redirects.conf`: 34 | * Add domain redirects if needed by uncommenting lines and updating the examples as appropriate. 35 | * Uncomment the last directive and replace `www.domain.com` with the production domain to force `www` in URLs 36 | * In `domain-rules.conf`: 37 | * If you're using CE Cache static caching, uncomment the top "CE Cache static" section (everything through "`# End CE Cache static rewrites`") and replace `xxxxxx` in the cache path with the actual value provided by CE Cache. 38 | * Look for the rule that replaces `.htaccess` `Deny` files. Replace `system` with the site's actual `system`/control panel path. 39 | * Add any other folders/paths that would usually need `Deny from all` to this directive (remember, nginx doesn't parse `.htaccess` files) 40 | * Uncomment any other commented blocks if you need any of the other rules in place. We've left a few examples to follow. 41 | 42 | ### Server notes 43 | * On CentOS or RHEL run the following to start nginx and PHP-FPM, and make sure they start on reboot: 44 | 45 | ```bash 46 | service nginx start 47 | chkconfig nginx on 48 | service php-fpm start 49 | chkconfig php-fpm on 50 | ``` 51 | 52 | * You'll need to run `service nginx reload` for any config changes to take effect. 53 | 54 | #### Warranty/Notes 55 | 56 | There's no warranty of any kind. If you have a suggestion, please open a ticket and we'll take a look. This configuration is provided completely as-is; if something breaks, you lose data, or something else bad happens, the author(s) and owner(s) of this code are in no way responsible. 57 | 58 | The SSL cipher choices are as listed in [Mozilla's TLS suggestions](https://wiki.mozilla.org/Security/Server_Side_TLS) as of this document's writing. We strongly suggest keeping up with that list and making updates as needed, even if not mentioned here. 59 | -------------------------------------------------------------------------------- /nginx.conf: -------------------------------------------------------------------------------- 1 | # For more information on configuration, see: 2 | # * Official English Documentation: http://nginx.org/en/docs/ 3 | # * Official Russian Documentation: http://nginx.org/ru/docs/ 4 | 5 | user nginx; 6 | worker_processes auto; 7 | 8 | error_log /var/log/nginx/error.log; 9 | #error_log /var/log/nginx/error.log notice; 10 | #error_log /var/log/nginx/error.log info; 11 | 12 | pid /var/run/nginx.pid; 13 | 14 | 15 | events { 16 | worker_connections 1024; 17 | } 18 | 19 | 20 | http { 21 | include /etc/nginx/mime.types; 22 | default_type application/octet-stream; 23 | 24 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 25 | '$status $body_bytes_sent "$http_referer" ' 26 | '"$http_user_agent" "$http_x_forwarded_for"'; 27 | 28 | access_log /var/log/nginx/access.log main; 29 | 30 | sendfile on; 31 | #tcp_nopush on; 32 | 33 | #keepalive_timeout 0; 34 | keepalive_timeout 65; 35 | 36 | gzip on; 37 | gzip_vary on; 38 | gzip_proxied any; 39 | gzip_comp_level 6; 40 | gzip_buffers 16 8k; 41 | gzip_http_version 1.1; 42 | gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; 43 | 44 | ssl_session_timeout 5m; 45 | ssl_session_cache shared:SSL:50m; 46 | 47 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 48 | ssl_ciphers 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:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA; 49 | ssl_prefer_server_ciphers on; 50 | 51 | client_max_body_size 2g; 52 | 53 | root /var/www/html/domain; 54 | 55 | index index.php index.html index.htm; 56 | 57 | server_tokens off; 58 | 59 | include /etc/nginx/conf.d/domain-redirects.conf; 60 | 61 | server { 62 | listen 80; 63 | # listen 443 ssl; 64 | 65 | # ssl_certificate /etc/nginx/ssl/domain.com.fullchain.crt; 66 | # ssl_certificate_key /etc/nginx/ssl/domain.com.key; 67 | 68 | server_name www.domain.com; 69 | 70 | location /nginx_status { 71 | stub_status on; 72 | access_log off; 73 | allow 127.0.0.1; 74 | deny all; 75 | } 76 | 77 | include /etc/nginx/conf.d/domain-rules.conf; 78 | 79 | location ~ /\. { 80 | access_log off; 81 | log_not_found off; 82 | deny all; 83 | } 84 | 85 | # EE rewrite 86 | try_files $uri $uri/ /index.php?$args; 87 | 88 | # error_page 404 /index.php; 89 | 90 | # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 91 | 92 | location ~ \.php$ { 93 | 94 | # If your PHP-FPM is on a different server from nginx, you'll need to take steps 95 | # to make sure PHP isn't processing arbitrary files. Make sure to research vulnerabilities 96 | # based on your own setup. 97 | try_files $uri =404; 98 | fastcgi_pass 127.0.0.1:9000; 99 | fastcgi_index index.php; 100 | fastcgi_param SCRIPT_FILENAME /var/www/html/domain$fastcgi_script_name; 101 | include fastcgi_params; 102 | fastcgi_read_timeout 120s; 103 | client_body_buffer_size 128k; 104 | fastcgi_buffers 8 16k; 105 | fastcgi_buffer_size 32k; 106 | } 107 | 108 | } 109 | 110 | } 111 | --------------------------------------------------------------------------------