How to Deploy a Laravel App on AWS EC2 Ubuntu?

My Personal Experience

Ravi Taxali
11 min readApr 3, 2023

I began learning Laravel in 2022 and developed an application using Laravel 9, Vue 2.6, and Vuetify after gaining some experience. Afterward, I opted to host the application on a server and stumbled upon AWS Free Tier Account, which provides many AWS services free of charge for a year. Upon creating my AWS Free Tier account, I gained experience in the three most widely used AWS services, namely EC2 (Elastic Compute Cloud), RDS (Relational Database Service), and S3 (Simple Storage Service). To run my application on AWS, I acquired a domain from GoDaddy.

Now started the most difficult part — deploying my application on AWS EC2. Despite reading numerous articles and watching countless YouTube videos, the experience proved to be frustrating. Nonetheless, after a few days, my application started running on AWS EC2.

In early March 2023, I decided to upgrade my application from Laravel 9 to Laravel 10. Although the upgrade process worked flawlessly on my local machine, I encountered issues when attempting to replicate it on AWS. Unfortunately, my limited knowledge of Linux and servers prevented me from resolving the bug that caused the server to fail to start. Therefore, my sole alternative was to deploy the application on a new EC2 server, which required me to search the internet for instructions. However, the guidance available was not as comprehensive or clear as before. Nonetheless, during this attempt, I maintained a record of both successful and unsuccessful steps. Subsequently, I am sharing the measures that worked for me, with the expectation that they may be of assistance to you.

Note: I assume that you have basic knowledge of AWS and Linux commands.

Launch a New EC2 Instance

  • Login to your AWS account as the root user, go to the EC2 Dashboard and click the Launch Instance button. You may also find this button on the Instances and Instances (running) page. On clicking Launch Instance, you would see a page similar to the following:
  • Enter a name, e.g. My Ubuntu 2023 Server for your server in the Name text box.
  • AWS provides various types of Amazon Machine Image (AMI) to choose from. Choose Ubuntu. If you are using the Free Tier account, ensure that the selected AMI is free tier eligible.

Create or Select a Key Pair

You need to create (or select if you already have one) key pair that you will need to connect to the EC2 server you are creating from your local machine. (A key pair, which consists of a public key and a private key, is a set of security credentials that you use to prove your identity when connecting to an EC2 instance.)

  • Scroll to the Key Pair section.
  • If you already have a key pair that you want to use with this EC2 instance, select it, otherwise click the Create new key pair link.

Creating a New Key Pair

On clicking the Create new key pair link, you would get a dialog box as show below:

  • Enter a suitable name, e.g. ubuntu2023, ubuntu_laravel, etc. in the Key Pair Name box and click the Create key pair button.

AWS creates a key pair file with extension .pem and automatically downloads it to your computer in the default download location. Save this file in a folder as you would not be able to download this file again. A common folder to store the .pem files is .ssh.

Network Settings

In the Network Settings section, you define rules for the inbound and outbound internet traffic. You also control SSH access to the EC2 instance in this section.

  • If you have saved security group settings, you may choose a saved settings.
  • To create a new security group, click Create Security Group and check the appropriate options. (If you are not sure, select all options; you can update these settings later.)
  • If you need to adjust other settings, e.g. Storage or Advanced Details, you may do so and then click the Launch Instance to launch the new EC2 instance you have just configured.

AWS would launch the EC2 instance and in few minutes, you would find that it is up and running, which you can confirm by clicking the Instances (running) or Instances on the EC Dashboard.

Connecting to the EC2 Instances

Before you can do anything on your EC2 instance, you need to connect to it, for which you will need the key pair (.pem) file you created and downloaded earlier.

  • Click the Instances (running) on the EC Dashboard and select your EC2 Instance name.
  • Click the Connect button in the top row, and it displays instructions to connect to the EC2 instance.
Instruction to connect to an EC2 instance

You may use any SSH client (e.g. Terminal on Mac or PuTTY) to connect to the EC2 instance. If you are using Terminal, change the current folder to the one where you saved the .pem file and use the command shown under ‘Example’, e.g. ssh -i "silkweb-ubuntu.pem@ec2-3-131-246.us-east-2.compute.amazonaws.com

Note: If you use a .pem file for the first time, it may display a “Unprotected Private Key File!” warning. In that case, use the chmod command to change the file permissions, as mentioned in “Instruction to connect to an EC2 instance” image.

Install Nginx Web Server

Next, let us install the Nginx web server. (I am not using the Apache web server for any particular reason.) Use the following commands to update software packages for Ubuntu.

sudo apt update
sudo apt upgrade

After you upgrade the software packages, you might see the following or similar message.

In that case, use sudo reboot to reboot the system, wait for a minute (for the system to reboot) and then connect it to your EC2 instance, as explained in the previous section.

Next, use the following command to install nginx.

sudo apt install nginx

Install PHP

Laravel 10 requires PHP 8.1 or higher, however, before installing PHP, execute the following command to a install a few prerequisites and Ondrej PHP repository.

sudo apt install ca-certificates apt-transport-https software-properties-common
sudo add-apt-repository ppa:ondrej/php

Note: Ignore any warnings that the command may display.

Next, use the following commands to update the installed packages and install PHP.

sudo apt update
sudo apt upgrade
sudo apt install php8.1 -y

Note: If you see the a dialog box similar to the following while running sudo apt upgrade, press Tab to jump to <OK> and press Enter to restart the services.

If everything went well, PHP has been installed on your system, which you can verify by using php -v command.

ubuntu@ip-172-31-12-45:~$ php -v
PHP 8.1.17 (cli) (built: Mar 16 2023 14:38:37) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.17, Copyright (c) Zend Technologies
with Zend OPcache v8.1.17, Copyright (c), by Zend Technologies
ubuntu@ip-172-31-12-45:~$

Install PHP Extensions

To use PHP with Laravel, some extensions are needed. Use the following command to install the required extensions.

sudo apt install php8.1-fpm php8.1-mysql php8.1-mbstring php8.1-xml php8.1-bcmath php8.1-zip php8.1-curl unzip  php8.1-gd

Restart Nginx Service

Use the following command to restart the Nginx service.

sudo systemctl restart nginx.service

Check if the Server is Running

  • Open the EC2 Dashboard and click Instances (running) to display all running EC2 instances.
  • Check the EC2 instance you have created, e.g. My Ubuntu 2023 Server.
  • Click the link in the Instance ID column (next to the Instance Name) to open Instance Summary details about your EC2 instance.

Have a look at the Public iPv4 address in the top row of the middle column. This is the ip address for your server.

  • To check if your server is running, click the copy icon located to the left of the Public iPv4 address and paste it in a browser address bar, and you would see a page similar to the following.

Note: If you click “open address” link next to the Public iPv4 address, it may not work. You may also manually type the address in the browser address bar, e.g. http://18.223.209.160

Linking your Domain to the EC2 Instance

The next step is to link your domain, e.g. www.mysite.com to the EC2 Instance, so that when someone types the url of your site in the browser address bar, it is directed to your server on the EC2 Instance where your Laravel application is hosted. For this, you need to link the Public iPv4 address to your domain.

Note: In general, public IPv4 address assigned to the EC2 instance remains same, however, there are some situations where public IPv4 address assigned to your EC2 may change when it is rebooted. To be on the safe side, you may create an Elastic IP address and link it to your instance. In that case, the public IPv4 address becomes the Elastic IP address, and it will never change. (If you associate EC2 instance to an Elastic IP address, the command to SSH into your EC2 instance will change.)

The instructions to link your public IPv4 address to your domain depends on your domain registrar, however, in general, you need to go to the Manage DNS section for your domain and update the Data value for the A record to the Public iPv4 address. On the following screen, you can see the A record that associates the domain name silkweb.ca registered with GoDaddy to the IP address 3.131.246.159.

Note: After changing the A record, the domain name propagation across the internet may take few hours, or even up to 24 hours.

Next, let us deploy the Laravel application on the EC2 instance.

Note: I am assuming that you have your application available in a GitHub repository.

Install Composer

You would need composer to setup the Laravel project. Use the following commands to install composer.

curl -sS https://getcomposer.org/installer -o composer-setup.php
sudo php composer-setup.php --install-dir=/usr/local/bin --filename=composer

After the composer has been installed, you may remove the composer set up file by executing the rm composer-setup.php command.

Clone the Laravel Application

Use the following commands to create the /var/www/vhosts folder, where the Laravel application will be cloned, and to select this folder.

sudo mkdir -p /var/www/vhosts
cd /var/www/vhosts
  • Login to your GitHub account, select the repository for the Laravel project you want to clone and click the Code button to reveal the url for the project, e.g. https://github.com/rktaxali/sayal.git in the following screeshot.
  • Click the copy icon to copy the git repository url.
  • Switch back to the Terminal, select the /var/www/vhosts folder and use the git clone command, as shown. (Replace the git repository url with the url you copied in the previous step)
cd /var/www/vhosts
sudo git clone https://github.com/rktaxali/cota22.git

It will start cloning the project and may ask for the username and password for the repository. After it has cloned the repository, you can confirm this by use the ls -l command:

Notice that it has created a folder for the repository name (cota22 in the example). We need to rename this to the domain name you want to use for your application and change the folder ownership from root to ubuntu. Use the following commands to accomplish this. (Replace mywebsite.com with your domain name)

sudo mv cota22 mywebsite.com
sudo chown ubuntu:ubuntu -R mywebsite.com

Next, change the ownership of the storage folder to www-data.

cd mywebsite.com
sudo chown www-data:www-data -R storage

Run Composer to Update Laravel Packages

While the Laravel application folder (/var/www/vhosts/mywebsite.com) is selected, use the following command to update Laravel packages.

composer update

Create .env file

You need to create an environment file for your project. You may either copy the .env.example to .env (and edit it) or create this file and copy the contents from the .env file of your local system.

nano .env

Generate Application Key

Use the following command to generate an application key for your project.

sudo php artisan key:generate

Note: If you read other articles on deployment of Laravel projects, you may find that they talk about php artisan migrate command to migrate database. I don’t use this because my database is already up and running and I manage it using DBeaver, a free and open-source universal database tool, therefore, I don’t need to migrate anything. Furthermore, I have not provided instructions for setting up a MySQL service on the EC2 instance as I use AWS RDS for running and managing my database.

Create a file in the sites-available folder and create a symbolic link

cd /etc/nginx/sites-available/
sudo nano laravel

Take code from https://laravel.com/docs/10.x/deployment#nginx and paste in the laravel file being edited. (If your application is based on Laravel 9 check https://laravel.com/docs/9.x/deployment#nginx)

You need to make changes in the following two lines:

server_name example.com;
root /srv/example.com/public;

Replace example.com with your website name, e.g. server_name mywebsite.com www.mywebsite.com and replace the second line with something like root /var/www/vhosts/mywebsite.com/public

Next, change folder to sites-enabled and create a symbolic link.

cd ../sites-enabled/
sudo ln -s ../sites-available/laravel .
ls -l

Notice that a new link has been created that links to ../site-available/laravel that you created above.

Restart Nginx

Use the sudo service nginx restart command and test your site. If you followed all instructions, you should see your website.

Additional Steps for a Laravel 10 Application

If you are deploying a Laravel 10 application that uses node modules, you may also need to complete the following steps:

  1. Set up node.js as per the instructions given in Tutorial: Setting Up Node.js on an Amazon EC2 Instance in the root folder.
  2. Switch to your application folder and execute the following commands:

npm install
npm update
npm run build

Install Free TSL Security Certificate (Optional)

If you want to install a free TSL certificate for your website, please see the article Setting up a Free SSL/TLS Certificate on AWS EC2 and other Servers.

If your website does not display on Rebooting the server

Occasionally, you may need to reboot your server after updating server software. If your website does not display after you reboot the server and your are unable to manually start the nginx service, check if the apache service is running by using sudo systemctl status apache2 If this service is running, stop this service and then try to start the nginx service:

sudo systemctl stop apache2

sudo systemctl start nginx

For details, please see this link on stackoverflow.

--

--

Ravi Taxali

Software developer and self-taught investor, who writes about self-development, health, life lessons and finance.