How to deploy a laravel application to a VPS

James Singizi
7 min readOct 31, 2020

--

Deploying applications to production the right way is not an easy task for newbies. At times even seasoned developers struggle with DevOps and end up taking days before their applications are available to the public. In this post, I will attempt to show how easy it can be to deploy a laravel application to production in a matter of minutes.

Prerequisites required.

  • A server running ubuntu 18.04 or 20.04
  • SSH access to the server from a local terminal
  • A project hosted with git (GitHub/GitLab/Bitbucket etc)

For the server, you can use any cloud service that suits you, I have personally used AWS and Azure, other services include Digital Ocean, Linode and Google cloud compute engine

For setting up git you can read the docs here. Github now supports free private repositories so you can use it for hosting your project, other alternatives include GitLab and bitbucket.

Once you have all the requirements setup you can now proceed with your deployment.

Step 1: Log in to your server as root

Login to your server using ssh from a terminal. I recommend that you set up ssh keys on your server from the server monitoring dashboard if your service provider supports it.

ssh root@serveripaddress

or with ssh setup

ssh -i /path to ssh keys.pem root@serveripaddress

Once you login to your server there are a few things you need to fix before proceeding. Run the following commands to

sudo apt-get updatesudo apt-get install -y unattended-upgrades

Step 2: Disable password login

Passwords are notoriously insecure at times and you should disable password login to your server. Once password login is disabled you can only login with ssh keys which are more secure. To disable password login, enter the following command to open the ssh config file in your favourite editor. (I am a vim user but you can use nano… but vim is cooler though :-) )

sudo vim /etc/ssh/sshd_config

Once the file opens in your text editor navigate to a line that says PasswordAuthentication. If the line is commented (prefixed by #), then remove the comment and make sure it is set to no. Save the file and restart ssh service with the following command:

sudo service ssh restart

Some service providers disable this by default and there is no need to do this step.

Step 3: Install Fail2Ban

Fail2Ban is a program for Linux based servers that block hackers by scoring server logs and banning IP addresses with malicious patterns

sudo apt-get install -y fail2ban

Step 4: Install Webserver

Nginx is awesome. For the majority of cases, Nginx will suit your needs. Enter the following commands to install and restart Nginx on your server.

sudo apt-get install -y software-properties-commonsudo add-apt-repository ppa:nginx/stablesudo apt-get updatesudo apt-get install -y nginxsudo service nginx restart

Now visit your servers public IP address in a browser (eg. http://127.0.0.1) and you should see a page similar to the following:

nginx default page

if you see an error output that mentions something similar to “Unable to resolve host”, try the command without the ‘sudo’ keyword

Step 5: Install PHP 7, composer, curl, wget and other required libraries

Curl and wget are important HTTP tools needed for composer installation. Git is a source code management tool and will be required for pulling code repo to the installation server

sudo apt-get install -y git curl wget

Install PHP 7

PHP 7 is required for Laravel 5.7+. Before installing PHP 7 first check if there is no PHP 5 installed. Remove PHP 5 using the following commands:

sudo apt-get purge php5-fpmsudo apt-get — purge autoremove

Once you are certain the PHP 5 is removed then proceed to install relevant repositories for PHP 7.

sudo apt-get install -y software-properties-commonsudo apt-get install -y python-software-propertiessudo add-apt-repository ppa:ondrej/phpsudo apt-get update

Install and restart PHP 7 using the following commands.

sudo apt-get install -y php7.4 php7.4-fpm php-mysql php7.4-mysql php-mbstring php-gettext libapache2-mod-php7.4 php-doctrine-dbal php7.4-pgsql php-xml redis-serversudo systemctl restart php7.4-fpm

Install composer for dependency management

Run the following command on your terminal to install composer dependency manager.

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

Install Node & NPM

If your project has NPM dependencies then you need to install Node and NPM package manager with the following commands:

curl -sL https://deb.nodesource.com/setup | sudo bash -sudo apt-get install -y npm#Gulp, Grunt and Yarnln -s /usr/bin/nodejs /usr/bin/nodesudo npm install — global yarn gulp-cli grunt-cli

Make your git repo production-ready

Create a production-ready version of your application on your development machine. Now, create a production branch using the following command.

git branch production

Now that the production branch is ready, check it out and push it to your repo.

Switch to the production branch

git checkout production

Merge changes in the development branch with your production branch.

git merge — no-ff master

*replace master in the command above with your development branch name. Adding “ — no-ff” makes sure it creates a new commit so that we can track merges into the production branch

Push the production branch to your remote repository (Gitlab, Github, Bitbucket)

git push -u origin production

Pull production branch to the production server.

First, create a directory for your app with your app name under /var/www

sudo mkdir /var/www/app_name

Now cd into your application directory and create a new git repo.

cd /var/www/app_namesudo git init

Add your git remote and pull your project to your server

git remote add origin https://github.com/user/repo.gitgit pull origin production

Step 6: Configure the Server to serve our app

Open the Nginx config file using a text editor (vim :-))

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

All edits to this file should be done within the ‘server{ }’ block.

Make URLs Pretty

Change the default ‘location / { }’ block’s contents from

try_files $uri $uri/ =404;

to

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

Disallow access to dot files (for obvious security reasons)

location ~ /\.{    deny all;}

Add PHP capability

Find the following line

index index.html index.html index.nginx-debian.html;

and change by adding index.php to make it look like this:

index index.html index.html index.nginx-debian.html index.php;

For php7, add the following lines, replacing 7.4 with the actual PHP version you have installed.

location ~ \.php$ {include snippets/fastcgi-php.conf;fastcgi_pass unix:/run/php/php7.4-fpm.sock;}

Now update the virtual hosts file to server our application.

change this line:

root /var/www/html;

to:

root /var/www/AppName/public;

Now we are done with editing the config file. Save it and run the following command to make sure our config is correct:

sudo nginx -t

If no error comes up then the config is okay, restart Nginx for changes to take effect.

sudo service nginx restart

Set Permissions

Set permissions for the public directory where public files are located.

sudo chown -R www-data:www-data /var/www/AppName/publicsudo chmod 755 /var/wwwsudo chmod -R 755 /var/www/AppName/bootstrap/cachesudo chmod -R 755 /var/www/AppName/storage

Now that permissions are set, its time to install PHP and npm dependencies.

composer install

may need sudo for this command

npm installnpm run production 

Your command to compile frontend javascript

Step 7: Setting up your database

Install MySQL 8.0 which is stable and works well with laravel and other application frameworks.

First, download the latest repository with the following command:

wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.11-1_all.deb

Now install the downloaded repository:

sudo dpkg -i mysql-apt-config_0.8.11–1_all.deb

Refresh the repositories (as always)

sudo apt-get update

Install MySQL

sudo apt-get install mysql-server

Once MySQL is installed, set up security using the following command

sudo mysql_secure_installation

Go through the prompts to complete securing your MySQL installation.

Once installation and securing is done the server should start automatically. You can check its status as follows:

sudo service mysql status

stop the service with:

sudo service mysql stop

and start it again with:

sudo service mysql start

Now login with root user. This is root@localhost.

sudo mysql -u root -p

To allow remote connections and other IP addresses make sure to change the MySQL configuration file as follows:

Delete or comment the bind_address parameter from the my.ini file.

(The file name is different depend on the OS. On Linux my.ini is actually my.cnf located in directory /etc/mysql/)

Restart the service.Create the root user (yes, a new user because what exists is ‘root@localhost’ which is local access only):CREATE USER ‘root’@’%’ IDENTIFIED BY ‘123’;Give privileges:GRANT ALL PRIVILEGES ON *.* TO ‘root’@’%’;

For DBA user, add WITH GRANT OPTION at the end.

e.g. CREATE USER ‘root’@’%’ IDENTIFIED BY ‘123’ WITH GRANT OPTION;

Step 8: Setup your environment

Create a .env file for the Laravel app using the following commands

cd /var/www/AppNamecp .env.example .env

Now open the .env file with your favourite text editor.

sudo vim .env

Change the necessary env variables. Change the following variables, as well as other variables that you may have to change such as database, AWS, Redis, mail, pusher configs.

APP_ENV=localAPP_DEBUG=true

to:

APP_ENV=productionAPP_DEBUG=false

Now generate application key which will be used for encryption

php artisan key:generate

Now migrate your database (make sure you have correct database credentials setup in your .env file)

php artisan migrate:installphp artisan migrate

Step 9: Setting up SSL with Lets Encrypt

Let’s Encrypt provides free SSL certificates. Let’s install it using Certbot

sudo apt-get install -y software-properties-commonsudo add-apt-repository ppa:certbot/certbotsudo apt-get updatesudo apt-get install -y python-certbot-nginx

Set up the website’s virtual hosts by opening nginx config file with the following command:

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

Change the following line, replacing example.com with your own domain

server_name _;

changes to

server_name example.com www.example.com;

and this

listen 80 default_server;listen [::]:80 default_server;

changes to:

listen 80 default_server;listen [::]:80;

Copy the newly created virtual hosts file into its own file and then to sites-enabled with the following command.

sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/example.comsudo ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/

Install your SSL certificate provided by let’s encrypt with the following command.

sudo certbot — nginx

And you are done, give yourself a pat on the back as your newly created application takes over the internet

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

James Singizi
James Singizi

Written by James Singizi

James is a software developer with more than 3 years experience with PHP and Python. He is passionate about code and software development

No responses yet

Write a response