Introduction
A big advantage of using a CMS like Kirby is that it’s possible to deploy your website directly from a GitHub repository. And because Kirby uses flat files instead of a database, this can include the content too.
As you complete each feature and push code to your repository, you can configure GitHub to push the changes automatically to a staging site for testing, and then to production when the site is ready for release. This is a major first step towards adopting a CI/CD workflow.
This tutorial assumes you are familiar with Git based source control, and how to use typical main and feature branches, so we won’t be covering this aspect here. Instead, we’re going to start by creating a staging site and configure GitHub to deploy your Kirby site automatically whenever you push code to your “main” repository branch. (Deploying to your live production site should only happen when you tag a release after testing is complete, which I will cover in a future article.)
Your web hosting must support Git and SSH for this to work. This tutorial also assumes you understand basic web administration functions, know how to use a terminal, and how to configure DNS, etc.
Note: a Kirby license is not required until you deploy to a live production site, at which point you will need to purchase one. In this tutorial, we will use a staging site, which you can password protect in your web hosting admin area, so it is not publicly available. Please refer to the Kirby License for more information.
Creating a new Kirby project
First, we’re going to create a new Kirby project.
To help kick-start this process, I’ve created a Kirby starter site which is available here on GitHub – https://github.com/christattum/kirby-starter-vanilla
Either download the repository files to a new directory on your development machine, or clone the repository and remove the “.git” folder afterwards.
If you’re using a local development environment like MAMP, WAMP or Laravel Herd, you can add the site and launch it from there. But you’ll need to run composer install to install Kirby and all its dependencies.
The starter project also includes DDEV config files, if that’s an option for you. Just edit the “.ddev/config.yaml” file, and change the project name at the top of the file, as highlighted below:-
name: kirby-starter-vanilla
type: php
docroot: ""
php_version: "8.2"
Then run the following commands in the project directory on your terminal:-
ddev start
ddev composer install
ddev launch
The Kirby site should now run on your local machine.
Creating a new GitHub repository
We can now create a new GitHub repository for the project. At a terminal, run the following commands in your new Kirby project directory:-
git init
git add .
git commit -m "Initial commit"
Push this to a new repository using the instructions GitHub provides.
Please note that the starter project includes a .gitignore file that excludes the kirby and vendor directories from your repository. These directories contain the Kirby CMS itself and its dependencies, and as Composer manages them, they are not required in your repository.
Creating a staging site
Now let’s create a new staging site on your web hosting, for the domain where you eventually want your site published. Make sure you use a staging subdomain such as:-
staging.yourdomain.com
As mentioned before, you won’t need to purchase a Kirby license until you move to production, so it needs to be clearly running on a staging site. You should also password protect the site in your web hosting admin area so that it’s not publicly accessible. The starter project also includes a robots.txt file which tells search engines not to crawl the site.
If you have questions about this, then please check the Kirby license for more details.
We now need to enable SSH access to the staging site from both your local machine and GitHub. Your local machine needs access so you can configure your web server and perform basic admin tasks, and GitHub requires access in order to deploy your site when you push changes to the repository. (Although strictly speaking, it’s actually a GitHub “runner” that logs into your web server, and then pulls the code from your repository, as we shall see!). So we need to create two SSH keys.
Creating an SSH key for your local machine
At your terminal, navigate to the ~/.ssh directory and run the following command to create an SSH key:-
ssh-keygen -t ed25519 -a 200 -f <your machine name> -C "<your machine name>"
This key will allow your local machine to access your web hosting using SSH, so your machine name is appropriate here.
Aside: An SSH key exists as a pair of files, a private key and a public key. In a nutshell, the way this works is that both keys are required to provide a secure connection between two machines, the private key at one end and the public at the other end. As the names suggest, we store the private key only on your local machine, i.e. it is private. The public key is shared and installed on the machine you require access to. When working with public/private keys, the principle is that we only share public keys, and private keys are secret (like passwords) and never shared.
So with that in mind, upload the public key (file with the .pub extension) to your staging site using your hosting’s SSH admin area. The key’s name should default to the comment we added (via the -C option), but if not, ensure you use the correct names for easy reference.
Configuring your machine SSH key
In your staging site’s SSH admin area, you should be able to view the SSH credentials for your local machine’s public key you uploaded. You need to note three pieces of information – the host, user and port number. We will refer to these as ssh host, ssh port and ssh user in the section below.
You need to add all three to your ~/.ssh/config file as shown below. Just create this file if it doesn’t already exist.
Host <friendly host>
HostName <ssh host>
IdentityFile ~/.ssh/<your machine SSH private key filename>
Port <ssh port>
User <ssh user>
The <friendly host> can be whatever you want, but use something descriptive and easy to remember such as my_project_staging. The IdentityFile line tells SSH to use the private key we just created when trying to connect.
When you connect using SSH, you only need to use this friendly host – the full (usually quite lengthy) host, user and port aren’t required as they’re stored in the config file.
Run the command below, and you should now connect to your staging site:-
ssh <friendly host>
If you get any errors, check the SSH credentials are correct, especially the port number. Your web hosting may also have an enable/disable SSH access toggle option, which you will need to enable. Once you can SSH successfully to your staging site, you can move on to the next section.
Creating an SSH key for GitHub Action
We’re now going to set up a GitHub action that automatically deploys the project to your staging site whenever you push code to your main branch. But as with your local machine, it needs an SSH key to access your web server. It’s not good practice to re-use SSH keys for different purposes (just as we shouldn’t reuse passwords) so we will create a new one.
At your terminal, navigate to the ~/.ssh directory and run the following command to create a new SSH key:-
ssh-keygen -t ed25519 -a 200 -f github-<your repo name> -C "github-<your repo name>"
This key will allow GitHub to access your staging site’s web server using SSH. The key’s name includes your project repository name to clarify its usage here, as we will attach it to your repository, not your GitHub account.
Just as before, upload the public key to your website’s SSH area. (You should now have TWO public SSH keys on your web hosting, one for your machine, the other for GitHub)
We now need to copy the private key we created above to GitHub. This appears to go against the principle of sharing private keys, but there’s no way to create the private key on GitHub itself. So what we do is copy the contents of the private key and store it in a GitHub Action secret, and then delete the private key from your machine. So in effect, we are adhering to the principle of keeping the private key secret by storing it solely against your GitHub repository.
Aside: You can think of it this way. The machine or system that requires access to some resource holds the (secret) private key, and the resource or system being accessed stores the (shared) public key.
To do this, via Settings – Secrets and Variables – Actions, add an Action Secret in your GitHub repository called SSH_KEY, and copy the entire contents of the private key file. Make sure you include both the BEGIN and END lines.
Then create three more secrets, STAGING_SSH_HOST, STAGING_SSH_USER, and STAGING_SSH_PORT and store the values from the same SSH credentials you stored in your machine’s “.ssh/config” file earlier. Make sure these secrets have the correct names, as they will be referenced later.
We prefix these secret names with “STAGING” because we’ll have different values for your live site when we get to that, although we can use the same SSH key for the staging and live site on the same server.
Summary of GitHub Action secrets
You should now have the following action secrets stored against your repository:-
| SSH_KEY | Private key used to SSH into your web server from GitHub |
| STAGING_SSH_HOST | Host used to SSH into your staging server from GitHub |
| STAGING_SSH_USER | User used to SSH into your staging server from GitHub |
| STAGING_SSH_PORT | Port number used to SSH into your staging server from GitHub |
Summary of SSH Keys
Let’s also review all the SSH keys we now have and their location:-
Your machine
<your machine name> PRIVATE key stored in ~/.ssh on your local machine.
GitHub repository
github-<your repo name> PRIVATE key stored in the SSH_KEY GitHub Action secret (now deleted from your local machine.)
Web server
<your machine name> PUBLIC key
github-<your repo name> PUBLIC key
End of Part 1
Well done! Both your machine and GitHub can now SSH into your staging server to issue commands.
This concludes the first part of this tutorial. The next part will explain how to configure GitHub to log into your staging site server (using SSH) and pull the latest code from your repository whenever you push or merge code into your main branch.