4 minutes
My website setup
Intro
This is a first small technical writeup on how I managed to setup this website. I’m a system engineer with only a little knowledge about web frontend design using HTML / CSS / JS, but I still wanted something that didn’t look like a website from 1992… That’s why I chose to make use of a static site generator!
There are a couple out there that can be used but I opted for Hugo. This is an open source framework written in GO that converts Markdown files into HTML & CSS code.
Before starting this setup, I already had automation in mind. I wanted to create a git repository that would contain all needed files and would check & rebuilt the site whenever I add a new post or make a change. I made use of my selfhosted Gitlab server to host the repository and created a CI/CD job to check and built the website on every new push.
These files will then be used by a nginx docker container that will host the website.
Starting off
The site has to be created using the hugo new site x
command. Moving into the newly created directory shows that the hugo site structure has been created!
hugo new site hugo-website
cd hugo-website
tree
.
├── archetypes
│ └── default.md
├── assets
├── config.toml
├── content
├── data
├── layouts
├── public
├── static
└── themes
Once inside the new directory I created a new repository and pushed it to my Gitlab server.
git init
git add .
git commit -m "initial commit"
git push --set-upstream http://{gitlab_IP}/{gitlab_namespace}/hugo-website master
Next up is adding a theme to the website. There are many to choose from here. The one I’m using is hello-friend-ng created by rhazdon.
git submodule add https://github.com/rhazdon/hugo-theme-hello-friend-ng.git themes/hello-friend-ng
CI/CD
The pipeline in my project creates the hugo website and uses rsync
to ship it to the server where my nginx container is running. To use rsync
within the pipeline we need to make use of SSH-keys which we will add as a variable.
A variable can be defined in the CI/CD section of the repository in the Gitlab GUI.
Here I created 3 variables which I will use in my CI file.
- HUGO_SERVER
- HUGO_USER
- RSYNC_PRIVATE_KEY
CI file
By creating a .gitlab-ci.yml
file inside the repository, the project can make use of a runner that triggers the CI pipeline on every push.
variables:
GIT_SUBMODULE_STRATEGY: recursive
stages:
- Build
- Deploy
build:
stage: Build
image: registry.gitlab.com/pages/hugo:latest
script:
# Build the website
- hugo
artifacts:
paths:
- ./public
deploy:
stage: Deploy
image: alpine:latest
needs:
- job: build
artifacts: true
before_script:
# SSH client for rsync
- apk add rsync openssh-client
# Add the key
- mkdir -p ~/.ssh
- echo "$RSYNC_PRIVATE_KEY" > ~/.ssh/key
- echo "StrictHostKeyChecking no" >> ~/.ssh/config
- chmod -R 700 ~/.ssh
- eval "$(ssh-agent -s)"
- ssh-add ~/.ssh/key
script:
# Sync the built site
- rsync -crtvz --delete ./public/ "$HUGO_USER"@"$HUGO_SERVER":~/webserver/public
only: # Only run on main branch
variables:
- $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
Now the every new push in the repository will trigger a 2 step pipeline which will build & deploy the website.
-
Build
- Use the hugo docker image to create the website
- Save the
public/
folder in artifacts (this will carry over to the next step)
-
Deploy
- Collect artifacts
- Use the alpine docker image
- Add needed SSH client
- Create needed SSH files + get private key from variable
- Use
rsync
to copy overpublic/
folder to remote host
Serve content using nginx
After the CI/CD was in a working state, the website was ready to be started. Hugo itself can serve the website but I wanted to divide the creation and the serving of the content.
This could be really easily done by utilizing a nginx docker container and using the public/
directory as the content. I quickly made a docker-compose file which would do just that!
---
version: '3'
services:
nginx:
image: nginx:latest
container_name: nginx
ports:
- 80:80
volumes:
- ~/webserver/public:/usr/share/nginx/html
restart: unless-stopped
Ready!
This was pretty much it.
By making a new push to my main repository it will trigger a CI job which will update my site with the new changes!