location ~ ^(/forum.+\.php)$ {
root /home/beregov/Projects/needfixmycar/workspace/nfmc-web;
try_files $uri $uri/ /forum/index.php?p=$uri;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
include fastcgi_params;
fastcgi_index /forum/index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/var/run/php5-fpm.sock;
}
location /forum {
root /home/beregov/Projects/needfixmycar/workspace/nfmc-web;
try_files $uri $uri/ /forum/index.php?p=$uri;
}
If you're going to clone the Git repo, don't run the forum directly from it, as it will make updates difficult. Instead, copy the clone's contents (minus the actual Git folders) to your intended web root. We're going to be running the forum on its own subdomain, rather than out of a subdirectory, as this will make the configuration a bit easier. It also means that pulls from the repo won't clobber the existing site and lead to errors.
Below is the entire configuration in use for the forum, for cutting and pasting. We'll go through it piece by piece. There is also a Vanilla configuration file to modify, which we'll do after we get Nginx all set.
server { server_name your.forum.com; root /var/www-vanilla; index index.php default.php index.html; autoindex off;# Root location location / { try_files $uri $uri/ @forum; }# Rewrite to prettify the URL and hide the ugly PHP stuff location @forum {# Start with this commented out until you configure it in Vanilla! # rewrite ^/(.+)$ /index.php?p=$1 last; }# PHP handler location ~ \.php { try_files $uri =404; include fastcgi_params; fastcgi_pass php5-fpm-sock; fastcgi_split_path_info ^(.+\.php)(.*)$; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_intercept_errors on; }# Stop things from executing in the uploads directory location ~* ^/uploads/.*.(html|htm|shtml|php)$ { types { } default_type text/plain; }# Keep nosey people from discivering categories by number location ~* /categories/([0-9]|[1-9][0-9]|[1-9][0-9][0-9])$ { return 404; }# Deny, drop, or internal locations location ~ /\. { access_log off; log_not_found off; deny all; } location ~ ~$ { access_log off; log_not_found off; deny all; } location = /robots.txt { access_log off; log_not_found off; } location ^~ favicon { access_log off; log_not_found off; } location ^~ /conf/ { internal; }# Taking advantage of browser caching for static stuff location ~* \.(js|css|png|jpg|jpeg|gif|ico|eot|woff|ttf|svg)$ { expires max; log_not_found off; }# Change Vanilla's undesirable behavior & force it to display things like a traditional forum location = /discussions { rewrite ^ $scheme://your.forum.com/ permanent; } location = /discussions/ { rewrite ^ $scheme://your.forum.com/ permanent; } location = /categories/discussions { rewrite ^ $scheme://your.forum.com/ permanent; } location = /categories/discussions/ { rewrite ^ $scheme://your.forum.com/ permanent; } location /vanilla/discussions { rewrite ^ $scheme://your.forum.com/ permanent; } location /vanilla/discussions/ { rewrite ^ $scheme://your.forum.com/ permanent; }# Plug-in specific rules # # Keep the WhosOnline plugin from flooding the logs location /plugin/imonline { access_log off; log_not_found off; }}
server_name your.forum.com; root /var/www-vanilla; index index.php default.php index.html; autoindex off;
We open with the usual Nginx server directive, specifing the site's hostname, the directory on disk where the site's web root is located, and the files to use as index files for each subdirectory. We also disable autoindex generation, to keep people from poking around in your subdirectories. We're omitting the listening port, which by default is port 80; if you were going to use a non-standard TCP port, this would be the place to put it.
In the original version of the post, I had a section in here on overriding Vanilla's default error handling some Nginx error_page
directives, but it turns out that this causes some problems with displaying properly-skinned error pages; the default error page atdashboard/home/filenotfound
isn't a whole page, but rather gets included inside of another page when Vanilla serves it, and so calling it directly either yields another 404 error (which gets displayed as a standard Nginx 404) or an incomplete, malformed PHP response (which shows up as a blank page). The best way to serve up proper error pages is to rely on Vanilla's built-in error handling, which doesn't require you to do anything special at all.
Still, if you want to supply your own errors instead of using the built-in ones, you would do it with a block of code like this:
# Error handling error_page 404 /path/to/your/error/page.html; error_page 403 =404 /path/to/your/error/page.html;
I like to violate standards and return 404 responses to forbidden locations. A "403 Forbidden" feels too much like a big fat challenge that says, "There's something interesting here but you can't look at it!" Rather than wave a red flag over areas of the site that shouldn't be accessible, it's a lot less provocative to return 404 errors instead.
There are lots of other things you can do with custom responses within the Vanilla forum software, using routes, which function a bit like Nginx location directives. For more info on constructing custom routes, check out this page on the official Vanilla forum site.
# Root location location / { try_files $uri $uri/ @forum; }# Rewrite to prettify the URL and hide the ugly PHP stuff # Start with this commented out until you configure it in Vanilla! location @forum {# rewrite ^/(.+)$ /index.php?p=$1 last; }
Here we set up our root location, using the try_files
directive to tell Nginx that for any URI it receives, it should first see if the URI corresponds exactly to an object on the server, and then a directory, and then to pass the URI on to the forum
named location.
Then, we define that named location. The reason for using a named location like this is so that we have something onto which we can tag our main SEO-friendly rewrite rule, which takes all the Vanilla forum URLs ending in index.php
and makes them more human-readable.
However, the actual rewrite directive should be commented out until you've enabled friendly URLs in the Vanilla config file. Otherwise, your forum won't work. We'll go over that change after we've finished with the Nginx config breakdown.
location ~ \.php { try_files $uri =404; include fastcgi_params; fastcgi_pass php5-fpm-sock; fastcgi_split_path_info ^(.+\.php)(.*)$; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_intercept_errors on; }
This is a standard PHP block to ensure that all PHP files are sent via Unix socket (pre-defined in another file with the alias php5-fpm-sock
) to the PHP-FPM handler. The one difference between this PHP block and the others I've used before is the inclusion of the splitpathinfo
(described here). This additional prameter helps PHP understand what part of the path being passed to it is the script it needs to execute and what parts are the arguments on which the script needs to act.
# Stop things from executing in the uploads directory location ~* ^/uploads/.*.(html|htm|shtml|php)$ { types { } default_type text/plain; }# Keep nosey people from discivering categories by number location ~* /categories/([0-9]|[1-9][0-9]|[1-9][0-9][0-9])$ { return 404; }
Like most forum solutions, Vanilla has a directory (uploads
) where forum users can store avatars. Vanilla has restrictions in place to keep users from uploading files other than images, but it's always possible that someone with mischief or mayhem on the brain will be able to work around those restrictions. As an added layer of security, the first location directive above forces potentially-executable content (HTML files, SHTML files, and PHP files) to be served out of the uploads directory with their mime types set as text/plain
.
The second block works around a non-critical but potentially annoying issue. Categories (individual discussion forums, in traditional forum parlance) in Vanilla are browsable by name or by number. Having them browsable by name isn't an issue, but being browsable by number means that curious folks can start plugging in numbers and get an idea of how many categories your forum employs. In a forum with moderator- or administrator-only forums that are otherwise hidden from view, this gives curious users more insight than they should have about the structure of your forum. So, to prevent this, the location directive above uses a regex to watch out for URLs containing /categories/1
through /categories/999
(along with variations with leading zeros) and serve up a 404 page instead.
location ~ /\. { access_log off; log_not_found off; deny all; } location ~ ~$ { access_log off; log_not_found off; deny all; } location = /robots.txt { access_log off; log_not_found off; } location ^~ favicon { access_log off; log_not_found off; } location ^~ /conf/ { internal; }
This set of locations help tighten up some other potential security holes, as well as keep your logs from filling up with extraneous stuff. The first two block access to temp or hidden files (beginning with a dot or a dollar sign); the next two turn off logging for your site's robots.txt
file and favicon.
The last item throws up a barrier to accessing the /conf/
directory, where Vanilla keeps files that have potentially sensitive information in them (like the Vanilla MySQL account name and password). Now, on one hand, all of the config files are PHP files and are prefaced with this line:
if (!defined('APPLICATION')) exit();
This by itself is enough to keep them from being accessed as long as your PHP handler is functioning correctly. However, securing the files using the web server adds an extra layer of protection that will come into play if your web server's PHP processes ever die.
In our case, we're using Nginx's internal
directive, which allows the location to be accessed through a script or by the web server itself, but disallows serving files directly out of the location.
location ~* \.(js|css|png|jpg|jpeg|gif|ico|eot|woff|ttf|svg)$ { expires max; log_not_found off; }
This block instructs the web server to add a "max" expiry time to some common image and web font file types, so that those files will stay cached in users' web browsers for as long as possible. This reduces the load on the web server by not having it dish up the same static, unchanging files over and over again.
location = /discussions { rewrite ^ $scheme://your.forum.com/ permanent; } location = /discussions/ { rewrite ^ $scheme://your.forum.com/ permanent; } location = /categories/discussions { rewrite ^ $scheme://your.forum.com/ permanent; } location = /categories/discussions/ { rewrite ^ $scheme://your.forum.com/ permanent; } location /vanilla/discussions { rewrite ^ $scheme://your.forum.com/ permanent; } location /vanilla/discussions/ { rewrite ^ $scheme://your.forum.com/ permanent; }
I prefer my forums to act like a traditional forum, without a flat view of all discussions. Vanilla provides some means to make that its default behavior, but some plug-ins break or bypass the default homepage view. It's one thing for a user to manually access a list of all discussions, but I don't ever want such a page served up automatically in response to a seemingly-innocent link. So, the above list of rewrites covers all of the scenarios I've found so far where this happens.
Setting these rules to be active is admin's preference. If you like the discussion-oriented nature of Vanilla and prefer to minimize the role of categories, then you probably don't want to use any of these.
# Keep the WhosOnline plugin from flooding the logs location /plugin/imonline { access_log off; log_not_found off; }
We close with a location directive that prevents logging the pings from the WhosOnline plugin. This is an indispensable plugin which, as its name suggests, shows which users are currently on-line and browsing the forum. When active, this plugin's user-generated responses clog up your log files like nobody's business, so we'll get rid of them.
All of the stuff above should go into a file in your /etc/nginx/sites-available
directory. To actually bring the site online, symlink the file into your /etc/nginx/sites-enabled
directory:
$ sudo ln -s /etc/nginx/sites-available/vanilla /etc/nginx/sites-enabled/vanilla
Then reload Nginx's configuration ($ sudo /etc/init.d/nginx reload
) and the configuration will be active. Once this has all been done, you can actually start the Vanilla forums install procedure.
After you've gotten your forum up and running, you'll probably want to enable pretty URLs. To do this, add the following line in conf/config.php
:
$Configuration['Garden']['RewriteUrls'] = TRUE;
Then, uncomment the rewrite line in this section of your Nginx configuration:
location @forum { rewrite ^/(.+)$ /index.php?p=$1 last;}
Finally, reload Nginx to make your changes active. Vanilla should now be up and running securely, with friendly URLs.