HackerOne users: Testing against this community violates our program's Terms of Service and will result in your bounty being denied.

[Documentation] Self-hosted Vanilla on Nginx

LeeHLeeH
edited April 2012 in Feedback

I've spent the past couple of weeks bringing a self-hosted Vanilla forum online (using 2.1 and a customized version of Bittersweet), and I'd like to share the Nginx configuration I'm using in production. I based it off of a number of guides on the web and from this forum, but I've modified the security sections to provide additional protection, and I've cleaned up the logging somewhat. I've also added several rewrites to help keep things looking more like a traditional discussion forum.

There's a comprehensive blog post on my personal site that goes into details about what each section of the configuration does, but here's a cut-n-paste of the whole thing for reference:

server {
server_name your.forum.com;
root /var/www-vanilla;
index index.php default.php index.html;
autoindex off;
# Error handling
error_page 404 /dashboard/home/filenotfound;
error_page 403 =404 /dashboard/home/filenotfound;
# Root location
location / {
try_files $uri $uri/ @forum;
}
# Rewrite to prettify the URL and hide the ugly PHP stuff
location @forum {
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 /dashboard/notifications/inform { access_log off; log_not_found off; }
location /settings/analyticstick.json { 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 some undesirable behavior & force things 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; }
}

(Apologies for any formatting errors above. Had to do some surgery to make that all display correctly, because Markdown processing continues inside of code blocks...)

Comments

  • looks pretty good, thanks for sharing. I'm going to look at replacing my own setup with yours as it has some extra security and features I'd like.

  • jspautschjspautsch ✭✭✭

    Bookmarked!

  • Good work @leeh

    There was an error rendering this rich post.

  • AoleeAolee ✭✭

    +1

  • aeryaery ✭✭✭

    Thanks for sharing mate :)

    There was an error rendering this rich post.

  • Thanks, guys. Note that the PHP handler section refers by name to a predefined Unix socket:
    fastcgi_pass php5-fpm-sock;

    This is defined in /etc/nginx/conf.d/php5-fpm.conf, like this:

    upstream php5-fpm-sock {
    server unix:/var/run/php5-fpm.soc;
    }

    Obviously, this needs to be in place, either in that included conf file or in the site's definition above, or things will not work right. If your PHP instance is hosted on another box and you're passing PHP to it via an IP address & TCP port, obviously use that instead. (And if your PHP instance is local on the webserver and you're using a TCP port to pass PHP, you're doing it wrong! Use Unix sockets!)

  • LeeHLeeH
    edited April 2012

    __Important note:__

    I've discovered an issue with the above configuration that appears to prevent notifications from working correctly and also stops the discussion view count from incrementing. This line is the problem line and should be omitted:

    location /dashboard/notifications/inform { access_log off; log_not_found off; }

    Comment out or delete that line.

    I'd put it in to prevent the access log from being gunked up with tons and tons of messages referencing /dashboard/notification/inform, but it appears that it actually has a deleterious effect on notifications in general and the discussion counter. I'm guessing, but the problem behavior appears to stem from Nginx expecting the path named in a location directive to actually exist on the web server; because /dashboard/notifications/inform isn't actually anywhere in the directory structure, every time Vanilla attempts to POST to it, the web server kicks replies with a 404, and so anything sent there is lost.

    I probably should have realized this sooner, but at least I figured it out now before my users got too angry with me :)

    I can no longer edit the original post in the thread, but I'll update the linked blog entry.

    edited to add:
    On reflection, probably also a good idea to omit this line, too:

    location /settings/analyticstick.json { access_log off; log_not_found off; }

Sign In or Register to comment.