From 26ed69508a183c9a43f1f7b1ad563392a72c4a3f Mon Sep 17 00:00:00 2001 From: Christian Lohmaier Date: Mon, 22 Apr 2013 01:51:00 +0200 Subject: [PATCH] fix nginx documentation to one that actually works :-) example configuration wuldn't allow to install silverstripe, as install.php does exist as a regular file (and that was ignored in the old version of the documentation) Similarily, the last rule in the htaccess snippet that should allow the access to the tinymce php files were never applied, as a previously listed regex did match and denied access. Even if it would have taken effect: as those files do exist on disk, they would have been handed out as-is and not been interpreted by php. Also the statement regarding accidental/exploitable execution of arbitrary php was misleading (and to some degree even wrong) in the old context. squashed commit as per pr#1791 --- docs/en/installation/nginx.md | 163 ++++++++++++++++++++++++---------- 1 file changed, 114 insertions(+), 49 deletions(-) diff --git a/docs/en/installation/nginx.md b/docs/en/installation/nginx.md index b9390385d..844a6d296 100644 --- a/docs/en/installation/nginx.md +++ b/docs/en/installation/nginx.md @@ -6,83 +6,147 @@ These instructions are also covered in less detail on the The prerequisite is that you have already installed Nginx and you are able to run PHP files via the FastCGI-wrapper from Nginx. -Now you need to set up a virtual host in Nginx with the following -configuration settings: +Now you need to set up a virtual host in Nginx with configuration settings +that are similar to those shown below. +
+If you don't fully understand the configuration presented here, consult the +[nginx documentation](http://nginx.org/en/docs/). + +Especially be aware of [accidental php-execution](https://nealpoole.com/blog/2011/04/setting-up-php-fastcgi-and-nginx-dont-trust-the-tutorials-check-your-configuration/ "Don't trust the tutorials") when extending the configuration. +
+But enough of the disclaimer, on to the actual configuration — typically in `nginx.conf`: server { listen 80; - - # SSL configuration (optional, but recommended for security) - include ssl - - root /var/www/example.com; - index index.php index.html index.htm; - server_name example.com; - include silverstripe3; - include htaccess; + root /var/www/example.com; + + # SSL configuration (optional, but recommended for security) + # (remember to actually force logins to use ssl) + include ssl + + include silverstripe3.conf; + include htaccess.conf; + + # rest of the server section is optional, but helpful + # maintenance page if it exists + error_page 503 @maintenance; + if (-f $document_root/maintenance.html ) { + return 503; + } + location @maintenance { + try_files /maintenance.html =503; + } + + # always show SilverStripe's version of 500 error page + error_page 500 /assets/error-500.html; + + # let the user's browser cache static files (e.g. 2 weeks) + expires 2w; + + # in case your machine is slow, increase the timeout + # (also remembers php's own timeout settings) + #fastcgi_read_timeout 300s; } -Here is the include file `silverstripe3`: +Here is the include file `silverstripe3.conf`: location / { try_files $uri @silverstripe; } - + + # only needed for installation - disable this location (and remove the + # index.php and install.php files) after you installed SilverStripe + # (you did read the blogentry linked above, didn't you) + location ~ ^/(index|install).php { + fastcgi_split_path_info ^((?U).+\.php)(/?.+)$; + include fastcgi.conf; + fastcgi_pass unix:/run/php-fpm/php-fpm-silverstripe.sock; + } + + # whitelist php files that are called directly and need to be interpreted + location = /framework/thirdparty/tinymce/tiny_mce_gzip.php { + include fastcgi.conf; + fastcgi_pass unix:/run/php-fpm/php-fpm-silverstripe.sock; + } + location = /framework/thirdparty/tinymce-spellchecker/rpc.php { + include fastcgi.conf; + fastcgi_pass unix:/run/php-fpm/php-fpm-silverstripe.sock; + } + location @silverstripe { - include fastcgi_params; - - # Defend against arbitrary PHP code execution - # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini - # More info: - # https://nealpoole.com/blog/2011/04/setting-up-php-fastcgi-and-nginx-dont-trust-the-tutorials-check-your-configuration/ - fastcgi_split_path_info ^(.+\.php)(/.+)$; - + expires off; + include fastcgi.conf; + fastcgi_pass unix:/run/php-fpm/php-fpm-silverstripe.sock; + # note that specifying a fixed script already protects against execution + # of arbitrary files, but remember the advice above for any other rules + # you add yourself (monitoring, etc,....) fastcgi_param SCRIPT_FILENAME $document_root/framework/main.php; fastcgi_param SCRIPT_NAME /framework/main.php; fastcgi_param QUERY_STRING url=$uri&$args; - fastcgi_pass unix:/var/run/php5-fpm.sock; - fastcgi_index index.php; - fastcgi_buffer_size 32k; - fastcgi_buffers 4 32k; - fastcgi_busy_buffers_size 64k; + # tuning is up to your expertise, but buffer_size needs to be >= 8k, + # otherwise you'll get "upstream sent too big header while reading + # response header from upstream" errors. + fastcgi_buffer_size 8k; + #fastcgi_buffers 4 32k; + #fastcgi_busy_buffers_size 64k; } +
+With only the above configuration, nginx would hand out any existing file +uninterpreted, so it would happily serve your precious configuration files, +including all your private api-keys and whatnot to any random visitor. So you +**must** restrict access further. +
+You don't need to use separate files, but it is easier to have the permissive +rules distinct from the restricting ones. -Here is the include file `htaccess`: +Here is the include file `htaccess.conf`: - # Don't serve up any .htaccess files - location ~ /\.ht { - deny all; - } - - # Deny access to silverstripe-cache - location ~ ^/silverstripe-cache { - deny all; - } - - # Don't execute scripts in the assets + # Don't try to find nonexisting stuff in assets (esp. don't pass through php) location ^~ /assets/ { - try_files $uri $uri/ =404; + try_files $uri =404; } - # Block access to yaml files - location ~ \.yml$ { + # Deny access to silverstripe-cache, vendor or composer.json/.lock + location ^~ /silverstripe-cache/ { + deny all; + } + location ^~ /vendor/ { + deny all; + } + location ~ /composer\.(json|lock) { deny all; } - # cms & framework .htaccess rules - location ~ ^/(cms|framework|mysite)/.*\.(php|php[345]|phtml|inc)$ { + # Don't serve up any "hidden" files or directories + # (starting with dot, like .htaccess or .git) + # also don't serve web.config files + location ~ /(\.|web\.config) { + deny all; + } + + # Block access to yaml files (and don't forget about backup + # files that editors tend to leave behind) + location ~ \.(yml|bak|swp)$ { + deny all; + } + location ~ ~$ { + deny all; + } + + # generally don't serve any php-like files + # (as they exist, they would be served as regular files, and not interpreted. + # But as those can contain configuration data, this is bad nevertheless) + # If needed, you can always whitelist entries. + location ~ \.(php|php[345]|phtml|inc)$ { deny all; } location ~ ^/(cms|framework)/silverstripe_version$ { deny all; } - location ~ ^/framework/.*(main|static-main|rpc|tiny_mce_gzip)\.php$ { - allow all; - } Here is the optional include file `ssl`: @@ -95,8 +159,9 @@ Here is the optional include file `ssl`: The above configuration sets up a virtual host `example.com` with rewrite rules suited for SilverStripe. The location block named -`@silverstripe` passes all php scripts to the FastCGI-wrapper via a Unix -socket. This example is from a site running Ubuntu with the php5-fpm -package. +`@silverstripe` passes all requests that aren't matched by one of the other +location rules (and cannot be satisfied by serving an existing file) to +SilverStripe framework's main.php script, that is run by the FastCGI-wrapper, +that in turn is accessed via a Unix socket. Now you can proceed with the SilverStripe installation normally.