Deploy Laravel with Nginx on Ubuntu 22.04

Today I'm gonna share how to Install and Configure Laravel with Nginx and I am using AWS EC2 (t3.micro) for writing this tutorial.

Step 1 — Creating an EC2 Instance, DNS and SSH

First, we require an ec2 instance so launch an instance with your preferred size, you can also attach an Elastic IP to your instance.

In your DNS Server (Route 53 or Cloudflare) add these records.

Record NameRecord TypeValue
@A[Server_IP]
wwwCNAMEexample.com

Now, we have pointed from our DNS to our new server IP, now we need to log in into our new server using SSH client.

Example: ssh -i "YourKey.pem" ubuntu@SERVER_IP

Step 2 — Setup and Installing Requirements

Set a Timezone on Ubuntu:

sudo timedatectl
sudo timedatectl set-timezone Asia/Kolkata

If first time using apt in this session, run the update command to update the package manager cache:

sudo apt update -y

Install Nginx:

sudo apt install nginx

After installing, you can request to your domain (example.com), You will get nginx default page as response.

Install PHP 8.2:

You can replace the version 8.2 to 8.1 if you needed.

sudo add-apt-repository ppa:ondrej/php && sudo apt update

sudo apt install --no-install-recommends php8.2

sudo apt install -y php8.2-cli php8.2-common php8.2-mysql php8.2-zip php8.2-gd php8.2-mbstring php8.2-curl php8.2-xml php8.2-bcmath php8.2-fpm php8.2-tokenizer php8.2-mysql php8.2-intl

Install PHP 7.3:

sudo add-apt-repository ppa:ondrej/php
sudo apt-get update
sudo apt-get install -y php7.3

sudo apt install -y php7.3-cli php7.3-common php7.3-mysql php7.3-zip php7.3-gd php7.3-mbstring php7.3-curl php7.3-xml php7.3-bcmath php7.3-fpm php7.3-tokenizer php7.3-mysql php7.3-mcrypt php7.3-intl

Optional: In some cases, apache2 will get installed automatically on that case you can uninstall apache2:

sudo systemctl stop apache2
sudo apt-get purge apache2 apache2-utils apache2-bin apache2.2-common
sudo apt-get autoremove

Install Composer (PHP Package Manager)

curl -sS https://getcomposer.org/installer -o /tmp/composer-setup.php
HASH=`curl -sS https://composer.github.io/installer.sig`
echo $HASH
php -r "if (hash_file('SHA384', '/tmp/composer-setup.php') === '$HASH') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
sudo php /tmp/composer-setup.php --install-dir=/usr/local/bin --filename=composer
composer

Step 3 — Creating a Database for Laravel

If you are using any third party database like RDS then you can skip this step.

Create a MySQL database for Laravel application; so execute the following command on command line to create database for Laravel app:

sudo apt install mysql-server
sudo mysql_secure_installation
sudo mysql
CREATE DATABASE app_database;
CREATE USER 'app_user'@'%' IDENTIFIED WITH mysql_native_password BY 'password';
GRANT ALL ON app_database.* TO 'app_user'@'%';

SHOW DATABASES;
exit;

Step 4 — Install and Configure Laravel Project in Ubuntu 22.04

Creating a new Laravel project.

cd /var/www
composer create-project --prefer-dist laravel/laravel project_name

Set permissions on the Laravel directory using the following command:

sudo chown -R :www-data /var/www/project_name/storage/
sudo chown -R :www-data /var/www/project_name/bootstrap/cache/
sudo chmod -R 777 /var/www/project_name/storage/

You can set up the git into your server following this Link (OPTIONAL)

Step 4 — Setup Nginx

sudo nano /etc/nginx/sites-available/project_name

Change the root path /var/www/project_name/public and Copy, and paste the following Nginx Configuration

server {
    server_name example.com www.example.com;
    root /var/www/project_name/public;

    proxy_read_timeout 600;
    proxy_connect_timeout 600;
    proxy_send_timeout 600;

    index index.php index.html index.htm;
    charset utf-8;
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

    client_max_body_size 100M;

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/run/php/php8.1-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
    location ~ /vendor/.*\.php$ {
        deny all;
        return 404;
    }
    location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
        expires 1y;
        add_header Cache-Control "public, no-transform";
    }
    location ~ /\.ht {
        deny all;
    }
    location ~ /\.(?!well-known).* {
        deny all;
    }
}

If you are using any specific version of PHP version, Replace the FPM version fastcgi_pass unix:/run/php/php7.3-fpm.sock;

sudo ln -s /etc/nginx/sites-available/project_name /etc/nginx/sites-enabled/

sudo nginx -t
sudo systemctl reload nginx
sudo systemctl status nginx
sudo systemctl restart php8.1-fpm

Now you can request domain http://example.com and your site should be visible.

Step 5 — Installing SSL

sudo apt install certbot python3-certbot-nginx

sudo certbot --nginx -d example.com -d www.example.com

sudo systemctl status certbot.timer
sudo certbot renew --dry-run

Now you can request the website using https://example.com.

Creating Shell Script (Quick Actions) [OPTIONAL]

For restarting the Nginx and pulling Code from Git, I have created a shell script.

sudo nano /usr/local/bin/z

For creating the shell script, modify copy, and paste the following code to your terminal.

#!/bin/bash
select opt in Sync Restart ChangeDir CheckStatus Quit
do
    case $opt in
        Sync)  
            git pull origin master
            echo "Code synced"
            exit 0
            ;;
        Restart)  
            sudo nginx -t && sudo systemctl restart php8.1-fpm && sudo systemctl restart nginx
            echo "Nginx has been restarted."
            exit 0
            ;;
        ChangeDir)
            cd /var/www/project_name/
            echo -e '\nHit [Ctrl]+[D] to exit this child shell.'
            $SHELL
            exit 0
            ;;
        CheckStatus)  
            sudo systemctl status nginx
            echo "Shell by Sanjay Sikdar"
            exit 0
            ;;
        Quit)
            echo "Exited!"
            exit 0
            ;;
        *)
            echo "invalid option"
            ;;
    esac
done
sudo chmod +x /usr/local/bin/z

Now press the z key and hit enter.

ubuntu@ip-172-31-0-94:~$ z
1) Sync
2) Restart
3) ChangeDir
4) CheckStatus
5) Quit
#?

Select any option by pressing the number keys.

Hope you guys like the article. If you encounter any difficulties in understanding this approach, please don't hesitate to leave a comment.

Troubleshoot

Configure PHP Settings > sudo nano /etc/php/8.1/fpm/php.ini

Running Laravel Project on the Server > php artisan serve --host 0.0.0.0

Running Laravel Project > php artisan serve

Recompile > php artisan dump-autoload

It seems you don't have your permissions set up correctly for /var/www Change the ownership of the folder > sudo chown -R $USER /var/www

Create folders manually: cd storage && sudo mkdir -p framework/{sessions,views,cache} && sudo chmod -R 775 framework

To uninstall any specific version of php sudo apt-get purge 'php7.3.*'

Setup Cron > apt-get install -y cron && service cron start && systemctl enable cron && php artisan schedule:list