Shortdark Software Development

Apache to Nginx

Development27th Jan 2019.Time to read: 8 mins

AWSAWS LightsailLEMPMariaDBNginxPHPUbuntu

I had a PHP website that was the last man standing on some shared hosting that was slow that didn't have SSH access. I decided that since I would be moving the website anyway, why not try something different with it. The website in question is PHP/PDO/MySQL with no framework.

Having already tried AWS Lightsail App+OS, I wanted to experiment with the Lightsail "OS Only" option. What better thing to do than to install the Nginx** web server** on it? Starting from scratch with an OS Only box I would be able to take a look at another side of AWS Lightsail (without Bitnami) and also learn about Nginx and using a LEMP stack.

I created a new instance of Lightsail with Ubuntu 18.04 LTS. It was exactly the same as most VPS that only come with Linux installed. After installing Nginx on Lightsail, the version of PHP I got from by installing PHP-FPM was PHP 7.2.10.

Link... https://www.digitalocean.com/community/tutorials/how-to-migrate-from-an-apache-web-server-to-nginx-on-an-ubuntu-vps

But, we've jumped ahead. Let's look at Linux...

First Things First: Linux

The first thing to do is to update and upgrade Linux. Sudo was already installed, so it's straight into...

sudo apt-get update
sudo apt-get upgrade 

I believe that while Debian is a pretty bare bones install, Ubuntu comes with a lot of stuff pre-installed such as sudo and nano, which is very convenient.

Nginx

With Linux updated, we can get the next part of the LEMP stack installed. That would be Nginx (Engine-X). This is the only part of the stack that I've not had much experience of in the past so was most interesting for me. I was expecting it to be slightly more different to Apache than it was. Apart from the different style of the config file...

sudo apt-get install nginx

Now, magically the unique domain you have in your Lightsail console will work in your browser, giving you a page like...

Welcome to nginx!

If you see this page, the nginx web server is successfully installed and working. Further configuration is required.

For online documentation and support please refer to nginx.org.

Commercial support is available at nginx.com.

Thank you for using nginx.

Doing some prep for when we change the DNS and point the domain name at this hosting, we should also make a config file...

The Nginx Config File

The config file should be the name of the site and should be created in /etc/nginx/sites-available. Copy the info from the default file across to the new site, changing the domain name. You can then set up a symlink to "sites-enabled"...

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/

https://www.digitalocean.com/community/tutorials/how-to-install-linux-nginx-mysql-php-lemp-stack-ubuntu-18-04

sudo unlink /etc/nginx/sites-enabled/default

Test the new Nginx config, then restart to load the new settings with...

sudo nginx -t
sudo systemctl reload nginx

Change permissions of the /var/www/htdocs/ folder then upload files. Convert htaccess...

https://winginx.com/en/htaccess

Something like this will eventually need the * removing for nginx...

<Files *.inc>
    Deny From All
</Files>

becomes...

location ~ .inc {
    deny all;     
} 

# I also had to convert the "break" to "last" on the mod_rewrite...

rewrite ^/(.*)/$ /item.php?item=$1 last;

Then, add the code to the example.com config file and test it again. Any duplicates will need commenting out with #. In the config file .php causes an error, remove the slash.

PHP

Now, we can install PHP and MySQL to complete our LEMP stack...

sudo apt install php-fpm php-mysql 

Luckily, the site I was moving had pretty modern PHP with nothing that needed fixing at all. Uploaded a file with the function phpinfo() on it to test that PHP is working. All good!

Nginx Default Log File

index.php not working! Look at the log file...

tail /var/log/nginx/error.log

Yes, the PHP was fine, it turns out that PDO was unhappy that I hadn't added the database yet...

MariaDB

Finish off getting MariaDB installed, then check it's working...

sudo apt install mariadb-client-core-10.1
sudo apt install mariadb-server
sudo systemctl status mariadb 

I was getting the error, below...

ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2 "No such file or directory")

So, I did a "locate" for the my.cnf file and the "mysqld.sock" file and added this to the mysql/mariadb config file, my.cnf...

socket  = /var/run/mysqld/mysqld.sock

Then...

sudo service mysql restart

Login for the first time with sudo...

sudo mariadb -uroot

Now you can create the database and database user for the app.

https://stackoverflow.com/questions/5376427/cant-connect-to-local-mysql-server-through-socket-var-mysql-mysql-sock-38

SSL Encryption

Pointed domain name at the public IP address with CloudFlare. Server-side SSL encryption to follow.

https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-18-04

Simple Password Authentication

https://www.tecmint.com/password-protect-web-directories-in-nginx/







sudo apt install apache2-utils
sudo htpasswd -c /etc/nginx/.htpasswd username 

Then put the following in the "location" you waant to be protected in the config file...

auth_basic "Administrator Login";
auth_basic_user_file /etc/nginx/.htpasswd;

Then, test and restart NginX.

Force or Remove WWW

For some sites I prefer to keep the www in, so I did the opposite of this on this occasion...

server {
    server_name www.example.com;
    return 301 $scheme://example.com$request_uri;
}
server {
    server_name example.com;
    # […]
}

https://stackoverflow.com/questions/11323735/nginx-remove-www-and-respond-to-both

index.php Downloads instead of Displaying

Sometimes the index.php, or ay PHP files can start downloading instead of displaying normally in the browser. The fix for this is to pass the PHP scripts to the FastCGI server. Make sure you use the correct filepath, below is for PHP 7.2 but it will be different for different versions of PHP...

server {
listen 80;
listen [::]:80;
root /var/www/myApp;
index index.php index.html index.htm;
location ~ \.php$ {
   try_files $uri =404;
   fastcgi_split_path_info ^(.+\.php)(/.+)$;
   fastcgi_pass unix:/run/php/php7.2-fpm.sock;
   fastcgi_index index.php;
   fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
       include fastcgi_params;
   }
}

Debug Mode

To show extra info in the error.log file add the word "debug" to the error_log statement...

error_log  /etc/nginx/error.log debug;

Example nginx.conf file

This file is taken from here. Shows SSL encryption...

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://example.com$request_uri;
}
server {
     listen 443 ssl;
     listen [::]:443 ssl;
     server_name example.com wwww.example.com;
     ssl on;
     ssl_certificate /root/certs/APPNAME/APPNAME_nl.chained.crt;
     ssl_certificate_key /root/certs/APPNAME/ssl.key;
     ssl_session_timeout 1d;
     ssl_session_cache shared:SSL:20m;
     ssl_session_tickets off;
     ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
     ssl_prefer_server_ciphers on;
     ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK'; 
     ssl_stapling on; 
     ssl_stapling_verify on;
     ssl_trusted_certificate /root/certs/APPNAME/APPNAME_nl.chained.crt;
     root   /srv/users/serverpilot/apps/APPNAME/public;
     access_log  /srv/users/serverpilot/log/APPNAME/APPNAME_nginx.access.log  main;
     error_log  /srv/users/serverpilot/log/APPNAME/APPNAME_nginx.error.log;
     proxy_set_header    Host              $host;
     proxy_set_header    X-Real-IP         $remote_addr;
     proxy_set_header    X-Forwarded-For   $proxy_add_x_forwarded_for;
     proxy_set_header    X-Forwarded-SSL on;
     proxy_set_header    X-Forwarded-Proto $scheme;
     include /etc/nginx-sp/vhosts.d/APPNAME.d/.nonssl_conf; include /etc/nginx-sp/vhosts.d/APPNAME.d/.conf;
}

Conclusion

Website moved and working as it did before, but possibly slightly faster.

In just the short time I have been using it Nginx is already growing on me. I like the simplicity. I like that it is quite similar to Apache in some ways. And, I like the fact that it should be faster than Apache.

Not being able to use .htaccess files, and the Nginx config being different to Apache virtualhost files was not bad at all. A combination of using a htaccess-to-Nginx converter and Google/Stackoverflow has already taught me a lot of how to replicate what I might do with an .htaccess or virtualhost file with Nginx.

As expected, the "OS Only" version of AWS Lightsail was much more like a standard VPS and there was nothing too hard in setting it up and moving a site across and onto Nginx.


Previous: Trying AWS LightsailNext: Interacting with S3 using PHP