a blog with hugo, served with a docker nginx behind traefik

i had a vps for some time now, with various things hosted (nextcloud, vaultwarden, elabftw, …) and reverse proxie’d with traefik. my usecase for a reverse proxy was to host multiple websites (all on port 443) on a single IP. traefik gets all the https requests, looks at what url is tried, and routes the traffic to the appropriate docker container.

i hosted multiple subdomains (e.g. subdomain.f31.eu), but it bothered me that f31.eu was empty. i knew i wanted a simple site, maybe also a blogging functionality, but i couldn’t decide on a cms. all i knew is, i didn’t want wordpress.

hugo to the rescue

yesterday i stumbled across erik espinoza’s article on selfhosting with CGNAT and really liked the idea, but also the simple, clean site. the site’s signature gave me the name to the cms used: hugo.

hugo is a static site generator - it takes simple input, and generates it into a nice html page, with links to other articles, a consistant theme and so on. static sites are really fast. i host a wordpress site (without fpm) that takes ~3500ms to load. this site loads in ~135ms (and the used vps is certainly not stronger!).

setup trouble

so i wanted to integrate hugo as my blog-system to finally fill f31.eu with some content. but reading the docs didnt answer a lot of my questions. i wanted to host the system in a docker container, but an official image wasn’t avaliable. i tried (and failed) setting up one of the community images - the documentation on these didn’t help me out much either.

the working setup

i now have the following:

  ______________                      -------------------
  |            | ---- nc.f31.eu ---> |    nextcloud    |
  80           |                     -------------------
  |   traefik  |                     ___________________           
 443           | ----- f31.eu -----> |      nginx      | ----> /home/daniel/blog/public/  (on the vps)
  |            |                     -------------------         
  --------------                                       

post 80 and 443 of the vps’s public IP is used by traefik. if traffic for f31.eu comes in, it’s redirectet to a nginx container, which servers up content from a directory on my vps.

hugo comes into this one step before:

/home/daniel
|-- apps
|-- blog   <-- this one
|-- downloads
|-- logs
|-- pers
baseURL = 'https://f31.eu/'
languageCode = 'en-us'
title = 'daniel fuchs blog'
theme = "harbor"
services:
 hugonginx:
  image: jojomi/nginx-static
  container_name: hugo-nginx
  volumes:
    - ./output:/var/www
  environment:
    - VIRTUAL_HOST=f31.eu
  restart: always
  labels:
    - "traefik.enable=true"
    - "traefik.http.middlewares.hugo-https.redirectscheme.scheme=https"
    - "traefik.http.routers.hugo-http.entrypoints=web"
    - "traefik.http.routers.hugo-http.rule=Host(`f31.eu`)" #Domain anpassen
    - "traefik.http.routers.hugo-http.middlewares=hugo-https@docker"
    - "traefik.http.routers.hugo.entrypoints=web-secure"
    - "traefik.http.routers.hugo.rule=Host(`f31.eu`)" #Domain anpassen
    - "traefik.http.routers.hugo.tls=true"
    - "traefik.http.routers.hugo.tls.certresolver=default"
    - "traefik.http.routers.hugo.middlewares=secHeaders@file"
    - "traefik.http.services.hugo.loadbalancer.server.port=80"
  networks:
    - traefik_proxy0
networks:
traefik_proxy0:
  external:
    name: traefik_proxy0 

surely there is plenty more to optimize, but i’m happy with it at the moment. TODO:

writing my first post

right now i’m ssh daniel@f31.eu. i created a new blog entry with hugo new content/hugo-with-docker-and-traefik.md and started editing with vim. after i’m done editing i’ll set the draft: true at the top of this .md file to false and run sudo hugo again. if you are reading this, it means it has worked :-)

edit

at first the post wasn’t visable on the front page. i took some of the config from the harbor github page, but still no luck.

the solution was looking in the docs: i created a folder unter blog/content for a category, e.g. blog/content/computers and put the .md file in there. and suddenly it worked.

but now it is visable in any of the filters (set up by the theme)… might want to fix that at some point.