Laravel zero downtime deployment with shared hosting
Tags: laravel, git, deployment, devops
Published: 2021-04-22 16:31:42

Lot of developers struggle to host a laravel application in a way so that they can deploy their latest update to production automatically.

I want to share some methods those I personally use.

In shared hosting you can update your production application using git VCS. This is really a cool feature. But we need some more.

We need to make sure every time we update our application, our production applications migrations and cache update as well.

There are two deploy on shared hosting.

1. Store your repository in repository hosting platform like GitHub. Update production application by pulling from your server.
2. Push your repository direct to server. (Must have SSH access).


## 1. Host somewhere and pull from server

Store your repository in any repository platform like GitHub.

 ![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qoqrh5zdmd0xiww36tva.png)
 
Copy the clone url.
Now, go to cpanel and navigate to **Git™ Version Control**
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/go2kjkrljnl3l6ke14zt.png)
Now click on the **Create** button to create a repository in your server.

A form will appear. Paste clone url.
Give a directory name, if you want to deploy your application to public_html directory, first clean public_html directory and write **public_html** in Repository Path.

*Putting laravel application in public_html is not good for security reason. If you want to know how to put laravel in another directory and link to public html, read [Linking public_html to laravel public directory in shared hosting](https://dev.to/hazzazbinfaiz/linking-publichtml-to-laravel-public-directory-in-shared-hosting-5ce2)*

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/26njdpcrqw3t3jqtlwro.png)

Now, click **Create** button to create repository.
If your repository is public, your server will clone the repository.

If your repository is public, Read [Deploy private git repository to shared hosting](https://dev.to/hazzazbinfaiz/deploy-private-git-repository-to-shared-hosting-na4)

Now you have a clone copy of your repository on your server.

Every time you update anything in your original repository you have to pull it from your server in order to sync servers repository with original repository.

To sync servers repository, login to cpanel and navigate to **Git™ Version Control** under **FILES** category. You will see the list of repository.
Click on the **Manage** button next to the repository you want to sync.

Now click on **Pull or Deploy** tab.
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2zjfko991ubbownqvh2d.png)

Click on **Update from Remote** button to update from remote repository.
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/td5yg2rf81tih1szhj35.png)

Now is zero downtime deployment part.

We want to automate the deployment part so that every time we update anything, migrate latest updates and recache config, views and events.

Put all commands you want to run every time any update become available in production in a bash file.

And execute it every time after updating the servers repository.

We can use cron job to automate this task.

```sh
#!/usr/bin/env bash

LAST_GIT_HASH=`git rev-parse --short HEAD`
LAST_HASH=`cat .git/laste_hash.txt`
if [[ "$LAST_GIT_HASH" != "$LAST_HASH" ]]; then
    cd /home/user/path_to_repository/
    php artisan down
    composer install -o --no-dev
    php artisan migrate --force
    php artisan optimize
    php artisan up
    git rev-parse --short HEAD > .git/laste_hash.txt
fi
```

You can add as much commands you need.

Put this bash file where you created the git repository.
You should add this to your project so that you can track it or add this bash file in .gitignore file so that your servers repository won't track it.

Execute this shell script in every minute by adding this command in cron tab.

`/usr/bin/bash /home/user/path_to_repository/script.sh >/dev/null 2>&1`

This script checks if the last deployed commit and the checked out HEAD is even or not. If not, it will execute commands between the condition.

## 2. Push your repository direct to server

In this way you don't need to store your repository in cloud. You can push from your computer (Must have SSH Access).

At first login to cpanel and navigate to **Git™ Version Control**
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/go2kjkrljnl3l6ke14zt.png)
Now click on the **Create** button to create a repository in your server.

A form will appear.
This time turn off **Clone a Repository** toggle switch because we are not cloning from anywhere.

Give a directory name, if you want to deploy your application to public_html directory, first clean public_html directory and write **public_html** in Repository Path.

*Putting laravel application in public_html is not good for security reason. If you want to know how to put laravel in another directory and link to public html, read [Linking public_html to laravel public directory in shared hosting](https://dev.to/hazzazbinfaiz/linking-publichtml-to-laravel-public-directory-in-shared-hosting-5ce2)*

Now, click **Create** button to create repository.

You will see a page with instruction command.
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5uqg5xm82z0np68vrh7v.png)
 
Follow those instructions to push your local repository to the server.

Now is zero downtime deployment part.

This time we will use git hook to automate this task.
Every time we push any update to remote repository, git executes `post-receive` hook.

In order to set up git hook for our task, we need to edit hook script.
If your repository is in `/home/user/repositories/example` directory, path of `post-receive` path will be `/home/user/repositories/example/.git/hooks/post-receive`.

You can edit is using cpanel text editor, or from terminal by SSH.

Some script should be already there, just go to end of the file and paste your deployment commands.

```sh

cd /home/user/repositories/example/
php artisan down
composer install -o --no-dev
php artisan migrate --force
php artisan optimize
php artisan up

```

You can add as much commands you need.

After adding those commands, the `post-receive` file will be like,
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ppr0n0cmsxg33rzt151g.png)
 

You will see the output of this hook while pushing from computer.


Have Fun 🎉 !!!