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

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.

AWS Lightsail is the closest thing AWS has to shared hosting. It is their quick, easy and inexpensive off-the-shelf hosting that has SSH access and many of the benefits of using a more expensive EC2 instance.

It is an affordable entry in cloud computing, but is it any good?

I decided to try out Amazon’s cheapest hosting offering by moving a WordPress blog from some shared hosting to Lightsail. I have tried EC2 in the past so this was not my first experience with AWS, but I was curious to see what their new more consumer-based hosting was like.

Creating an Instance

When you create an instance of Lightsail you chose how big or small you want it. You also chose whether you want just the OS, or you can have an app pre-installed with Bitnami (“App+OS“). The options for the app include a pre-installed WordPress blog, LAMP, MEAN, LEMP or several other applications. Alternatively, you can choose “OS Only” where you currently have the choice of either Windows or Linux flavors: Amazon Linux, Ubuntu, Debian, FreeBSD, openSUSE and CentOS.

I went with the PHP 7 LAMP stack option in the smallest size ($3.50 per month). I chose this option because I wanted to make sure WordPress was exactly the way I wanted it. And I wanted to see what the LAMP option was like.

In the price you also get a dedicated IP which makes setting up a breeze before pointing the domain name at the new instance, definitely a nice touch.

The LAMP 7 option came with PHP 7.1. But it’s possible to upgrade. All the elements of LAMP come pre-installed (Linux, Apache, MySQL and PHP) but you’ll want to configure them to your needs.

The main thing you can say about the setup is that it was lightening fast. Within seconds I had a fully operational instance. In the past, when setting up some hosting you might have assumed it would take at least a couple of days. Because the dedicated IP is plainly visible on the AWS console, you can immediately see the default index page in your browser.

First Look at Lightsail App+OS

The main difference between the “App+OS” option and a normal VPS is Bitnami. You notice right away is that the default username is “bitnami” and after logging into the Linux console you get a large “Bitnami” logo at the top of the screen.

So, what is this Bitnami?

Bitnami

Amazon AWS has so many quirks that you might assume that Bitnami is an AWS thing, as is their own Amazon Linux, but it is quite widely used in cloud computing (including Oracle Cloud and Google Cloud Platform).

With the “App+OS” Bitnami a lot of the things you normally have to do to set up a LAMP stack are already done for you. For example, Apache is pre-installed with most/all modules and even MySQL is pre-installed. However, to find your root login for MySQL you’ll need to look for it, see below.

With Bitnami other slightly unusual thing you notice upon logging into SSH or SFTP is the directory structure, the apache.conf does not look the same as normal, and where are the virtual host files?

Bitnami uses httpd-app.conf, httpd-prefix.conf and httpd-vhosts.conf files, as described here.

This is unusual and I imagine many people who do not want to use Bitnami would want to use the “OS Only” option. While it may take a little longer to set up, once that’s done you have a “normal” Bitnami-free Linux instance.

Transferring a Website to Lightsail

Having gone with the LAMP (PHP 7) option I basically followed my guide from here to move a WordPress blog over to different hosting. With minimal setup to do it was mainly a case of setting up the database, installing WordPress then using WP-CLI to install the plugins and theme.

As the instance was just going to be hosting one website I didn’t have to worry at all about the virtualhosts as everything was set up to just work from the off.

My first question was how do I login to MySQL. The login info for MySQL did not appear to be anywhere in the AWS console. To find the password for the root user you need the Bitnami Application password. From the home directory (where you arrive after logging in) just type…

$ cat bitnami_application_password

Transferring everything across, most things just worked. While PDO worked fine in normal PHP pages, I had to tweak the php.ini to get PDO to work from a script run with cron. For me, I just had to uncomment the .so file for PDO which was almost the last line of the php.ini.

After changing something like the php.ini you’ll have to restart. The following command seems to stop everything (apache/HTTPd, PHP and MySQL, ), then restart everything; perfect for making sure everything gets restarted all at once but not very graceful (from here)…

$ sudo /opt/bitnami/ctlscript.sh restart

To just restart apache you’d just add “apache” to the end…

$ sudo /opt/bitnami/ctlscript.sh restart apache

Linux

While some things are very different in Bitnami, it’s basically just a Linux instance. The Linux version I got with the LAMP (PHP 7) option was actually Ubuntu 16.04, so if you want the latest version of Ubuntu (18.04 is currently the latest LTS), or a different flavor of Linux, chose the “OS Only” option. I am most comfortable with Ubuntu/Debian and a lot of the standard CLI functions are exactly the same as Ubuntu.

Nano comes pre-installed and was the default editor for the crontab.

$ crontab -e

BTW, cron needs the full path to php, i.e. something like…

* * * * * /opt/bitnami/php/bin/php -f /opt/bitnami/apache2/htdocs/scripts/index.php "name_of_method()"

Then…

$ sudo service cron reload

The timezone is quite important because it can also affect your keyboard layout when typing into the Linux terminal. Changing the timezone is based on Ubuntu 16.04, so something like this would work to list the timezones, select a timezone then check which timezone you’re using…

$ timedatectl list-timezones   
$ sudo timedatectl set-timezone America/Vancouver  
$ timedatectl

Now, that the Linux timezone is set, you may also need to update the timezone PHP uses by updating this line in the php.ini…

date.timezone="Europe/London"

For all the PHP timezone variables, click on your region from the PHP timezones page.

Something else that is the same as Ubuntu is updating and upgrading…

$ sudo apt-get update
$ sudo apt-get upgrade

Once you get used to the quirks and the different directory structure with Bitnami, most things seem the same as a typical Ubuntu instance.

Issue(s) with AWS Lightsail

The first “upgrade” was a large one which took a while. It took so long in fact that either putty went inactive, or my computer went to sleep, or both. After this, the website went down and I had no access to SSH. What I seemed to have to do was not “reboot” the instance, but “stop” and “start” the instance from the AWS console. After this, I had a different public IP address but I was able to fix whatever had happened with the upgrade.

If the restart is the opposite of graceful, stopping and starting was similarly very ungraceful, comparable to doing the same thing with any VPS instance.

Apart from some minor changes that will probably be easy to get used to, I did not have many issues at all.

AWS Lightsail App+OS: Conclusion

Bitnami saved some time during setup, but honestly, any time I saved was probably offset by time spent figuring out what was going on with Bitnami.
I’m not 100% sure that the speed of setup of Bitnami is worth the changes it makes to the Linux operating system. For something like this example, a WordPress blog, that isn’t going to need a lot of administration, the “App+OS” option was fine though.

If you are a purist and don’t mind setting up the Linux instance with everything you need there is always the “OS Only” option which I don’t believe uses Bitnami. This would be better for a website where you’re going to want to make more changes to the Virtualhost file and/or possibly upgrade to an EC2 instance in future. If you are already a full stack LAMP developer you’ll probably be wanting to use that option for any actual development. App+OS seems to be mainly for people who do not want to get too involved with the “L” or “A” parts of LAMP.

AWS Lightsail with the App+OS option is perfect for someone who just wants to have a cheap WordPress blog running on AWS, as I did here. For a brand new blog, choosing the “WordPress” option would simplify the whole process even more.

I’d say App+OS might also be a good way to play around with something new such as MEAN before starting an actual project with it. Everything would be pre-installed so you could get straight into the javascript and the NoSQL.

So far so good. The instance seems fast for a WordPress blog, it certainly is compared to the previous shared hosting. And, very affordable.

The internet is gradually becoming more and more encrypted and secure. While this is most important for websites where you might enter sensitive data, like credit card info, it is generally a good thing to have for any website. Browsers now warn surfers if a website is not encrypted. As I write this unsecure, unencrypted websites just have an exclamation mark inside a circle in the location bar, but the trend is towards this warning getting more and more visible on the surfers browser.

As well as having quality content for surfers, you can also try to not turn surfers off your content by having an unencrypted website. Maybe secure websites will rank higher than unsecured ones.

Contents

Setting up a SSL Certificate to make a Secure Website

When trying to set up a free SSL certificate from Let’s Encrypt the information I found to begin with was quite confusing. Then, once I got my head around what I was doing, the sites I tried to add it to were not able to use Let’s Encrypt certificates for different reasons.

Once I finally got a VPS that could handle Let’s Encrypt certificates I followed this guide… Install Let’s Encrypt to Create SSL Certificates.

I would say that starting off it is important to pay attention to detail. Make sure everything is updated to begin with, and you have all the server requirements. Also, whereas you may not have specified the IP address in your virtual host config file before, you will need to specify the IP there for this to work.

Luckily, for a Linux administration beginner there are plenty of error logs and hints to find out what if anything has gone wrong. Not all the online guides state all the pitfalls. That’s why I am putting this information together in one place on how to make your website secure with SSL encryption…

Installing Let’s Encrypt

To begin with, make sure port 443 is open in the firewall (see troubleshooting). In these lines of code make sure to change “example.com” to your website domain.

Start off by getting and installing the Let’s Encrypt software, then use it to get the certificates. The order of the two domains in the final command are fairly important because the virtual directory containing the certificates will be named after the first domain, so you might want to use the one without www for simplicity…

sudo apt-get install git
sudo git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt

Installing Let’s Encrypt SSL Certificates

Go to the directory you have cloned to when installing Let’s Encrypt…

cd /opt/letsencrypt
sudo -H ./letsencrypt-auto certonly --apache -d example.com -d www.example.com

If there are any errors after the final command, it should tell you what the error is related to, but if it does not or it is unclear there are some ideas in the troubleshooting section.

Check the certificates by typing the following commands, below. The directory should be your domain instead of “example.com“, if it does not exist or is misspelt then you’ll have to get the certificates again as it will not work. When you get the certificates you should specify both www and non-www. Let’s Encrypt does not work for wildcards so every subdomain has to be specified. If it is a subdomain with a different config file then it will need a separate set of certificates…

sudo ls /etc/letsencrypt/live/example.com
sudo stat /etc/letsencrypt/live/example.com/fullchain.pem

Modify the VirtualHost file to look for SSL Certificates

Then, once you have the certificates. Modify the config file for the website, e.g. “/etc/apache2/sites-available/example.com.conf“. You can Keep the same file just change the port from 80 to 443 and the VirtualHost tags should contain the following. The file path to the certificates should be the actual paths to your certificates. And, I believe for this to work you must have the IP address in the VirtualHost tag, a wildcard will not work…

<VirtualHost 123.123.123.123:443>
SSLEngine On
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
</VirtualHost>

Then, make sure SSL is enabled and restart apache…

a2enmod ssl
service apache2 restart

By this stage when you go to https://www.example.com your website should work! If that’s the case you can make sure that everyone gets the secure version of your site, below.

Redirecting to Force HTTPS Encryption

Once the SSL certificates are working properly you’ll want to make sure everyone gets the secure version of your website. There are a few different methods to do this but perhaps the simplest for people who are new to Linux is using .htaccess. How to force HTTPS using the .htaccess file

RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://www.example.com/$1 [R,L]

This will still allow https://example.com/ to work so you may choose to add another line for that.

Or, have two VirtualHost tags for ports 80 and 443 in the “/etc/apache2/sites-available/example.com.conf” file and redirect port 80 as suggested here

<VirtualHost 123.123.123.123:80>
ServerName www.example.com
ServerAlias example.com
Redirect permanent / https://www.example.com/
</VirtualHost>

Now, you’ll all done!

Checking the Expiration Date of Let’s Encrypt Certificates

Let’s Encrypt certificates last for 90 days, you do not want them to expire unless you want to stop encrypting the website. To check when your current certificates are du to expire type this into the terminal…

openssl x509 -noout -dates -in /etc/letsencrypt/live/example.com/cert.pem

Which will give you the date they were created and the date they are valid until…

notBefore=May 7 14:33:00 2017 GMT
notAfter=Aug 5 14:33:00 2017 GMT

From here there is also “ssl-cert-check” for Debian-like versions of Linux. It needs installing first if it is not already installed, so…

apt-get install ssl-cert-check

Then, run it by typing this simple code (needs superuser privileges so use “sudo”)…

ssl-cert-check -c /etc/letsencrypt/live/example.com/cert.pem

Which gives something like this…

Host                                             Status   Expires     Days
---------------------------------------------------------------------------
FILE:/etc/letsencrypt/live/example.com/cert.pem   Valid   Aug 5 2017   90

Renewing Let’s Encrypt SSL Certificates

To renew the Let’s Encrypt certificates, navigate to the Let’s Encrypt directory… cd /opt/letsencrypt.

Then, this is one way to renew the certificates…

sudo service apache2 stop
sudo -H ./letsencrypt-auto certonly --standalone --renew-by-default -d example.com -d www.example.com
sudo service apache2 restart

The “standalone” flag means that you would have to stop apache because Let’s Encrypt needs to be the only application using port 443.

However, by using --apache or --webroot you can do the same thing while apache is running, from here. This may reload or restart apache but apache would not be stopped for nearly as long as it would be if apache was manually stopped and then restarted again at the end…

sudo -H ./letsencrypt-auto certonly --apache --renew-by-default -d example.com -d www.example.com

To automatically renew the Let’s Encrypt certificates one a month, enter this command to make a monthly task in your crontab…

echo '@monthly root /opt/letsencrypt/letsencrypt-auto certonly --quiet --apache --renew-by-default -d example.com -d www.example.com >> /var/log/letsencrypt/letsencrypt-auto-update.log' | sudo tee --append /etc/crontab

To automatically renew the Let’s Encrypt software, enter this command…

echo '@monthly root cd /opt/letsencrypt && git pull >> /var/log/letsencrypt/letsencrypt-auto-update.log' | sudo tee --append /etc/crontab

Alternative Method for Debian 8 (Certbot)

Another way is to install the Let’s Encrypt certificates is to install Certbot on Debian 8 using Backports… How to Set Up Let’s Encrypt Certificates for Multiple Apache Virtual Hosts on Ubuntu 14.04.

sudo nano /etc/apt/sources.list

Then, enter this line if it is not already there…

deb http://ftp.debian.org/debian jessie-backports main

Save and exit nano, then…

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install python-certbot-apache -t jessie-backports

Troubleshooting and Checking

Check which sockets are open using ss (socket statistics)…

ss -tlnp

More information on ss here.

Check apache version and check which modules are installed

apache2 -v
apache2ctl -M

or

dpkg-query -l

For your second secure website on the same webserver you will have already enabled the SSL module and port 443 will already be serving your first website to the world. When you try to install the certificate for the second website there may be problems if you are using the --standalone flag, because Let’s Encrypt wants to use the same port as is already serving the website. To continue using --standalone you can stop Apache for a few seconds while you install the certificates.

service apache2 stop

Then, once the Let’s Encrypt certificates are done, you can restart Apache again…

service apache2 restart

To avoid having to stop and start apache like this on a production website you can use the --apache flag instead.

If you are using UFW as a firewall, the following command will show you whether socket 443 is allowed…

sudo ufw status

Also, Apache problems when trying to set up SSL (Debian).

Further Checks to make your Website Secure (Green Padlock)

If your website is working with HTTPS in the location bar (“https://www.example.com/”) but you do not have a green “SECURE” you have an “i” with a circle around it, check to see what it says by clicking on it. If it says you are not fully secure it probably means that the files and/or images you are linking to are not using the SSL encrytion. To fix this simply either fix your absolute image/file locations by changing them from HTTP to HTTPS, or just use relative linking.

Another thing that may cause errors is your .htaccess file, if you have one. Make sure that the error documents are all updated from http:// to https:// for the site in qustion.

Adding more Secure websites to the same Webserver

When “Let’s Encrypt” is already installed you do not have to re-install it, you can simply create the new certificates for the next website you want to make secure. When you are trying to create the certificates there may be an error saying that port 443 is already in use. In this case, you may have to stop apache briefly while you make the certificates, then restart apache as soon as they’re made.