Skip to main content

Continuous deployment of a Hugo website to shared hosting with Github Actions

·2 mins

After I converted my personal website to the static site generator Hugo, I ran into a problem. Every time I wanted to make an adjustment to my site I had to go through the following steps:

  1. Make the change
  2. Commit and push to Github
  3. Build the site with Hugo (hugo --minify)
  4. Upload the output of the public folder over FTP to my webhost.

To speed up this process I started using Github Actions. As soon as I push the changes to the main branch the site needs to be built and uploaded.

Creating a Github Action #

The first step is to create a Github Action. To achieve this, you need to create a file in the .github/workflows folder. The name of this file is not important, but the metadata filename must be either action.yml or action.yaml. I use build-and-deploy.yml.

Building and deploying #

1. Checkout code #

First we checkout our repository so that our workflow can access it.

on: push
name: 🚀 Deploy website on push
jobs:
  web-deploy:
    name: Deploy
    runs-on: ubuntu-latest
    steps:
    - name: Checkout
      uses: actions/checkout@v3

2. Build with Hugo #

The next step is to build our Hugo site. We achieve this using actions-hugo. I use the --minify flag, but it can be replaced by -D for example if you want to include drafts or just hugo is also sufficient.

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

- name: Build
  run: hugo --minify

3. Deploy with FTP #

Finally, the content of the public must be uploaded via FTP to the webhost. It is necessary to add the username (FTP_USERNAME) and password (FTP_PASSWORD) as secrets on your Github repository.

- name: Deploy
  uses: SamKirkland/[email protected]
  with:
    server: ftp.niekvanleeuwen.nl
    username: ${{ secrets.FTP_USERNAME }}
    password: ${{ secrets.FTP_PASSWORD }}
    local-dir: ./public/

Result #

If we merge the above code snippets we reach the following result

on: push
name: 🚀 Deploy website on push
jobs:
  web-deploy:
    name: Deploy
    runs-on: ubuntu-latest
    steps:
    - name: Checkout
      uses: actions/checkout@v3

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

    - name: Build
      run: hugo --minify
    
    - name: Deploy
      uses: SamKirkland/[email protected]
      with:
        server: ftp.niekvanleeuwen.nl
        username: ${{ secrets.FTP_USERNAME }}
        password: ${{ secrets.FTP_PASSWORD }}
        local-dir: ./public/

Thanks for reading! If you have found a mistake, want to ask a question or have a comment, please send me an email.