BeingDevOps Website Setup (Multistage Tutorial)
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.md2.2 Initialize Hugo with Hextra
mkdir -p hugo-site && cd hugo-site
hugo mod init github.com/yourorg/siteAdd to hugo-site/go.mod:
require github.com/imfing/hextra v0.11.1Create hugo-site/config/_default/hugo.yaml:
baseURL: "https://yoursite.com/"
title: "Your Site"
module:
imports:
- path: github.com/imfing/hextra2.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.mdNext: 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-stopped3.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 -dOpen 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-website4.2 Taxonomies
In hugo.yaml:
taxonomies:
tag: tags
tools: toolsAdd 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— Logofooter.html— Footer contentsection-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 --minifyOutput 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]
| Option | Use case |
|---|---|
| Docker + Nginx | Self-hosted VPS |
| Kubernetes | Already on K8s |
| Netlify / Vercel | Zero-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
- BeingDevOps Website Setup Project — Full architecture
- Why DevOps Needs a Website — Rationale and approaches