How to deploy Laravel application to a server
Step-by-step guide on deploying laravel application to a VPS.First published on
This is a step-by-step guide to setup your Laravel application on Vultr or Digital Ocean or any other VPS with root access.
- Selecting a server
- Creating a server
- Login to your server
- Add a user
- Setup SSH for the new user
- Install PHP
- Install Composer
- Install Nginx
- Setup Git
- Set permissions
- Setup MySQL
- Import/Export database
- Setup Redis
- Setup Supervisor for Queues
- Setup Cron for Scheduled jobs
- SSL Certificate
- Storage Symlink
Selecting a server
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.
Important: The signup bonus expires after 2 months from signup. Be careful with the resources you create with them. If you are not careful you will charged accordingly after the bonus duration.
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 serversforhackers.com 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@192.168.0.1
from your terminal app.
Replace 192.168.0.1 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
On your local machine, you need to create public and private keys. Run the below command from your local terminal to create the keys. All the keys should be in .ssh folder
cd ~/.ssh
ssh-keygen -o -a 100 -t ed25519 -f id_some_identifier
Copy the public key
cat id_some_identifier.pub
On the server, add the public key. First we need to create the directly and then paste the key in authorized_keys file.
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.2-fpm php8.2-cli php8.2-mysql \
php8.2-mcrypt php8.2-gd php8.2-imap php8.2-curl \
php8.2-mbstring php8.2-xml php8.2-bcmath php8.2-zip
You can replace the version number if you are installing more latest versions.
Install Composer
php -r "readfile('http://getcomposer.org/installer');" | 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
Note: We should add ssl_certificate details in the config only after installing ssl certificate with certbot. You can also refer laravel docs to get the config details.
server {
listen 80 default_server;
server_name thedomain.in www.thedomain.in;
return 301 https://thedomain.in$request_uri;
}
server {
listen 443 ssl default_server;
ssl_certificate /etc/letsencrypt/live/<thedomain.in>/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/<thedomain.in>/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 everytime you change the nginx configs.
sudo nginx -t
sudo systemctl reload nginx
- Nginx setup in Laravel docs
Setup Git
It would be easy to push directly from your local machine. There are many other ways to push your code to the server. This will act as your starting point.
On your server:
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
#!/bin/sh
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://raviteja@example.com/var/repo/site.git
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
sudo apt-get install supervisor
Create new file laravel-worker.conf inside /etc/supervisor/conf.d directory.
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/thelaravelfolder/artisan queue:work redis --tries=1 --timeout=3600 --max-time=3600
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=raviteja
numprocs=8
redirect_stderr=true
stdout_logfile=/home/raviteja/thelaravelfolder/worker.log
stopwaitsecs=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.
Storage Symlink
php artisan storage:link