Running a static page with Hugo and a Docker web server
I’ve been writing notes with Joplin in Markdown syntax for a long time. As IDE for PowerShell, I use VSCode - and I have to say, I absolutely love it. There’s something deeply satisfying about writing content in such a pure, basic form. It reminds me of the early days of web development, back when there were no Content Management Systems and we hand-crafted every single page. That’s probably why creating this website with Markdown and VSCode feels so natural to me - it combines modern tools with that wonderful simplicity of the early web.
Hugo fits perfectly into this approach. It’s a static website generator freely available under the Apache license. The web pages are written in Markdown, and Hugo takes care of generating the HTML pages. I transfer the pages in PowerShell to an Ubuntu VM, where a Lighttpd web server runs in a Docker container. Access to the Docker container is controlled by the reverse proxy Traefik, which also takes care of the website’s Lets Encrypt certificate.
Table of contents
Preparation
Creating a site
On windows 11, I use the Windows Terminal with Powershell 7. I assume a working HUGO installation.
We change the path to the Hugo root directory (which I place in ~/Documents) and create a new site:
cd .\Documents\_HUGO\
hugo new site blog.example.com
Hugo creates all necessary files of the new site in the path $env:USERPROFILE\Documents\_HUGO\blog.example.com
:
Congratulations! Your new Hugo site is created in $env:USERPROFILE\Documents\_HUGO\blog.example.com
Just a few more steps and you're ready to go:
1. Download a theme into the same-named folder.
Choose a theme from https://themes.gohugo.io/ or
create your own with the "hugo new theme <THEMENAME>" command.
2. Perhaps you want to add some content. You can add single files
with "hugo new <SECTIONNAME>\<FILENAME>.<FORMAT>".
3. Start the built-in live server via "hugo server".
Visit https://gohugo.io/ for quickstart guide and full documentation.
Installing a Hugo Theme
I use the theme m10c: https://themes.gohugo.io/themes/hugo-theme-m10c/
cd .\Dammmert.net\
git clone https://github.com/vaga/hugo-theme-m10c.git themes/m10c
The theme is defined in the configuration file config.toml
of the new Hugo site:
baseURL = "https://blog.example.com/"
title = "HomeLab & Selfhosting"
theme = "m10c"
paginate = 10
Test the website
In a new Windows Terminal tab, we start the Hugo-Live Server within the site folder:
cd .\Documents\_HUGO\blog.example.com
hugo server
The page can be accessed via the URL http://localhost:1313/. All changes to the files will be immediately visible on this website.
Create content
A new page is created with the following command:
hugo new posts/Hello-World.md
I then edit the page in VSCode:
Web server for external access
On an Ubuntu VM, I create a Docker container for the Lighhtpd web server:
ssh ubuntu-vm
mkdir web/blog.example.com
cd web/blog.example.com
touch docker-compose.yml
Further editing is done in VSCode. With the extension Remote - SSH I connect to the Ubuntu VM and open the file docker-compose.yml
.
In the YAML file the service lighttpd
is defined. I use the image rtsp/lighttpd
.
version: "3.3"
services:
lighttpd:
container_name: web-example.com
volumes:
- ./htdocs:/var/www/html:ro
image: rtsp/lighttpd
restart: unless-stopped
networks:
- proxy
labels:
## Enable Trafik
- "traefik.enable=true"
## Traefik Entry-Point HTTP
- "traefik.http.routers.web-example.com.entrypoints=http"
## Traefik Host-Rule
- "traefik.http.routers.web-example.com.rule=Host(`blog.example.com`)"
## Traefik Middleware Redirect HTTPS
- "traefik.http.middlewares.web-example.com-https-redirect.redirectscheme.scheme=https"
- "traefik.http.routers.web-example.com.middlewares=web-example.com-https-redirect"
## Traefik Entry-Point HTTPS
- "traefik.http.routers.web-example.com-secure.entrypoints=https"
## Traefik Host-Rule HTTPS
- "traefik.http.routers.web-example.com-secure.rule=Host(`blog.example.com`)"
## Traefik Enable TLS
- "traefik.http.routers.web-example.com-secure.tls=true"
## Traefik Service Definition
- "traefik.http.routers.web-example.com-secure.service=web-example.com"
## Traefik Load-Balancer
- "traefik.http.services.web-example.com.loadbalancer.server.port=80"
## Traefik Network
- "traefik.docker.network=proxy"
networks:
proxy:
external: true
The directory local directory ~/web/blog.example.com/htdocs
is mapped read-only into the Docker container with: ./htdocs:/var/www/html:ro
. So the static content from the Hugo installation just needs to be copied to this path.
The container is started:
sudo docker-compose up -d
Creating static web pages
To generate the HTML files of the web page, just execute HUGO in the site directory:
hugo
The files are placed in the subfolder public
.
Workflow: Updating the web page
After making changes to the website, the static content needs to be regenerated with Hugo and transferred to the Ubuntu server. For this I use a small Powershell function.
function Update-HugoWeb {
Set-Location "$env:USERPROFILE\Documents\_HUGO\blog.example.com"
& "C:\Program Files\hugo\hugo.exe"
$expression = "scp -r .\public\* $env:USERNAME@ubuntu-vm:/home/$env:USERNAME/lighttpd/htdocs"
Invoke-Expression $expression
}
The function is inserted into my Powershell Profile, so its available in all Powershell consoles: C:\Users\and\Documents\PowerShell\Microsoft.PowerShell_profile.ps1
.
Finally, to make changes to the web page, it is enough to save the change in the Markdown file (for example, with VSCode) and call the function in Powershell:
Update-HugoWeb