# Deploy Laravel App on AWS

## Introduction

Laravel is a popular open-source PHP framework known for its elegant syntax and comprehensive tools for building modern web applications. Its robust ecosystem and built-in features have made it a favorite among developers, leading to its rapid adoption in recent years.

In this guide, you'll learn how to install and configure a new Laravel application on an Ubuntu 24.04 LTS server. We'll use Composer to download and manage the framework dependencies and Nginx to serve the application.

## Prerequisites

To follow this guide, you will need to have an AWS EC2 instance up and running. This guide does not cover the setup of AWS or how to connect to your instance, as we will start from the point where you already have an Ubuntu instance on AWS. Let's get started.

### 1. Prepare for installing the required PHP and Nginx

In AWS EC2 instances, all root privileges are delegated to the default user. Therefore, you need to use the `sudo` command before executing any commands that require superuser privileges. This tells the server that you are authorized to run these commands. For example, to update the package list, you would run `sudo apt update`.

{% code fullWidth="false" %}

```vim
ubuntu@ip-172-31-20:~$ sudo apt update
```

{% endcode %}

### 2. Install Nginx

Install Nginx using the following command:

```vim
ubuntu@ip-172-31-20:~$ sudo apt install nginx -y
```

Now to verify that nginx works. We will need to visit the IP address of the server in the browser.

```vim
http://172-31-20
```

You will see a page like this:

<figure><img src="https://2084980273-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoRuMvjYhDLSQAmsSS9Bo%2Fuploads%2FklY1oVgMWikdvEXXzjky%2FScreenshot%202024-06-28%20162832.png?alt=media&#x26;token=8a7c59aa-46ee-4d83-a471-6cd65ba52a29" alt=""><figcaption></figcaption></figure>

### 3. Install PHP 8.2 and PHP-FPM

Since PHP 8.2 is relatively new, you might need to add a third-party repository to get the latest version. Use the following commands to add the repository and install PHP 8.2 along with PHP-FPM.

```vim
ubuntu@ip-172-31-20:~$ sudo add-apt-repository ppa:ondrej/php
```

### 4. Install PHP-FPM

```vim
ubuntu@ip-172-31-20:~$ sudo apt install php8.2-fpm
```

Okay, let's check whether our PHP version has worked or not.

```vim
ubuntu@ip-172-31-20:~$ php --version
PHP 8.2.20 (cli) (built: Jun  8 2024 21:38:01) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.20, Copyright (c) Zend Technologies
    with Zend OPcache v8.2.20, Copyright (c), by Zend Technologies
```

Awesome! It's worked. Before installing Laravel, you need to install several PHP modules required by the framework. These extensions provide additional support for handling character encoding, XML processing, etc. [Here](https://laravel.com/docs/11.x/deployment#server-requirements) is the server requirement.

```vim
ubuntu@ip-172-31-20:~$ sudo apt install zip unzip php8.2-zip php8.2-curl php8.2-xml php8.2-intl
```

### 5. Installing the Composer

We’ll use [Composer](https://getcomposer.org/) to install Laravel and its dependencies. You can install Composer by following the digital ocean guide on [How to Install Composer on Ubuntu 22.04](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-composer-on-ubuntu-22-04). That's the same installation on Ubuntu 24.04. You can feel free to start with Step 2! I already covered the php additional dependencies.

### 6. Installing the Node.js

Download your desired Node.js version PPA installation script. For example, run the following command to use the Node.js version `22.x`.

<pre class="language-vim"><code class="lang-vim"><strong>ubuntu@ip-172-31-20:~$ curl -fsSL https://deb.nodesource.com/setup_22.x -o nodesource_setup.sh
</strong></code></pre>

Run the Node.js setup script

```vim
ubuntu@ip-172-31-20:~$ sudo -E bash nodesource_setup.sh
```

Install Node.js using the following command.

```vim
ubuntu@ip-172-31-20:~$ sudo apt-get install -y nodejs
```

View the installed Node.js and NPM version on your server.

```vim
ubuntu@ip-172-31-20:~$ node -v
v22.3.0
ubuntu@ip-172-31-20:~$ npm -v
10.8.1
```

### 7. Installing Laravel App

So right now we have Nginx, PHP, PHP-FPM, and Composer installed. Let's start cloning the Laravel repo from GitHub. To do that, we need to generate an SSH key pair on the server, copy the public key, and save it as a deployment key on GitHub.

```vim
ubuntu@ip-172-31-20:~$ ssh-keygen -f /home/ubuntu/.ssh/id_rsa -t rsa -N ''
```

Okay. Let's print that key.

```vim
ubuntu@ip-172-31-20:~$ cat /home/ubuntu/.ssh/id_rsa.pub
```

> ssh-rsa AAAAB3NzaC1yc2\*\*\*\*\*ubuntu\@ip-172-31-20

And paste that key into your repo Settings>Deploy keys.

<figure><img src="https://2084980273-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoRuMvjYhDLSQAmsSS9Bo%2Fuploads%2FlC7R5Khd9T0fdCtEWCj0%2Fweshop-deploy-tutorial.png?alt=media&#x26;token=e1b62284-e813-4d62-a8cc-2af9116f235f" alt=""><figcaption></figcaption></figure>

That's it. And we need to check `/www` the directory which is owned by the root user or not. Let's change our directory `~` home to `/var` using:

```vim
ubuntu@ip-172-31-20:~$ cd /var
```

List down all of the directory and file permissions:

```vim
ubuntu@ip-172-31-20:/var$ ls -la
drwxr-xr-x  3 root root   4096 Jun 28 09:24 www
```

That's not good `/www` the directory is owned by the root user which means if we want to write any files in this directory we will have to use `sudo`. Okay, let's change the owner to Ubuntu. We need to change the owner `chown` belong to the user `ubuntu` and the group `ubuntu` for `/www` . Here is the command:

```vim
ubuntu@ip-172-31-20:/var$ sudo chown ubuntu:ubuntu www
```

{% hint style="info" %}
Why www directory?  The `www` directory in Nginx is commonly used as the document root or web root directory where your website's files (such as HTML, CSS, JavaScript, images, etc.) are stored. When Nginx is configured to serve a website, it looks in this directory to find the files to serve to users. If you want to learn more about nginx, php-fpm like that check it out [here](https://medium.com/@mgonzalezbaile/demystifying-nginx-and-php-fpm-for-php-developers-bba548dd38f9).
{% endhint %}

And let's check again.

```vim
ubuntu@ip-172-31-20:/var$ ls -la
drwxr-xr-x  3 ubuntu ubuntu   4096 Jun 28 09:24 www
```

Cool now. Right? Next, let's clone our Laravel app from GitHub. Change directory to `/www` and clone it.

```vim
ubuntu@ip-172-31-20:/var/www$ git clone git@github.com:ShaungBhone/weshop.git
```

Great. Now `cd` to `weshop` folder and let's install the composer. Notice that we are handling the production version of our app.

```vim
ubuntu@ip-172-31-20:/var/www/weshop$ composer install --ignore-platform-reqs --no-dev
```

We're running `composer install --ignore-platform-reqs --no-dev` will install only the necessary production dependencies, ignoring any platform requirements, and excluding the development dependencies.

### 8. Asset Bundling (Vite)

Laravel is now default support with Vite by providing an official plugin and Blade directive to load your assets for development and production. So, we need to install node modules on our server.

```vim
ubuntu@ip-172-31-20:/var/www/weshop$ npm install && npm run build
```

### 9. Configuring Laravel

We’ll now edit the `.env` file to customize the configuration options for the current application environment. At this time, we don't have `.env` file. Just an example file in here. Let's copy that environment file.

```vim
ubuntu@ip-172-31-20:/var/www/weshop$ cp .env.example .env
ubuntu@ip-172-31-20:/var/www/weshop$ nano .env
```

Let's generate the key.

```vim
ubuntu@ip-172-31-20:/var/www/weshop$ php artisan key:generate
```

We don’t need to set up all of them now. Just cover some values.

```properties
APP_NAME=Weshop
APP_ENV=production
APP_KEY=base64:qUYh8NpeFrPtJavWF0b8yVSaavzaNTOswv9KZh5Xb9I=
APP_DEBUG=false
APP_URL=http://172.31.20
ASSET_URL=http://172.31.20
```

Fantastic, we're almost there! All of the Laravel configurations are now complete. But, we need to tell the Nginx "This is our laravel application! I want to show it on the web server". Let's go back to the terminal. Before we configure nginx to display our Laravel application, we need to change back the ownership of the `/www` directory to a user and a group called www-data.

```vim
ubuntu@ip-172-31-20:/var$ sudo chown -R www-data:www-data www

ubuntu@ip-172-31-20:/var$ ll
drwxr-xr-x  4 www-data www-data 4096 Jun 28 14:15 www/
```

Perfect.

### 10. Setting up Nginx

We still need to configure Nginx to serve the content. To do this, we’ll create a new virtual host configuration file at `/etc/nginx/sites-available`:

```vim
ubuntu@ip-172-31-20:/var$ cd /etc/nginx/sites-available
```

The following configuration file contains the [recommended](https://laravel.com/docs/11.x/deployment#nginx) settings for Laravel applications on Nginx. So, let's create a new one called `weshop`.

```
ubuntu@ip-172-31-20:/etc/nginx/sites-available$ sudo nano weshop
```

And paste that code.

```vim
server {
    listen 80;
    listen [::]:80;
    server_name _;
    root /var/www/weshop/public;
 
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";
 
    index index.php;
 
    charset utf-8;
 
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
 
    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }
 
    error_page 404 /index.php;
 
    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
        fastcgi_hide_header X-Powered-By;
    }
 
    location ~ /\.(?!well-known).* {
        deny all;
    }
}
```

{% hint style="info" %}
The *server\_name* is left blank, we will use this attribute to match requests coming from a specific domain to a specific nginx block in the future.
{% endhint %}

We need to activate the `weshop` new virtual host configuration file into the `/etc/nginx/sites-enabled/` The final thing you need to know is that nginx will only read the above blocks that are enabled. To enabled use this command:

<pre class="language-vim"><code class="lang-vim"><strong>sudo ln -s /etc/nginx/sites-available/weshop /etc/nginx/sites-enabled/
</strong></code></pre>

In the Nginx configuration file's 'sites-available' directory, the default site configuration is still present. Nginx cannot operate with multiple default sites, so we need to remove the existing default site configuration.

```vim
ubuntu@ip-172-31-20:/etc/nginx/sites-available$ ll
total 16
drwxr-xr-x 2 root root 4096 Jun 28 18:49 ./
drwxr-xr-x 8 root root 4096 Jun 28 09:24 ../
-rw-r--r-- 1 root root 2412 Nov 30  2023 default
-rw-r--r-- 1 root root  786 Jun 28 18:49 weshop
ubuntu@ip-172-31-20:/etc/nginx/sites-available$ sudo rm -rf default
```

And site-enabled directory. Change directory to `/etc/nginx/sites-enabled`.

```vim
ubuntu@ip-172-31-20:/etc/nginx/sites-enabled$ ll
total 8
drwxr-xr-x 2 root root 4096 Jun 28 18:54 ./
drwxr-xr-x 8 root root 4096 Jun 28 09:24 ../
lrwxrwxrwx 1 root root   34 Jun 28 09:24 default -> /etc/nginx/sites-available/default
lrwxrwxrwx 1 root root   33 Jun 28 18:54 weshop -> /etc/nginx/sites-available/weshop
ubuntu@ip-172-31-20:/etc/nginx/sites-enabled$ sudo rm -rf default
```

To apply the changes, reload Nginx with:

```vim
ubuntu@ip-172-31-20:~$ sudo systemctl reload nginx
```

Now go to your browser and access the application using the server’s domain name or IP address.

```
http://172.31.20
```

Boom. you will see your Laravel app.

<figure><img src="https://2084980273-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoRuMvjYhDLSQAmsSS9Bo%2Fuploads%2FWiu8sK2TDwB2AsGhkdRb%2FScreenshot%202024-06-29%20104310.png?alt=media&#x26;token=700c3e1f-c148-4f92-bb77-4ebb89a0bca3" alt=""><figcaption></figcaption></figure>

## Conclusion

In this tutorial, you’ve set up a new Laravel application on top of a LEMP stack (Linux, Nginx, MySQL and PHP), running on an Ubuntu 24.04 server with php 8.2. However, I didn't cover MySQL, you can use any other AWS RDS Postgres, SQLite etc.

If you have any error, you can contact me <sbdev.business@gmail.com>. Follow me and googling with keywords `Shaung Bhone`. Thank you.
