In order to run a hugo webserver you will need a few things in order first. I will mention the requirements; however, I will not be going into detail here.
If you would like me to write a post on these pre-requisites. Please let me know in the comments!
Pre-Requisites
Service | Provider |
---|---|
Virtual Private Server | Vultr |
Domain Name Registrar | Epik |
DNS | Cloudflare |
Git | GitHub |
Domain, VPS, and nginx Configuration
Setup your A Record to point your domain name to your webserver
type | name | content |
---|---|---|
A | @ | vps_ipv4_address |
Create simple nginx configuration file, /etc/nginx/conf.d/.conf
server {
server_name <domain-name> www.<domain-name>;
root /var/www/<domain-name>/public;
index index.html;
location / {
try_files $uri $uri/ =404;
add_header Permissions-Policy interest-cohort=();
}
listen 80;
listen [::]:80;
return 404;
}
Create a temporary index.html in your website’s root directory, /var/www//public/index.html
<html>
<p><domain></p>
</html>
Start and Enable nginx
systemctl enable --now nginx.service
If necessary, allow HTTP and HTTPS through firewall
firewall-cmd --add-service=http --permanent
firewall-cmd --add-service=https --permanent
firewall-cmd reload
You should be able to verify access to your webserver over port 80 at this point.
After a successful verification you can continue finishing the configuration.
SSL with acme.sh
For SSL you can find all Let’s Encrypt client options here
I recommend acme.sh
Install acme.sh
Issue cert for your domain
acme.sh --issue -d <domain> -w /var/lib/nginx/<domain>
Install certificate to an nginx directory
acme.sh --install-cert -d <domain> \
--key-file /etc/nginx/<domain>/key.pem \
--fullchain-file /etc/nginx/<domain>/cert.pem \
--reloadcmd "service nginx force-reload"
acme registers a cron job to run daily. This will ensure your certificate is always valid and will restart your webserver.
Create Hugo Website
Locate a Hugo theme you’d like to use
I’m using PaperMod
PaperMod installation instructions are here
Once you have followed the installation instructions for your theme you can begin customizing your site.
Again, each theme has their own configuration options; however, I’ll explain the general layout of the hugo folder structure to help you understand where to go.
Ensure you are inside the websites directory.
cd ~/Projects/davidspencer.xyz
tree -L 1 .
.
├── archetypes
├── config.yml
├── content
├── layouts
├── resources
├── static
└── themes
Most of the configuration will be done in the config.yml file You can see my exact configuration at my repo
baseURL: https://davidspencer.xyz
languageCode: en-us
title: Title of Website
theme: Theme Name
env: production
outputs:
home:
- HTML
- RSS
- JSON
params:
assets:
disableHLJS: true
disableFingerprinting: false
favicon: "/favicon.ico>"
favicon16x16: "/favicon-16x16.png"
favicon32x32: "/favicon-32x32.png"
apple_touch_icon: "/apple-touch-icon.png"
safari_pinned_tab: "/safari-pinned-tab.svg"
socialIcons:
- name: "linkedin"
url: "https://www.linkedin.com/in/davidjspencer/"
- name: "github"
url: "https://github.com/Elevate08"
- name: "email"
url: "mailto:david@davidspencer.xyz"
- name: "rss"
url: "/index.xml"
editPost:
URL: "https://github.com/Elevate08/davidspencer.xyz/blob/master/content"
Text: "Suggest Changes" # edit text
appendFilePath: true # to append file path to Edit link
fuseOpts:
minMatchCharLength: 3
keys: ["title", "content", "summary"]
menu:
main:
- identifier: tags
name: tags
url: /tags/
weight: 20
- identifier: search
name: search
url: /search/
weight: 30
markup:
highlight:
codeFences: true
guessSyntax: false
style: native
tabWidth: 4
Once you have some settings in place for your site you can create a new post.
hugo new posts/first-post.md
Using your editor of choice, write up your first post using Markdown.
You can learn about Markdown here Markdown Guide
Once you have some content created run the following command
hugo server
Watching for config changes in /home/elevate/Projects/davidspencer.xyz/config.yml
Environment: "development"
Serving pages from memory
Running in Fast Render Mode. For full rebuilds on change: hugo server --disableFastRender
Web Server is available at http://localhost:1313/ (bind address 127.0.0.1)
You should now be able to access your hugo website at the location provided.
This is how most development / testing of new content can be done.
Click around and test out your new site.
Deploying Hugo Website using GitHub Actions
Up until now we have just been working locally. You should have a working development environment where you can access your site locally.
To make deployment to your VPS easier and allow you to focus on just creating new content, let’s setup some GitHub Actions to do some work for us!
cd ~/Projects/davidspencer.xyz
git init
Usually at this point I’d run git add .
; however, you most likely need to configure the git submodule for your theme.
We want to be able to pull a fresh version from the repo every time we deploy.
You should be able to run the following command without error.
git submodule add <theme clone url>
If you do run into an error let me know in the comments and I’ll help you troubleshoot.
Once the theme repo is properly added as a submodule we can continue.
At this time you should login to GitHub and create a new repo. Grab the clone URL.
git add .
git commit -m "initial upload"
git remote add origin git@github.com:/Elevate08/davidspencer.xyz
git push -u origin master
Now to make our github action file, we will need to create a couple directories.
mkdir -p .github/workflows
touch .github/workflows/main.yml
Add the following text to your main.yml file
name: Hugo to VPS
on:
push:
branches:
- master # Set a branch to deploy
pull_request:
jobs:
deploy:
runs-on: ubuntu-20.04
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: 'latest'
# extended: true
- name: Build
run: hugo --minify
- name: Deploy
uses: appleboy/scp-action@master
with:
host: ${{ secrets.HOST }}
port: ${{ secrets.PORT }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
source: "./public"
target: "/var/www/davidspencer.xyz"
In my workflow, i’m using scp-action to copy the generated website files to my server.
This means we’ll need to create some secrets on our repo.
In your repository on GitHub create the following secrets Settings > Secrets > New repository secret
- HOST
- KEY
- PORT
- USERNAME
I’ll assume you have knowledge on SSH and what the secrets should contain.
I’d encourage you to generate a unique key pair and user for this action.
cd ~/Projects/davidspencer.xyz
git add .
git commit -m "adding github action for automated deployments"
git push
You can now watch the action run on GitHub and monitor your VPS for the website files to be copied over.