Skip to main content

Publishing to BunnyCDN with Hugo and GitHub

·419 words·2 mins
Table of Contents

I’ve been happily using BunnyCDN for general storage and distribution of web content for over 6 months. It’s very cost effective and flexible, with no overhead for running a static website.

As all of my static websites use GitHub for version control, I thought it would be interesting to change the experat@nothing website to use GitHub actions to kick off my Hugo builds and then to deploy by copying the contents to BunnyCDN.

BunnyCDN settings #

The first action was to check the storage zone associated with the expert@nothing domain. Under the “FTP & API Access” menu item BunnyCDN provides the FTP details.

Screenshot of BunnyCDN FTP & API Access settings

GitHub actions #

Using GitHub actions is pretty easy, all it takes is the creation of a single file in your repo that’s written in YAML and details what GitHub should do.

I use Hugo on my laptop to write posts and preview. I only push to the master branch at GitHub when I am happy for the website to be updated. So, I want GitHub to perform my Hugo build action on receiving the push to that branch. Once built the resulting files need to sent to BunnyCDN via FTP using the BunnyCDN credentials.

For GitHub to be aware of the BunnyCDN FTP credentails I added them to the GitHub secrets store. This allows GitHub to inject the value into the action when it’s run, without the credential being hardcoded into the YAML file.

I created the .github directory in the root of my website and created a new YAML file in it. I populated it with the code below which was modified from https://github.com/peaceiris/actions-hugo and https://github.com/sebastianpopp/git-ftp-action.

name: BunnyCDN FTP Deployment

on:
  # Trigger the workflow on push
  push:
    # To the master branch
    branches:
      - master
    # Also trigger on page_build, as well as release created events

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
        with:
          submodules: true  # Fetch Hugo themes (true OR recursive)
          fetch-depth: 0    # Fetch all history for .GitInfo and .Lastmod

      - name: Setup Hugo
        uses: peaceiris/actions-hugo@v2
        with:
          hugo-version: '0.74.2'
          # extended: true

      - name: Build
        run: cd expertatnothing; hugo --minify; pwd;

      - name: Create custom error page for 404
        run: mkdir /home/runner/work/expertatnothing/expertatnothing/expertatnothing/public/bunnycdn_errors

      - name: Create 404
        run: cp /home/runner/work/expertatnothing/expertatnothing/expertatnothing/public/404.html /home/runner/work/expertatnothing/expertatnothing/expertatnothing/public/bunnycdn_errors/404.html
        
      - name: Deploy FTP
        uses: sebastianpopp/ftp-action@releases/v2
        with:
          host: ftp://storage.bunnycdn.com
          user: expertatnothing
          password: ${{ secrets.BUNNYCDNSTORAGERW }}
          localDir: "/home/runner/work/expertatnothing/expertatnothing/expertatnothing/public"

This code is not perfect. It does overwrite existing files when there has been a change to them, but does not remove old files. It seems that if there’s no change between the newly generated version of a file and the existing version of the file that’s on BunnyCDN, that the file isn’t reuploaded which saves time.

Also, this code doesn’t purge the BunnyCDN pullzone in order to force the fresh content to be cached. This could be achieved by adding an API call after the FTP upload.