A production workflow for Laravel using Webdock servers

Last updated: May 25th 2021

Introduction

In this series we'll show you how to create a basic workflow between your local development environment and a live environment on our server stacks, leveraging git and git hooks.

We will be setting up a live environment on Webdock and showing you how you can automatically deploy code to your server whenever you push from your local development environment to, for example, Github.

Prerequisites

In order to follow along you need to have:

  • A local Laravel project (Laravel 8 or newer)
  • A (new) server on Webdock running our latest LEMP Perfect Server Stack
  • Shell access
  • A Github/Gitlab/Bitbucket account

In addition, we recommend you enable "Passwordless Sudo" script on your server (found on the Shell Users screen) in order to be able to run sudo commands in scripts and on the command-line without entering a password every time.

Set up Git & Git Hooks

Git is already installed on Ubuntu by default, so here we show you how you can initialize your Git repository on the Webdock server and set up hooks.

Once ssh'ed in to your server you initialize git by making a new folder in an appropriate location, for example /var/repo/ by doing:

      cd /var
      sudo mkdir repo

This will move you to the /var/ folder and make a new directory called /repo/.

To move you inside of that newly created folder type: cd repo and execute the following:

      sudo mkdir site.git && cd site.git
      sudo chown admin /var/repo/site.git
      git init --bare

This creates a folder called site.git, moves you into that folder and initializes git. The --bare flag is generally only used on servers which purpose is to receive pushes from developers. Visit the official git documentation to read more

Before initializing the git repo we change the ownership of the repo. This is nessecary to avoid root user rights to the git repo which causes problems when pushing to your live server. In this example we are using the default "admin" shell user which Webdock creates for you.

Git Hooks

Git repositories have a feature called hooks that can be used to moves files (and perform other actions) when performing a git push. Upon initializing git, a folder called hooks is created. Cd into that and by creating the following post-receive script the files will be moved to our specified destination after the push

Inside the hooks folder (/var/repo/site.git/hooks):

      sudo nano post-receive

This will open up a blank file. Paste the following into the file and save and exit the file by Ctrl + X then Y to confirm:

      #!/bin/sh
      git --work-tree=/var/www/laravel --git-dir=/var/repo/site.git checkout -f

The first line is the "shebang" operator followed by specifying which shell this script should run under. Here we have specified /bin/sh but it could just as well be /bin/bash if you prefer.

As this is "just a shell script" you can put in further post-receive actions here, such as normalizing permissions, running composer or whatever else you might need after your server has received code from your development environment.

In the command shown, the --work-tree= flag tells git where to copy received files. We set it to point to a web root folder called laravel that we will be making in the next section. The --git-dir= tells git where the bare git directory is that has received the files.

A final step to make the git hooks work is to assign the right permission to it in order to make the script executable. Still in /var/repo/site.git/hooks/ folder:

      sudo chmod +x post-receive

That sums up the basic setup of git and hooks.

Add the laravel folder and make it your web root

By default on Webdock stacks the web root is located at /var/www/html. To use the newly created git hook you will need to create at folder for the push to write to, as specified above. Fortunately this is easy:

      sudo mkdir /var/www/laravel
      sudo chown admin /var/www/laravel

Filesystem permissions

In order to allow Nginx to read your files and serve your content, the web group needs ownership and write permissions to the relevant laravel folders

      sudo chown -R :www-data /var/www/laravel
      sudo chmod -R 775 /var/www/laravel/storage
      sudo chmod -R 775 /var/www/laravel/bootstrap/cache

You could consider adding these commands to the post-receive script we made above, so they are run every time new code is deployed.

Change the web root in the Webdock dashboard

Laravels index.php is located in the public subfolder in your web root, so in order to serve the application you need to change the web root as interpreted by the web server (Nginx in this case). Locate the pencil icon next to your web root in the Webdock dashboard and change it from /var/www/html to /var/www/laravel/public

If you want to do this manually you have to change your web root in your nginx configuration, typically found under /etc/nginx/sites-enabled/ and restart nginx with systemctl restart nginx

Connect your local development to your production server

In this example we assume you are using Github, but almost any other Git repository service is compatible with this including Bitbucket, Gitlab and others. As mentioned we used Github with the suggested name 'origin' for our local to the repo provider. You can follow along by typing this into your local terminal window:

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

If you made a repo in Github both the user and repo parts come pre-filled for you in the link they provide.

Connecting to production is almost the same as connecting your development files to your repo service provider. You set up a git remote with a name that you think is appropriate. We choose 'production' to represent the production server. Be sure to have both connections to keep version control at your repo provider up to date as well.

First, make sure you still are in your local development terminal and not the server terminal. Then run:

     git remote add production ssh://admin@yourservername.vps.webdock.io/var/repo/site.git
     git push production master

The servername is the name of your created server, in this case laravel. The code from your git development master branch is now pushed to your server!

From now on, you can push to your server from your local computer by typing the command git push production master and this will push the master branch to our production server.

You can continue to push to github using git push origin master and let the changes go live once they are ready to push to production.

Note: You can create as many “remotes” as you want in git. It is common to have a secondary server called “staging” which is where push your project to for testing purposes in a live enviroment before pushing to a live production site

Verify it works

To check if everything is working correctly ssh into your server and cd into the /var/www/laravel/ folder and list the files.

      cd /var/www/laravel
      ls -lah

You should be able to see all the files from your development site in this directory.

Install Composer in production server

Now that your files are pushed to the server you need to install all of the composer dependecies for the application to work. In the /var/www/laravel/ folder:

      cd /var/www/laravel
      composer install --no-dev

Make sure to run the --no-dev flag on production. This will prevent composer from installing the unnessecary development dependencies to the production server.

These are also commands you could consider adding to your post-receive script in order to automatically install dependencies.

Laravel configuration

.env file

The .env file is the configuration file for your entire application. You can read more about it here

To create it you just copy the .env.example file from the root directory. In the /var/www/laravel/ folder run:

      cp .env.example .env
    

Edit it by typing:

      nano .env
    

Fill in your own database information and set the url and application environment to production & debug to false. On Webdock stacks the database host should be set to localhost.

App key and finishing configuration touches

You may have noticed when editing the .env file that the application key was missing. Generate it now by running:

      php artisan key:generate
    

All that is left is to cache for production speed load times, migrate the database and create a symlink from the storage to the public folder. 

Laravel comes with a lot of configuration which inherits from and cross references each other, all of which makes the configuration easier to read, but is slower for PHP to compile. By collecting all of the configuration in a single file it is a much faster execute by the server. Run:

      php artisan config:cache

Now that the configuration is set up, your app is ready to run. If you have a database and a public upload folder the only thing left is to migrate it and create a symlink from the storage folder to the public folder:

     php artisan migrate
     php artisan storage:link

When migrating the database you will get a warning that your app is in production mode to make you think twice about your decision. At this point it is fine but be aware of this in the future.

Additional concerns - The need for a staging and beta/testing server

In order to eliminate errors before they reach your clients/users it is wise to setup a testing/staging environment that matches your production environment.

One way of doing this is to have a seperate server. You can even grab a snapshot of one Webdock server and then create another with the exact same setup and then just adjust your git hooks.

Another suggestion is where you use a single server with different URL's for different versions of your code. For a guide on this setup using multiple urls which contain different Laravel installs - please see our guide on this approach

Series Author:  Thomas Damsgaard

Related articles