DEV Community

Matt Rueedlinger
Matt Rueedlinger

Posted on • Originally published at rueedlinger.ch on

Deploy Hugo Websites to SFTP with GitHub Actions

In my 2020 post, I revitalized my blog and set up an automated pipeline to publish blog posts using Hugo and GitHub Actions.

Hugo is a fast, open-source static site generator written in Go. I store all my site content on GitHub, where it is automatically built by GitHub Actions and then published to my website via SFTP.

In this post, I will give an update on my publishing pipeline and describes how to use a Hugo theme with Git submodules. Previously, I created my own private Hugo theme, but this was quite a challenge to update and maintain. So I decided to switch to the PaperMod theme, which looks very nice and clean.

Prerequisites

Before you start, make sure you have:

Steps

1. Create a New GitHub Repository

Create a new project folder and navigate into it:

mkdir MyFreshWebsite
cd MyFreshWebsite/
Enter fullscreen mode Exit fullscreen mode

Initialize a Git repository and create a README file:

echo "# MyFreshWebsite" > README.md
git init
git add README.md
git commit -m "Initial commit"
Enter fullscreen mode Exit fullscreen mode

Set the main branch, add your remote repository, and push:

git branch -M main
git remote add origin https://github.com/rueedlinger/MyFreshWebsite.git
git push -u origin main
Enter fullscreen mode Exit fullscreen mode

2. Create a New Hugo Site

Run the following command to create a new Hugo site using YAML configuration:

cd MyFreshWebsite/
hugo new site . --format yaml --force
Enter fullscreen mode Exit fullscreen mode

Add /public to .gitignore so that when we build our website locally, these files are ignored by Git.

.gitignore

# Hugo default output directory
/public
Enter fullscreen mode Exit fullscreen mode

3. Install and Activate the PaperMod Theme

This will add the PaperMod theme as a submodule in themes/PaperMod. See the PaperMod Installation Guide for details.

git submodule add https://github.com/adityatelange/hugo-PaperMod.git themes/PaperMod
Enter fullscreen mode Exit fullscreen mode

This command should add the file .gitmodules

.gitmodules

[submodule "themes/PaperMod"]
    path = themes/PaperMod
    url = https://github.com/adityatelange/hugo-PaperMod
Enter fullscreen mode Exit fullscreen mode

Next, let's update the submodule. First, change to the root directory of your project:

git submodule sync               # Updates Git configuration
git submodule update --remote    # Pulls the latest commit from the submodule
Enter fullscreen mode Exit fullscreen mode

As last step we have to acivate the theme in the hugo.yml

theme: ["PaperMod"]
Enter fullscreen mode Exit fullscreen mode

As the final step, let’s test our setup by starting Hugo.

hugo server -D
Enter fullscreen mode Exit fullscreen mode

You should now be able to access the site at http://localhost:1313.

4. Create the GitHub Action

Our workflow looks as follows:

  • actions/checkout - The first step checks out the Hugo site from the GitHub repository and also checks out the submodule where our theme is located.
  • lowply/build-hugo - The next step builds the Hugo site publish it to the public directory.
  • Dylan700/sftp-upload-action - In this step, we use SFTP to upload the contents of the public directory to the root directory (./).

Now that we have our workflow defined, it’s time to create the GitHub Action that will automate our process. For every push to the main branch, the site will be built and published via SFTP to the web server. The credentials, URL and PORT are stored as GitHub secrets. For more details see:

Our final workflow file .github/workflows/publish.yml looks as follows:

name: Build and Publish Hugo Site 
on:
  push:
    branches: 
      - main
jobs:
  build:
    name: Publish Hugo Site
    runs-on: ubuntu-latest
    steps:
    - name: Checkout Source (GIT)      
      uses: actions/checkout@v6.0.1
      with:
        submodules: true
    - name: Hugo Build     
      uses: lowply/build-hugo@v0.154.5
      with:
        # Hugo parameters like --buildDrafts, --baseURL, etc.
        # see https://gohugo.io/getting-started/usage/
        args: --minify
    - name: List files for debugging
      # For debugging list files from current directory to console
      run: ls
    - name: SFTP Upload      
      uses: Dylan700/sftp-upload-action@v1.2.3        
      with:
        server: ${{ secrets.FTP_SERVER }}
        username: ${{ secrets.FTP_USER }}
        password: ${{ secrets.FTP_PASSWORD }}
        port: ${{ secrets.FTP_PORT }}
        dry-run: false
        delete: true
        uploads: |
          ./public/ => ./
Enter fullscreen mode Exit fullscreen mode

Note:
It's also important that you enable submodules: true in the checkout action.

Running the Project Locally and Deploy

To make local development a bit more convenient, I added a simple Makefile. It wraps the most common Hugo commands so you don’t have to remember them or type them out every time.

# Makefile for Hugo

.PHONY: default clean serve

# Default target: clean and serve
default: clean serve

# Clean the project directory (delete public folder)
clean:
    @echo "Cleaning public/ directory..."
    rm -rf public

# Start Hugo server
# -D, --buildDrafts 
# -F, --buildFuture  
# -O, --openBrowser 
serve:
    @echo "Starting Hugo server..."
    hugo server -D -F -O
Enter fullscreen mode Exit fullscreen mode

To start the project locally, just run it, and then you should be able to access the page at http://localhost:1313/.

make
Enter fullscreen mode Exit fullscreen mode

As the last step, you should commit everything and push the changes. This should now trigger the whole workflow.

git add .
git commit -m "Ready to deploy"
git push
Enter fullscreen mode Exit fullscreen mode

I enjoyed experimenting with GitHub Actions while creating this post, and I hope you find some value in it as well.

Top comments (0)