Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Try Vanilla Forums Cloud product

Ready to contribute?

Amazing! Sign our contributors' agreement and then join us on GitHub.

Update for critical security issue in PHPMailer included in release Vanilla 2.3.1

[Documentation] Self-hosted Vanilla on Nginx

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 {<br /> server_name;<br /> root /var/www-vanilla;<br /> index index.php default.php index.html;<br /> autoindex off;<br /> &#035; Error handling<br /> error_page 404 /dashboard/home/filenotfound;<br /> error_page 403 =404 /dashboard/home/filenotfound;<br /> &#035; Root location<br /> location / {<br /> try_files $uri $uri/ @forum;<br /> }<br /> &#035; Rewrite to prettify the URL and hide the ugly PHP stuff<br /> location @forum {<br /> rewrite ^/(.+)$ /index.php?p=$1 last;<br /> }<br /> &#035; PHP handler<br /> location ~ &#92;.php {<br /> try_files $uri =404;<br /> include fastcgi_params;<br /> fastcgi_pass php5-fpm-sock;<br /> fastcgi_split_path_info ^(.+&#92;.php)(.&#042;)$;<br /> fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;<br /> fastcgi_intercept_errors on;<br /> }<br /> &#035; Stop things from executing in the uploads directory<br /> location ~&#042; ^/uploads/.&#042;.(html|htm|shtml|php)$ {<br /> types { }<br /> default_type text/plain;<br /> }<br /> &#035; Keep nosey people from discivering categories by number<br /> location ~&#042; /categories/([0-9]|[1-9][0-9]|[1-9][0-9][0-9])$ {<br /> return 404;<br /> }<br /> &#035; Deny, drop, or internal locations<br /> location ~ /&#92;. { access_log off; log_not_found off; deny all; }<br /> location ~ ~$ { access_log off; log_not_found off; deny all; }<br /> location = /robots.txt { access_log off; log_not_found off; }<br /> location ^~ favicon { access_log off; log_not_found off; }<br /> location /dashboard/notifications/inform { access_log off; log_not_found off; }<br /> location /settings/analyticstick.json { access_log off; log_not_found off; }<br /> location ^~ /conf/ { internal; }<br /> &#035; Taking advantage of browser caching for static stuff<br /> location ~&#042; &#92;.(js|css|png|jpg|jpeg|gif|ico|eot|woff|ttf|svg)$ {<br /> expires max;<br /> log_not_found off;<br /> }<br /> &#035; Change some undesirable behavior &amp; force things to display things like a traditional forum<br /> location = /discussions {<br /> rewrite ^ $scheme:// permanent;<br /> }<br /> location = /discussions/ {<br /> rewrite ^ $scheme:// permanent;<br /> }<br /> location = /categories/discussions {<br /> rewrite ^ $scheme:// permanent;<br /> }<br /> location = /categories/discussions/ {<br /> rewrite ^ $scheme:// permanent;<br /> }<br /> location /vanilla/discussions {<br /> rewrite ^ $scheme:// permanent;<br /> }<br /> location /vanilla/discussions/ {<br /> rewrite ^ $scheme:// permanent;<br /> }<br /> &#035; Plug-in specific rules<br /> &#035; Keep the WhosOnline plugin from flooding the logs<br /> location /plugin/imonline { access_log off; log_not_found off; }<br /> }

(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...)


  • 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 Themester ✭✭✭
  • 422422 Developer MVP

    Good work @leeh

    422 Real Estate Australia , now open Check it out

  • AoleeAolee Hobbyist & Coder ✭✭
  • aeryaery Gtricks Forum in 2.2 :) ✭✭✭

    Thanks for sharing mate :)

    Vanilla is sweet & support is great, to encourage volunteers, please donate.

  • 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 {<br /> server unix:/var/run/php5-fpm.soc;<br /> }

    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; }<br />

    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; }<br />

Sign In or Register to comment.