CI/CD with GitLab, cPanel, and my website

The one thing I’ve never liked about websites and why I always gravitate towards using a CMS is I hate FTPing files. I build the content, then I have to launch FileZilla, wait for everything to upload, and then call it a day. The downside is that I also lose some benefits of using version control such as git. What if there was an easier way? Turns out, there is.

As a system engineer, I use git on the daily for managing configuration software such as Ansible and Puppet. Git is great in these scenarios as you always have a record as to what was changed, by whom, and should things break, it’s easy to revert. I also use git at home for my own internal code, projects, documents, etc. I’ve always wanted to manage my site with it, but I’ve never had a true automatic deployment (CI/CD). I’d track the changes in git and then FTP the updates.

cPanel has boasted git for a few years now and according to the docs, there’s only two methods available: pull or push. Only one of these is automatic and that’s push. Push means that I pull code from my repo, I edit it, and then I push it to cPanel’s repo on my cPanel server and then it publishes to my web directory. There are a few issues with this:

  1. Pulling from my git repo and then pushing to a remote repo means there’s an extra step.
  2. I could mirror the repos, but that’s still an extra step.
  3. Either way, there’s too many extra steps.

If you have a cPanel hosting account and want to deploy your static site from git, here’s how to do it. This will also work if you have your site on a VPS without cPanel.

Requirements:

  • Shell access (if you have a shared hosting account)
  • PHP with shell_exec enabled (note: most hosts have this disabled. You can try this and then ask your host, however they may not disable it for you)
  • git

Steps

  1. If your site is not in git already, create a repo and get your site in it.
  2. Create a .gitignore file if you don’t already have it. Add the following and commit:
cgi-bindeploy.php.well-known

3. Login to your cPanel account and add the following file called deploy.php:

<?php/** * GIT DEPLOYMENT SCRIPT * * Used for automatically deploying websites via GitHub * Based on: https://gist.github.com/oodavid/1809044 */$key = '[SET_YOUR_RANDOM_KEY]';if ($_GET['key'] != $key){    header('Location: ./');    die();}    // array of commands$commands = array(    'echo $PWD',    'whoami',    'git checkout -- .',     'git pull',    'git status',    'git submodule sync',    'git submodule update',    'git submodule status',);chdir("/home/[SET_PATH_TO_PROJECT]/public_html");// exec commands$output = '';foreach($commands AS $command){    $tmp = shell_exec($command);        $output .= "<span style=\"color: #6BE234;\">\$</span><span style=\"color: #729FCF;\">{$command}\n</span><br />";    $output .= htmlentities(trim($tmp)) . "\n<br /><br />";}?><!DOCTYPE HTML><html lang="en-US"><head>    <meta charset="UTF-8">    <title>GIT DEPLOYMENT SCRIPT</title></head><body style="background-color: #000000; color: #FFFFFF; font-weight: bold; padding: 0 10px;"><div style="width:700px">    <div style="float:left;width:350px;">    <p style="color:white;">Git Deployment Script</p>    <?php echo $output; ?>    </div></div></body></html>
Source: https://gist.github.com/dusta/56dbbc0dec0aebd9196538088d2fd758

4. Add a secret key. I generated a GUID from here: https://www.allkeysgenerator.com/Random/Security-Encryption-Key-Generator.aspx

Make sure that deploy.php is in a public directory. For example, mine is at https://www.nightfox.tech/deploy.php.

6. Update the file directory path to your public_html (or subdomain public directory).

7. Switch over to your terminal or login via SSH and move to your public_html directory.

8. Run the following commands to initialize your public_html as a git repo:

git config credential.helper store #this saves my username and password as I use HTTPS to snycgit init .            #the . is important!git branch -m main    #this is because my main branch is called "main" but cPanel initializes it as "master"git remote add origin <url-to-my-repo>git checkout -f main  #my public_html already had my site in it so I had to overwrite everything

9. Now, add a hook to your repo. Consult your git provider on how to do this. I use GitLab so here’s how to do it:

Your Repo > Settings > Webhooks

URL: https://<your-domain>/deploy.php?key=<your-secret-key>

Trigger: Push events on main branch

SSL verification enabled

Save

Now, whenever you push to the main branch, your changes will be published automatically to your live site.

How to stop pushing every commit to prod (GitLab)

This is for GitLab, though I suspect similar is available for GitHub. But I self-host and prefer self-hosting so GitLab on-prem is my source of truth 🙂 If you use GitHub, that’s cool. I just can’t help you. You’ll have to RTFM yourself 😉

At this point, you’ve probably noticed that every commit will push to prod. You may not want this. Sometimes, I miss small things and I’ll commit 3 or 4 times in 5 minutes. To not do this, I protect my main branch.

Settings > Repository > Protected Branches

From here, I select my main branch. Set Allowed to Merge to Developers + Maintainers. Set Allowed to Push to No One. It should look like this:

With the main branch protected, only GitLab can actually merge. So to be able to merge, you need a Merge Request. Go to Settings > General > Merge Requests. Set these settings to whatever works for you.

Now to edit your site, you need to create a new branch. Make you changes in that branch, then create a Merge Request. When you click the merge button, your changes will then be added to the main branch which will then call the webhook and publish your changes. How awesome is that?

A MR from my website repo. I fixed an issue I was having with my automated deployments and needed to push a change.

Now you have some CI/CD for your site. You can probably take it a step further and implement an actual CI/CD pipeline, staging site, etc.

Welcome to DevOps!

1 thought on “CI/CD with GitLab, cPanel, and my website”

  1. Pingback: A wrap up of 2022 – NightFox Blog

Leave a Comment

Your email address will not be published. Required fields are marked *