Japanatron Logo

What follows is an outline I compiled while building an Ubuntu server for running the Joomla CMS on the Nginx web server.
NOTE: Ubuntu 14.04 LTS was used for this.

Ubuntu Server
* choose SSH server during the install
* setup static IP address

Install Packages
* nginx (or nginx-naxsi that conveniently includes the Naxsi firewall)
* mysql-server
* php5
* php5-curl
* php5-fpm
* php5-gd
* php5-mcrypt
* php5-mysql
* php5-xmlrpc
* nano
* unzip
* zip
* wget
* phpmyadmin
* webmin
* libav-tools (I install this for avconv, a utility used to convert video files.)

Create DNS Entries / Zones (if necessary)

PHP Configuration
NOTE: Nginx uses PHP as FastCGI, so configuration is found in /etc/php5/fpm/php.ini
* set expose_php to OFF (security measure)
* set cgi.fix_pathinfo to 0 (security measure recommended by Nginx documentation)
* set output_buffering OFF (recommended by Joomla installer)

PHPMyAdmin
* Don't configure it for Apache during the install :-)
* Create a virtual host on a custom port pointing to /usr/share/phpmyadmin  I used almost the same virtual host config as the Joomla one.
* Check that no Apache packages accidentally got installed.  You can remove them (apt-get purge).
* Enable the php5-mcrypt module:
php5enmod mcrypt
service php5-fpm restart

Webmin
* Download and install Nginx Webmin module--search Webmin's 3rd party modules: http://www.webmin.com/third.html

Nginx - General
* Nginx complained about some default setting upon start, but I quickly found the mentioned setting commented-out in nginx.conf.  Enabling the setting fixed the issue.

Nginx - Virtual Hosts
As for the virtual hosts, I started with the virtual host configuration from Joomla's documentation: http://docs.joomla.org/nginx

This was an excellent start, but 2 things needed tweaking:
1. The log type "main" is undefined, and "info" is a bit more than I need.  So I went with this:

access_log /var/log/nginx/localhost.access_log;
error_log /var/log/nginx/localhost.error_log notice;


Alternatively, you can choose not to define the logging level/type and it will just use the defaults, as I did for the access log setting above.

2. Php-fpm's defaults seem to favor a Unix socket (which I've read is a better approach), so I modified the PHP processing section to look like the below.  Aside from the TRY_FILES line, this mirrors Nginx's default site configuration example.

location ~ \.php$ {
       try_files $uri =404;
       fastcgi_split_path_info ^(.+\.php)(/.+)$;
       fastcgi_pass unix:/var/run/php5-fpm.sock;
       fastcgi_index index.php;
       include fastcgi_params;
       }

NOTES
This section was a challenge because the Joomla docs, Nginx's own default virtual host configuration, and Nginx's wiki site presented slightly modified versions of the above:
* The Joomla docs version doesn't have a split path info line.
* The Joomla docs version adds a fastcgi parameter line.
* The Nginx wiki tutorial recommended an IF statement over TRY_FILES; however, this caused PHP security errors (access denied) to appear in the logs on legitimate traffic.  Here's the link: http://wiki.nginx.org/PHPFcgiExample

I settled on the above, combined with setting cgi.fix_pathinfo to 0 in php.ini (as mentioned earlier).  I ensured only PHP files are sent to the PHP processor using this simple test:
1. Open http://yoursite.com/robots.txt. Your robots.txt file appears.
2. Open http://yoursite.com/robots.txt/nonexistent-file.php.  You should get an error (like 404).  You have a serious security issue if your robots.txt file appears.

Nginx - X-Forwarded-For
* I defined a custom logging format in nginx.conf to log the x-forwarded-for IP, which is great for servers behind a reverse proxy.  You can also achieve this using Nginx's real_ip module, but I just went with this for the time being.  This only shows the x-forwarded-for in the logs.

log_format revproxy '$http_x_forwarded_for - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent "$http_referer" ' '"$http_user_agent"' ;

After a bit of research, I realized that using the real_ip module is easier than I thought because the latest Nginx binary package (in the Ubuntu 14.04 repositories) already includes it.  I simply added something like this to the virtual host's server section:

# X-Forwarded-For
        set_real_ip_from X.X.X.X/32;
        real_ip_header    X-Forwarded-For;


Then I turned off the custom logging format and restarted Nginx.  The logs still showed the real IP.  Nice!  The advantage of the real_ip module is that things like PHP applications see the real IP as well, not just the logs.

Joomla
* set file / folder permissions
* set owner and group to www-data
* set Joomla email settings - I use my ISP's SMTP server to save me from having to run mail services on the web-server
* verify the file / folder permissions using a tool like Akeeba Admin Tools or RSFirewall

Some Joomla extensions caused PHP to throw "strict" errors, and unfortunately several of these errors would appear on my site.  Even more unfortunately, suppressing the errors in both Joomla's and PHP's logging settings had no effect.

Here's what I ended up doing:
1. Suppress the errors in the Joomla template.  This didn't fix the errors, which is why step #2 is preferred; however, it did stop them from appearing on my site.  In other words, it bought me some time to complete the next step.  I added these lines to the top of the template's default.php file, after <?php.

error_reporting(0);
ini_set('error_reporting', E_ALL & ~E_NOTICE & ~E_WARNING & ~E_STRICT & ~E_DEPRECATED);
ini_set('display_errors','Off');


2. Search the Nginx error log and find the extensions causing the errors.  Update the problem extensions, replace them with alternatives, or fix the code.  Usually it's just a minor syntax issue.  The error log revealed the problem php file and line number, and a quick Internet search told me how to fix it.

Please see this helpful post for more info: http://www.gavick.com/documentation/general-questions/how-to-fix-strict-standards-non-static-method/

JomSocial
* setup JomSocial cron job: wget -O /dev/null "http://www.domain.com/index.php?option=com_community&task=cron" > /dev/null
* php.ini tweaks as suggested in JomSocial documentation:

- max_execution_time = 9000 ; Maximum execution time of each script, in seconds
- max_input_time = 9000 ; Maximum amount of time each script may spend parsing request data
- memory_limit = 1024M ; Maximum amount of memory a script may consume
- post_max_size = 4096M ; Maximum size of POST data that PHP will accept.
- upload_max_filesize = 4096M ; Maximum allowed size for uploaded files.

Related Articles

Ubuntu 22.04 Nginx Build Outli...

I re-built my LEMP web-server fresh on Ubuntu 22.04 and learned some things along the way. This is my base build outline mostly created for my own notes. INS...

How to Spot an iPhone Unlock S...

While Apple technically calls it "iPhone IMEI database whitelisting," it's better known around the web as a factory unlock--a process that allows your iPhone to...

Adding iTunes to Joomla Stalke...

The Joomla extension Stalker is awesome, but oddly enough it doesn't have iTunes as one of the default available networks.  If you're using the component, you c...

How to Look at Internet Porn

In the course of my IT career, I can't tell you how many times some guy has brought a computer to me saying, "I dunno what happened.  It seems to have a ...