Deploying and Scaling a Laravel Web App on AWS — Part 1

Deploy Laravel on AWS

In this article, we will deploy a Laravel web application on Amazon Web Services and we will scale it across several instances. These instances will share a single MySQL database that will be deployed on the Amazon Relational Database Service(RDS).

We will also simulate failures of random instances to assess the behavior of the system in the event of a real-world problem that may impede the availability of our Laravel web application. The system will be fault-tolerant and designed to fail with grace, performing regular health-checks on instances and spinning up new, healthier ones to replace failed ones.


Amazon EC2

Amazon Elastic Cloud Compute is a web service that provides resizable compute capacity in the cloud. Think of it as a personal computer, but in the cloud. With complete control of computing capacity, Amazon EC2 takes web-scale cloud computing to the next level for developers.

To get the ball rolling, you will need to create an AWS account, if you don’t already have one. The Free-Tier account will enable you use and familiarize yourself with some of AWS platform, products and services.

Once you have done that, head on to the EC2 dashboard.

Launching the instance

To launch an instance, click on the Launch Instance button. You will be taken to a launch instance wizard page that contains a list of Amazon Machine Image(AMI)s which provides important information required to launch an instance. You have to specify a source AMI when launching an instance.

Select the Amazon Linux AMI 2018.03.0 (HVM), SSD Volume Type which comes with preconfigured installations of PHP, Python, MySQL, Docker and other essential packages to get you up and running as soon as possible.

Create an Ec2 instance

You will be taken to the next page where you will choose an instance type. Choose the t2.micro instance type which is Free-Tier compatible. The t2.micro instance type doesn’t provide the best nor most optimized compute capacity but will suffice for the purpose of this tutorial.

Skip through the 3rd, 4th and 5th steps without changing any of the default parameters as that’s outside of the scope of this tutorial. Head to the 6th step where we will configure a Security Group. Think of a Security Group as an imaginary firewall around an instance, filtering traffic into and out it.

Click on the Add Rule button and select HTTP, click on it again and select HTTPS. These will allow HTTP/HTTPS traffic in and out of the instance, making it accessible over the internet. The first rule, the SSH directive, will enable us SSH into the instance and make necessary updates, configurations, and installation.

AWS Ec2 Security Group

Once that’s done, click on the Review and Launch button.

Now Launch the instance. You will be prompted to select or create a new key pair. Select “Create a new key pair” and name it myNVirginiaKeyPair. Once this is done, download the key pair(make sure you do). Will will be using the downloaded key pair to SSH into our instance shortly.

AWS Ec2 Key Pair

Click on Launch Instances and wait for the instance to launch then click the View Instances button on the bottom right.

Amazon Ec2 instance

Launching our Amazon RDS Database

Amazon RDS is a relational database service in AWS that enables you to launch fully-managed, relational databases such as MySQL, Oracle, Amazon Aurora (High performance and available MySQL), PostgreSQL, MariaDB and Microsoft SQL Server.

We will create a MySQL database in RDS before installing Laravel on our EC2 instance. This will give us the needed database endpoints to configure the Laravel web app with.

Navigate to the RDS Page and click on the Create Database button

Create an Amazon RDS database

Select the MySQL engine and click Next. Select the Dev/Test use case which keeps us within the RDS Free Usage Tier.

The next section is where we will specify the Database details. Select the t2.micro DB instance type, then scroll down to the Settings row at the bottom.

Amazon RDS settings

Set the DB instance identifier, the Master username, the Master Password and the Confirm Password to laravelaws. You can use any value within the defined constraints but we will stick to laravelaws for the sake of simplicity.

Click on the Next button and you will be taken to the 4th section where we will configure advanced settings.

Amazon RDS Database options

Scroll down to the Database options row where we will set the Database name to laravelaws also. Leave every other parameter as is and click the Create database button at the bottom. Now RDS will begin the instantiation of our MySQL database. This may take a few minutes. We will come back to get the generated endpoint with which we will connect the Laravel Web App to our MySQL database, through the internet.

Remember: Amazon RDS is a fully-managed service, thus SSH access to our MySQL database is prohibited. Amazon RDS takes care of OS patching, upgrading, automated backups and other database administrative processes for you.

The last thing we need to do is create a Security Group that will allow traffic through port 3360 to our MySQL database.

Navigate to Security Groups under Network & Security on the EC2 dashboard and click the Create Security Group button

Create AWS Security Group

We will name the Security Group RDS-SG. Then add a MYSQL/Aurora rule that opens port 3306 access. Select Anywhere as source, then click Create.

Once this is done, head back to the Amazon RDS dashboard, select the laravelaws database and click on Modify button.

On the third row — Network & Security — click on Security Group, then add the newly created RDS-SG security group. Click Continue and then Modify DB Instance.

Amazon RDS Security Group

We can now connect to our MySQL DB instance via port 3306 with our endpoint and other DB credentials.

Connecting to the EC2 Instance via SSH

Now that the instance is started and running, we need to grab the public IP address of the instance to enable us establish an ssh connection to it, together with the key pair we downloaded earlier.

Note: If you are using a windows PC follow this guide on Connecting to Your Linux Instance from Windows Using PuTTY.
Amazon Ec2 Public IP

Grad the Public IP address and navigate to the downloads folder the key pair is located. Now run the command:

ssh ec2-user@<your public IP> -i myNVirginiaKeyPair.pem

Make sure you are running this command in the folder that contains the myNVirginiaKeyPair.pem we downloaded earlier.

If all goes well, you should be prompted with the question Are you sure you want to continue connecting (yes/no)? , type yes and hit enter.

If you get any unprotected private key file warning, run the command

chmod 400 myNVirginiaKeyPair.pem

this will protect the myNVirginiaKeyPair.pem file against accidental overwriting. Now attempt the ssh connection again.

Yaay!! we have successfully established ssh connection with our EC2 instance. We can now install needed packages via the console.

Installing Apache

Lets assume the role of a root user then upgrade system software to the latest version.

sudo su
yum update -y

Lets install Apache 2.2 and PHP 7.2 and a new version of mod_ssl

yum install httpd24 -y
yum install php72 php72-mysqlnd php72-imap php72-pecl-memcache php72-pecl-apcu php72-gd php72-mbstring -y
yum install mod24_ssl -y

Now let’s start Apache: run the command

service httpd start

You should get an OK response.

Go to your browser of choice and paste the Public IP address of the EC2 instance. You should see a test page like below.

Amazon Linux Apache Test Page

Now that Apache server is running, we can proceed to install our Laravel Web App, but first, we need to make sure that in the event our instance is restarted, for whatever reason, that Apache will be automatically started as soon as the instance comes on. That way we wouldn’t have to ssh into the instance then starting it on the console each time. We will do this by running:

chkconfig —add httpd
chkconfig httpd on

Installing Laravel

We will install Laravel from its official Github repository. But first we need to install git on our instance.

yum install git -y

Navigate to the Apache public folder:

cd /var/www/html

We will now clone Laravel from the git repository:

git clone https://github.com/laravel/laravel.git

Now that we’ve cloned a fresh Laravel project, we need to reconfigure our Apache server to point to the Laravel directory. we will do this by copying the code below to the bottom of the /etc/httpd/conf/httpd.conf file:

nano /etc/httpd/conf/httpd.conf

Edit the .htaccess file:

nano /var/www/html/laravel/public/.htaccess

Then add RewriteBase / just below RewriteEngine On


We will create a .env file and specify the MySQL database endpoint generated by RDS earlier and other credentials.

Navigate to the RDS dashboard on the AWS console and click on the laravelaws DB instance. Scroll down to Connectivity to see the Endpoint generated for the MySQL database.

NB: For those that may want to connect to the endpoint displayed below, this DB instance will be delete immediately after this tutorial.
Amazon RDS endpoint

Run the command(This copies the content of the .env.example file into a new file called .env):

cd /var/www/html/laravel
mv .env.example .env

nano .env

Paste in the code below. Make sure you substitute the DB_HOST parameter value for your generated MySQL endpoint(No http(s)://. Paste as is).

Laravel .env file

Once done, press ^X, then enter y to the prompted question and hit enter.

Now we need to give Apache write access to the storage folder, else Laravel will throw a write permission error.

sudo chmod -R 777 /var/www/html/laravel/storage

Let’s restart Apache to ensure immediate effect, and then return to the laravel folder:

service httpd restart
cd /var/www/html/laravel

To install composer(make sure you’re in the laravel directory):

Confirm installation by running:

php composer.phar

Now that we have composer installed, we will now install all needed Laravel packages specified in the composer.json file:

php composer.phar install

Generate Application key:

php artisan key:generate

Create Authentication scaffold:

php artisan make:auth

User session will be stored on the database instead of the file on the Ec2 instance. This is because, when we eventually scale our Laravel Web App, the Load Balancer will balance traffic request across all instances. So if my session file was stored on instance 1 and my next request is directed to instance 5, instance 5 will not have access to my session file on instance 1, thus it will ask that i re-authenticate myself. To avoid this, we will manage user sessions on the database, since all instances are connected and have access to it. Alternatively, we can make use of Amazon Elastic Cache that offers fully managed Redis and Memcache.

Create a sessions table migration:

php artisan session:table

Now let’s run Laravel migrations:

php artisan migrate

Paste the Public IP of your instance in your browser. You should see the Laravel welcome screen:

Laravel welcome screen

We have now successfully installed and configured Laravel on our Amazon Ec2 instance. We have also linked it to our MySQL database. You can make login and registration attempts to test the app.

Conclusion

In this article, we launched an EC2 instance and installed several packages and an Apache server on it, through an established SSH connection. Further more, we created a MySQL database instance on Amazon RDS and also installed a fresh Laravel application on the EC2 instance. This web application was eventually assessable on the web browser.

Here is the concluding part of this article, where we proceed to scale our Laravel Web application to enable it handle high user traffic while maintaining availability:

As always, comments, questions and feedbacks are welcome.

Did you find this tutorial useful ? Then hit that clap button and follow me to get more articles and tutorial on your feed.