Deploying and Scaling a Laravel App on AWS
Author: Gbenga Oni
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 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.
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
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
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
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:
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
Alias / /var/www/html/laravel/public/ <Directory "/var/www/html/laravel/public"> AllowOverride All Order allow,deny allow from all </Directory>
RewriteBase / just below
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
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
service httpd restart cd /var/www/html/laravel
To install composer(make sure you’re in the
yum install wget -y wget https://getcomposer.org/composer.phar
Confirm installation by running:
Now that we have
composer installed, we will now install all needed Laravel packages specified in the
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 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.
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© Gbenga Oni.RSS