How to deploy a Laravel application into an ISPConfig server using GitLab pipelines

Angelo Cassano
4 min readApr 17, 2020

If you ever used Laravel Forge to deploy, you might have not ever faced the trouble of uploading a Laravel application. But what about using a different destination server? Things start getting a little bit harder when you use a non-conventional environment like ISPConfig.

Our case scenario will include a Debian 9 linux based OS, an ISPConfig control panel (with Apache2), and a Gitlab Community Edition repository manager.

I found peace when Loris Leiva released some Laravel deployment tools like Laravel Deployer and Laravel Docker. Laravel Deployer, I quote, is a lightweight wrapper of Deployer.org giving Artisan the power of zero-downtime deployment. Laravel Docker is a generic docker image for Laravel Applications.

To setup a Laravel deployment using GitLab’s pipelines I suggest you to follow this well documented guide written directly by Loris, just make sure to skip the deploy_path and the user parameters in the hosts configuration of the deploy.php file, we will edit this file later.

Once you’ve done it, we are going to make some changes and make the process ISPConfig compatible.

Setting up the permissions recipe

Laravel Deployer gives you the ability to define custom recipes to perform a new set of tasks during the deployment phase. In our case, we will define a new Permission.php file in the app/Tasks folder of our Laravel Application. The folder Tasks does not exist, so make sure you create it.

In the Permissions.php file, we will paste the following code, which essentially changes the permissions of our files according to the Laravel guide, and will also change the ownership of the deployed folders by assigning them to the user and the group given by ISPConfig. If we don’t perform these steps, we will face some 500 errors after the deployment because Laravel Deployer will deploy using root, and ISPConfig (Apache in our case) doesn’t have the permissions to read root’s stuffs.

<?php

namespace Deployer;

desc('Change app:permissions');
task('app:permissions', function () {
writeln('change permissions in {{deploy_path}}');

run('find {{deploy_path}} -type d -exec chmod 0755 {} +');
run('find {{deploy_path}} -type f -exec chmod 0644 {} +');

writeln('change ownership to {{app_user}}:{{app_group}} in {{deploy_path}}');
run('cd {{deploy_path}} && chown -Rf {{app_user}}:{{app_group}} current releases shared');
});

Update the deploy.php file

We now need to link our Permissions.php recipe to the deploy process. Open the config/deploy.php file and add ‘app:permissions’ in the ‘done’ array under the ‘hooks’ section of the file.

'hooks' => [
// Right before we start deploying.
'start' => [
],

// Deployment is done but not live yet (before symlink)
'ready' => [
'artisan:storage:link',
'artisan:view:clear',
'artisan:cache:clear',
'artisan:config:cache'
],

// Deployment is done and live
'done' => [
'app:permissions',
],

// Deployment succeeded.
'success' => [
//
],

// Deployment failed.
'fail' => [
//
],
],

Also, we have to define two new options that will be used by Permissions.php, these are app_user and app_group. These variables are read from the Laravel .env file, we will update it later.

Locate the ‘options’ section and update it accordingly.

'options' => [
'application' => env('APP_NAME', 'Laravel'),
'app_user' => env('APP_USER', 'root'),
'app_group' => env('APP_GROUP', 'root'),
'repository' => '<your repo>',
],

Remember the hosts section? Now we need to update the deploy_path and the user. In my example I’m using beta.example.com as a staging configuration and root as the user since my VPS forces me to use root to access it, but you can change it as mentioned by the Loris guide. Just make sure you set the web subfolder as the deploy_path.

'hosts' => [
'example.com' => [
'deploy_path' => '/var/www/example.com/web',
'user' => 'root',
],
'beta.example.com' => [
'deploy_path' => '/var/www/beta.example.com/web',
'user' => 'root',
],
],

To let the deploy.php find our Permissions.php file, we need to add a new line in the ‘include’ section of the file with the name of the recipe: ‘app/Tasks/Permissions.php’.

'include' => [
'app/Tasks/Permissions.php',
],

Update the .env files

It doesn’t really matter if you are deploying directly to production or you are passing by a staging process, if you have multiple .env files like .env.staging, .env.production, .env.testing and so on, you must update them accordingly and define the variables APP_USER and APP_GROUP used by the deploy.php file.

My .env.production file will look like this:

APP_NAME=Laravel
APP_ENV=production
APP_KEY=
APP_DEBUG=false
APP_URL=https://www.example.com

LOG_CHANNEL=stack

BROADCAST_DRIVER=log
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120

MAIL_DRIVER=smtp
MAIL_HOST=hostname
MAIL_PORT=587
MAIL_FROM_ADDRESS=info@example.com
MAIL_FROM_NAME="Laravel"
MAIL_USERNAME=info@example.com
MAIL_PASSWORD=
MAIL_ENCRYPTION=tls

APP_USER=web4
APP_GROUP=client5

What are web4 and client5? Well, these are the user and the group defined by ISPConfig for your specific website, you can retrieve them by opening the Options section in your Web Domain section. You will find the labels Linux User and Linux Group.

As a final step of our guide, we need to add the new DocumentRoot in the Apache Directives, by directly pointing to the Laravel’s public folder.

DocumentRoot "/var/www/example.com/web/current/public"

Deploy!

That’s it, you can now push your modifications and your Gitlab Runner will gently take care of building your Laravel application and deploy it to your ISPConfig server!

Thank you for reading!

Thank you so much for reading and if you enjoyed this article make sure to hit the clapbutton.

--

--

Angelo Cassano

A perfectionist. Software engineer and IT passionate.