Gbenga Oni
Published on

Deploying and Scaling a Laravel App on AWS

Authors

Learn Hand-On AWS Cloud EngineeringHERE

Laravel App on AWS

Introduction

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 to use and familiarize yourself with some of the AWS platforms, 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.

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.

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.

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

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

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.

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.

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 3306 to our MySQL database.

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

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.

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.

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.

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`
Alias / /var/www/html/laravel/public/
<Directory "/var/www/html/laravel/public">
        AllowOverride All
        Order allow,deny
        allow from all
</Directory>

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.

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

APP_NAME=Laravel
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost

LOG_CHANNEL=stack

DB_CONNECTION=mysql
DB_HOST=<RDS ENDPOINT>
DB_PORT=3306
DB_DATABASE=laravelaws
DB_USERNAME=laravelaws
DB_PASSWORD=laravelaws

BROADCAST_DRIVER=log
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
SESSION_DRIVER=database
SESSION_LIFETIME=120

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):

yum install wget -y
wget https://getcomposer.org/composer.phar

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:

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. Furthermore, 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 to handle high user traffic while maintaining availability:

Deploying and Scaling a Laravel Web App on AWS - Part 2

Also, if you are looking to deploy your dockerized Laravel application to Amazon Elastic Container Service, here’s an article that demonstrates that:

Deploy a Docker-ized Laravel Application to AWS ECS with CodeBuild

Also if you are looking to deploy your Laravel Application on Kubernetes, here’s how:

Deploy a Laravel App to Amazon EKS in 5 minutes