September 24, 2020

A while back I showed you how to deploy your WordPress site with Deploybot. I’ve used this service for years now, but when I started, it was out of my price range, so I used nothing and made many mistakes deploying my sites which cost me many lost hours and some tears.

Today, I’m going to walk you through how to use Github Actions to deploy your site automatically for no cost. The set up is more complex than Deploybot, but it’s going to be free for most projects.

This post has a bunch of working parts so set aside some time, especially if you haven’t worked with Git or SSH keys before. We’re going to cover:

  • Creating a Hosting Account
  • Getting your code into Git
  • Creating special deploy SSH keys for Github to use
  • Configuring the Github Actions YAML file
  • Using Github repository secrets to keep private information safe
  • rsync via ssh

What Are Github Actions?

Github Actions is a feature of Github that allows you to automatically perform tasks based on the state of your code. Today, we’ll look at deployment, but you could also have an action to run your unit tests or notify a Slack chat when someone makes a new PR on your project.

While they may take a bit of time and effort to set up your first time, they return the investment by letting you get back to code instead of worrying about repeating the same work over and over. 

Getting Your Site Set up

The first thing you’ll need is to create a hosting account on Nexcess, so head over and check out the plans available. The Maker WordPress plan is a good plan if you’re hosting a few sites.

With your site set up, go to the backups and create a backup of the site before you do anything else. Make sure you download this backup as well so you have a copy on your computer…just in case.

Unzip the backup and then copy out the public_html folder to use as our git repository. You can remove the wp-config.php file because we won’t need it today.

Now that we have our copy of the repository downloaded, let’s add it to Github. To start we’ll need to create a new repository in Github. Add your title and whatever description you want, I usually don’t initialize the repository with a README because I’ll provide my own with any project-specific notes and documentation for a client project.

Next, open up Terminal and cd into the downloaded copy of WordPress so you can initialize the repository with git init. The first thing we want to do is add our .gitignore file so that we don’t add any files that may overwrite what Nexcess needs to run your site. You can use the .gitignore file provided below.

The top eight lines are specific to Nexcess, so make sure you copy those lines if you have your own preferred ignore configuration.

If you’re not familiar with Git, check out my post on Introduction to Git.

.htaccess

wp-config.php

wp-content/uploads/*

wp-content/cache/*

wp-content/upgrade/*

wp-content/advanced-cache.php

wp-content/object-cache.php

wp-content/mu-plugins/*

config/app_config.yml

config/database.yml

config/*.sphinx.conf

config/s3_credentials.yml

*~

*.cache

*.log

*.pid

tmp/**/*

.DS_Store

db/cstore/**

db/sphinx/**

doc/api

doc/app

doc/plugins

doc/*.dot

coverage/*

db/*.sqlite3

*.tmproj

*.sw?

*.esproj

_notes*

dwsync.xml

podcast.xml

*.kpf

*uploads/*

*.swp

*.idea

*.sublime-project

*.sublime-workspace

*/node_modules/*

tags

*.bak

cache/*

managewp/*

Now that you have the ignore file ready, use git add and git commit to add the WordPress files to your repository. Then push those files to your Github repository.

Creating a Deploy SSH Key for Github

To deploy our site via Github Actions, we’ll need an SSH key for the action to use. Do not use your regular SSH key.

To generate the SSH keys needed use the command below using your email. When prompted for a passphrase, press enter and leave it blank. When you’re asked for a location, choose a location to store them temporarily. You can find Github’s documentation on SSH keys with extra details here.

ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

Before we take the next step, make sure your new SSH keys are stored safely. I store them in my 1Password vault alongside the other server credentials. Don’t leave them sitting in some folder on your computer because if someone gets your keys they get access to any server those keys are used on.

Now, open the public key (the one that ends in .pub) and open it in the text editor of your choice. In your Nexcess account, click on your account name in the top right corner and select SSH Keys.

Next, select Add Key and copy/paste the whole key out into the main text field. Make sure to label your key properly so you can tell what the key is being used for.

Finally, click Add to save the key to your account.

Adding and Configuring Your Github Action

Before we start to build our action, we’ll need some secret information stored in our account. Stuff like our private key for the key pair we just created, the location of our server, and the entry for the known_hosts file.

Start this by choosing Settings from the top right of your repository. Then choose Secrets from the left column. We’re going to add 3 different values.

  1. DEPLOY_SSH_KEY: This is the private key we generated (doesn’t have .pub at the end)
  2. NEXCESS_LOCATION: The location SSH will access on our server plus the file path to your html directory. Making a mistake here could delete your site, but this is why we took a backup.
  3. NEXCESS_HOST: The allowed host file we need from our server

You already have 1 so open your key file and copy it’s entire contents into a secret called DEPLOY_SSH_KEY.

Next, you can get the location of your server from your Nexcess control panel for your site under the Access menu.

Finally, the easiest way to get the content for NEXCESS_HOST is to ssh into your server from your computer. This should prompt you to accept a new known server. Accept the new server and then you can head to ~/.ssh/known_hosts and get the last line in the file for the secret you need to add to your repository.

Why are we keeping this stuff secret? Each of these pieces of information has some security risk so you don’t want them in your repository. Putting them in a secret variable in Github makes sure you don’t expose information by accident.

We’re ready to head back over to our repository on Github and get our action going. Start by going to the Actions menu at the top of your repository and click on it. While there are lots of prebuilt actions, we’re going to start by creating our own action so select that from the Actions screen.

Doing this will give you a basic workflow file written in YAML. By default, it works only on your master branch, but by changing which branch is in the arguments on lines 9 & 11 you can make it work for a different branch. You may do this if you wanted to deploy from a staging branch to a staging site and from master to the live site.

Starting with the line below, delete the rest of your default workflow file.

# Runs a single command using the runners shell

    - name: Run a one-line script

      run: echo Hello, world

Now we need to get our SSH agent. On the right hand side of the workflow screen search for webfactory/ssh-agent.

Click on this and it will provide you with some commands to copy and paste into the bottom of your file, but we’re going to use our own custom script. Copy the code below and paste it into your workflow file below the actions/checkout@v2line.

   # Setting up SSH

    - name: Setup SSH agent

      uses: webfactory/ssh-agent@v0.4.0

      with:

        ssh-private-key: ${{ secrets.DEPLOY_SSH_KEY }}

    - name: Setup known_hosts

      run: echo '${{ secrets.NEXCESS_HOST }}' >> ~/.ssh/known_hosts

    - name: Sync project files

      run: rsync -uvzr --backup --backup-dir='~/deploy-backup/' --exclude 'wp-config.php' --exclude '.gitignore' --exclude '.git/*' --exclude 'wp-content/uploads/*' --exclude '.htaccess' --exclude 'wp-content/cache/*' --exclude 'wp-content/advanced-cache.php' --exclude 'wp-content/object-cache.php' --exclude 'wp-content/mu-plugins/*' ${GITHUB_WORKSPACE}/ ${{ secrets.NEXCESS_LOCATION }}

You can see the secrets we set up earlier in this file. It starts by pulling in the ssh-agent and adds our private DEPLOY_SSH_KEY to the server it’s getting ready in the background. Next, it adds our server as a known host.

It finishes by syncing the project files over to the live server in a long rsync command. In short, it backs up the remote server into a directory called deploy-backup and then moves any new files in the Github project over to the live server. We excluded all the same location we ignored in our original .gitignore file so that rsync doesn’t touch them by accident.

If you want to read up on each rsync command there, I usually refer to this Ubuntu documentation on rsync

Now all you need to do is make some changes in your repository and then use git to add and commit them to your repository. Push those changes to Github, and the action will automatically backup your files and then push your changes over to your site.

If you’re new to automatic deployments, this does seem like a lot of work. Even my first time using Github Actions to deploy my site I spent a few days working on the script. This doesn’t feel like it saves time until I’m using the same script for weeks with a project deploying regularly.

Automating your deployment, and taking the time to get it right, means you never accidentally overwrite the wrong files, put the wrong files in the wrong directory, or make any other of the many mistakes I’ve made moving files around in the 12 years I’ve been building sites.

A day or two of time spent configuring deployment for your first time is worth saving that pain.

Curtis McHale
Curtis McHale

Curtis is a husband, father, developer and business coach. He specializes in helping people build a business that lets them spend time with their family instead of working all the time.

We use cookies to understand how you interact with our site, to personalize and streamline your experience, and to tailor advertising. By continuing to use our site, you accept our use of cookies and accept our Privacy Policy.