Skip to content

BeingDevOps Website Setup (Multistage Tutorial)

February 14, 2025
Published: 2025-02-14 00:00 UTC

This multistage tutorial walks you through building the BeingDevOps website from scratch: stack selection, Docker dev setup, content structure, theme customization, and production considerations. Each stage is self-contained but builds on the previous.

Stack Overview

    flowchart LR
    subgraph Stack
        A[Hugo] --> B[Hextra]
        B --> C[HTML/CSS/JS]
        C --> D[Traefik]
        D --> E[Docker]
    end
    F[Markdown] --> A
    E --> G[Browser]
  

Stage 1: Choose the Stack

Goal: Decide on static site generator, theme, and runtime.

1.1 Why Hugo?

  • Single binary, no Node/Python runtime
  • Fast builds (Go)
  • Markdown + front matter
  • Module system for themes
  • Excellent docs

1.2 Why Hextra?

  • Documentation-focused
  • FlexSearch (client-side search)
  • Mermaid diagrams
  • Dark mode
  • Responsive sidebar

1.3 Why Docker + Traefik?

  • Reproducible dev environment
  • No “works on my machine”
  • Traefik discovers containers via labels—no manual Nginx config

Next: Stage 2


Stage 2: Project Structure and Initial Setup

Goal: Create the folder structure and bootstrap Hugo.

2.1 Directory Layout

your-project/
├── docker/
│   ├── docker-compose.yml
│   ├── Dockerfile
│   ├── Dockerfile.prod
│   ├── traefik-dynamic.yml
│   ├── generate-certs.sh
│   └── certs/
├── hugo-site/
│   ├── config/_default/hugo.yaml
│   ├── content/
│   │   ├── blog/
│   │   ├── projects/
│   │   ├── tutorials/
│   │   └── about/
│   ├── layouts/
│   ├── assets/
│   └── static/
└── README.md

2.2 Initialize Hugo with Hextra

mkdir -p hugo-site && cd hugo-site
hugo mod init github.com/yourorg/site

Add to hugo-site/go.mod:

require github.com/imfing/hextra v0.11.1

Create hugo-site/config/_default/hugo.yaml:

baseURL: "https://yoursite.com/"
title: "Your Site"
module:
  imports:
    - path: github.com/imfing/hextra

2.3 Content Structure

Create section indexes:

mkdir -p content/{blog,projects,tutorials,about}
touch content/blog/_index.md content/projects/_index.md content/tutorials/_index.md content/about/_index.md

Next: Stage 3


Stage 3: Docker Dev Environment

Goal: Run Hugo and Traefik via Docker Compose with HTTPS.

3.1 Architecture

    flowchart TB
    subgraph Docker
        T[Traefik :80/:443]
        H[Hugo :1313]
    end
    Client[Browser] --> T
    T -->|TLS| H
    H --> Static[HTML]
  

3.2 Dockerfile

Create docker/Dockerfile:

FROM ghcr.io/gohugoio/hugo:latest
WORKDIR /src
ENV HUGO_CACHEDIR=/tmp/hugo_cache
CMD ["server", "--bind", "0.0.0.0"]

3.3 Docker Compose

Create docker/docker-compose.yml:

services:
  hugo:
    build:
      context: ..
      dockerfile: docker/Dockerfile
    volumes:
      - ../hugo-site:/src
    working_dir: /src
    command: ["hugo", "mod", "get", "&&", "hugo", "server", "--bind", "0.0.0.0"]
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.hugo.rule=Host(`localhost`)"
      - "traefik.http.services.hugo.loadbalancer.server.port=1313"
    restart: unless-stopped

  traefik:
    image: traefik:v3.2
    command:
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    restart: unless-stopped

3.4 Self-Signed Certs (Optional)

Create docker/generate-certs.sh:

#!/bin/bash
mkdir -p certs && cd certs
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout localhost.key -out localhost.crt \
  -subj "/CN=localhost"

Then add TLS config in traefik-dynamic.yml and mount certs in Traefik.

3.5 Run

cd docker
docker compose up -d

Open http://localhost (or https://localhost with certs).

Next: Stage 4


Stage 4: Content and Layout Customization

Goal: Add blog posts, projects, tutorials, and custom layouts.

4.1 Front Matter and Related Content

Use related_projects, related_tutorials, related_blogs in front matter:

related_projects:
  - /projects/beingdevops-website-setup
related_tutorials:
  - /tutorials/linux/webservers/beingdevops-website-setup
related_blogs:
  - /blog/why-devops-needs-a-website

4.2 Taxonomies

In hugo.yaml:

taxonomies:
  tag: tags
  tools: tools

Add tags and tools to content front matter.

4.3 Mermaid Diagrams

Hextra supports Mermaid in fenced code blocks:

```mermaid
flowchart LR
  A[Hugo] --> B[Traefik]
  B --> C[Browser]
```

4.4 Custom Layouts

Override theme partials in layouts/partials/:

  • navbar-title.html — Logo
  • footer.html — Footer content
  • section-cards.html — Card grid for list pages

Next: Stage 5


Stage 5: Production and Deployment

Goal: Build static output and deploy.

5.1 Build Static Site

cd hugo-site
hugo mod get
hugo --minify

Output in hugo-site/public/.

5.2 Production Dockerfile

Create docker/Dockerfile.prod:

FROM nginx:alpine
COPY hugo-site/public /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

5.3 Deployment Options

    flowchart TD
    Build[hugo --minify] --> A{Deploy target?}
    A -->|Docker| B[nginx container]
    A -->|K8s| C[IngressRoute]
    A -->|Cloud| D[S3 / Netlify / Vercel]
  
OptionUse case
Docker + NginxSelf-hosted VPS
KubernetesAlready on K8s
Netlify / VercelZero-ops, free tier

Summary Diagram

    flowchart TB
    subgraph Input
        MD[Markdown]
        FM[Front Matter]
    end

    subgraph Hugo
        Build[Hugo Build]
        Theme[Hextra]
        MD --> Build
        FM --> Build
        Theme --> Build
    end

    subgraph Output
        HTML[Static HTML]
    end

    Build --> HTML
    HTML --> Traefik
    Traefik --> User[User]
  

Related Content