How to deploy Laravel application to a server

This is a step-by-step guide to setup your Laravel application on Vultr or Digital Ocean.

First you need to select a server in one of the service providers. I deploy all my servers on Vultr. I have been using this service since 2017. Get 100$ as signup bonus on Vultr.

Or you can use DigitalOcean. Get 200$ as signup bonus on DigitalOcean.

Do note that the signup bonus expires after 2 months from signup.

This post is a collection of commands that helped me setup Laravel in a VPS. I have written this for myself to just copy and past the commands directly so that I don’t have to go to individual resources. Most of the resources are from by Chris Fidao.

Creating a server

After creating an account on Vultr or DigitalOcean, you should select a server size based on your needs and opt to install Ubuntu.

Please choose Ubuntu LTS version. If it is not LTS version, it will be hard to update our softwares - like PHP - in future.

Login to your server

After creating a server, you will be given the IP address and login credentails for root user.

You will need an ssh client to log into your newly created server. I use Windows Terminal app.

To login, do ssh root@ from your terminal app.

Replace with the IP address of your server.

Add a user

After logging in as root, add a new user and add to sudo group.

sudo adduser raviteja

usermod -aG sudo raviteja

From here on, run commands as the new user with sudo permissions.

sudo su raviteja

Setup SSH for the new user

cd ~/.ssh
ssh-keygen -o -a 100 -t ed25519 -f id_some_identifier

Copy the public key


On the server, add the public key.

sudo su raviteja
mkdir ~/.ssh
cd ~/.ssh
nano authorized_keys

Install PHP

Installs the latest version if you have not added PPA package.

sudo apt-get install git curl wget zip unzip

sudo add-apt-repository -y ppa:ondrej/php

sudo apt-get update

sudo apt-get install -y php8.1-fpm php8.1-cli php8.1-mysql \
  php8.1-mcrypt php8.1-gd php8.1-imap php8.1-curl \
  php8.1-mbstring php8.1-xml php8.1-bcmath php8.1-zip

You can replace the version number if you are installing more latest versions.

Install Composer

php -r "readfile('');" | sudo php -- --install-dir=/usr/bin/ --filename=composer

Install Nginx

sudo apt-get install nginx

Allow Nginx in firewall

sudo ufw app list

sudo ufw allow 'nginx full'

sudo ufw reload

Change nginx config

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

We should add ssl_certificate details in the config only after installing ssl certificate with certbot.

server {
  listen 80 default_server;

  return 301$request_uri;

server {
  listen 443 ssl default_server;

  ssl_certificate      /etc/letsencrypt/live/<>/fullchain.pem;
  ssl_certificate_key  /etc/letsencrypt/live/<>/privkey.pem;

  root /var/www/ourprojectfolder/public;

  index index.php;

  location / {
    try_files $uri $uri/ /index.php?$query_string;

  location ~ \.php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/var/run/php/php8.0-fpm.sock;

  location ~* (?:^|/)\. {
    deny all;

  location ^~ /.well-known/acme-challenge/ {
    allow all;

Test the configuration

sudo nginx -t

sudo systemctl reload nginx

Setup Git

cd /var

sudo mkdir repo && cd repo

sudo mkdir site.git && cd site.git

sudo git init --bare

Setup post-receive hoook

cd /var/repo/site.git/hooks

sudo nano post-receive

Add the contents to the post-recieve file

git --work-tree=/var/www/laravel --git-dir=/var/repo/site.git checkout -f

Change the permission

sudo chmod +x post-receive

Change the ownership for the current user

cd /var/repo

sudo chown -R raviteja site.git

On your local system, inside your Laravel project

git remote add production ssh://

git push production master

If you are using main branch locally, do git push production main:master

Set permissions

ps aux | grep php

cd /var/www/thelaravelappfolder

sudo chown -R www-data:raviteja storage bootstrap

Setup MySQL

sudo apt-get install -y mysql-server

create database yourdatabase

create user databaseclient@'localhost' identified by 'a-password';

grant all privileges on yourdatabase.* to databaseclient@'localhost';

Import/Export database

// Export
mysqldump -u databaseclient -p yourdatabase | gzip > the_database_file_name.sql.gz

// Import
gunzip < 20122020_b.sql.gz | mysql -u databaseclient -p yourdatabase

Setup Redis

sudo apt-get install redis-server

redis-cli ping

Setup Supervisor for Queues

Supervisor docs.

sudo apt-get install supervisor

Create new file laravel-worker.conf inside /etc/supervisor/conf.d directory.

command=php /var/www/thelaravelfolder/artisan queue:work redis --tries=1 --timeout=3600 --max-time=3600

Make this directory /home/raviteja/thelaravelfolder/ for the log.

Start supervisor

sudo supervisorctl reread

sudo supervisorctl update

sudo supervisorctl start laravel-worker:*

sudo supervisorctl status

For timeout function to work on the queues, pcntl extension should be enabled.

php -i | grep pcntl

Setup Cron for Scheduled jobs

crontab -e

* * * * * cd /var/www/laravelfolder && php artisan schedule:run >> /dev/null 2>&1

SSL Certificate

sudo snap install core; sudo snap refresh core

sudo snap install --classic certbot

sudo ln -s /snap/bin/certbot /usr/bin/certbot

// This command will edit the nginx configuration
sudo certbot --nginx

// I use this command so that the nginx configuration is not edited
sudo certbot certonly --nginx

// testing to renew
sudo certbot renew --dry-run

More instructions on the official website.

php artisan storage:link

Post Tags: