Adding Hugo to Your Technovangelist Homelab - Complete Guide
This comprehensive tutorial will walk you through adding Hugo to your existing technovangelist homelab setup. We’ll cover Docker configuration, Caddy reverse proxy setup, proper DNS configuration, and troubleshooting Safari iOS compatibility issues.
π Prerequisites
- Working technovangelist homelab setup
- Caddy reverse proxy running (usually as
caddy2
) - Domain name with Cloudflare DNS management
- SSH access to your server
- Basic understanding of Docker and Docker Compose
π― What You’ll Have After This Tutorial
- Hugo website running in Docker
- Proper DNS setup with A and CNAME records
- Safari iOS compatibility (important!)
- Secure HTTPS via Cloudflare Origin Certificates
- Easy content management workflow
π Step 1: Create Hugo Directory Structure
cd homelab
mkdir hugo
cd hugo
π³ Step 2: Create Docker Compose Configuration
Create the file docker-compose.yml
:
version: '3.8'
services:
hugo:
image: ghcr.io/gohugoio/hugo:latest
container_name: hugo
restart: unless-stopped
user: "${UID}:${GID}"
volumes:
- ./site:/src
working_dir: /src
command: server --bind 0.0.0.0 --port 1313 --baseURL ${HUGO_BASE_URL} --disableLiveReload --watch=false
environment:
- HUGO_ENV=production
networks:
- caddy2_default
networks:
caddy2_default:
external: true
Important: Adjust the network name (
caddy2_default
) to match your Caddy setup. Check withdocker network ls | grep caddy
.
π Step 3: Environment Configuration
Create the file example.env
:
HUGO_BASE_URL=https://yourdomain.com
UID=1001
GID=1001
Copy to your active configuration:
cp example.env .env
# Update with your actual values
echo "UID=$(id -u)" > .env
echo "GID=$(id -g)" >> .env
echo "HUGO_BASE_URL=https://yourdomain.com" >> .env
π Step 4: Initialize Hugo Site
# Initialize new Hugo site
docker run --rm -v $(pwd):/src -w /src --user $(id -u):$(id -g) --entrypoint hugo ghcr.io/gohugoio/hugo:latest new site site
# Verify site creation
ls -la site/
You should see Hugo’s basic directory structure including content/
, themes/
, hugo.toml
, etc.
π¨ Step 5: Install PaperMod Theme
cd site
# Initialize git repository
git init
# Add PaperMod theme as submodule
git submodule add --depth=1 https://github.com/adityatelange/hugo-PaperMod.git themes/PaperMod
git submodule update --init --recursive
# Return to hugo directory
cd ..
βοΈ Step 6: Configure Hugo
Edit the file site/hugo.toml
and replace the content:
baseURL = 'https://yourdomain.com'
languageCode = 'en'
title = 'Your Site Title'
theme = 'PaperMod'
enableRobotsTXT = true
buildDrafts = false
buildFuture = false
buildExpired = false
[params]
env = "production"
title = "Your Site Title"
description = "Your personal website and homelab"
author = "Your Name"
DateFormat = "January 2, 2006"
defaultTheme = "auto"
disableThemeToggle = false
ShowReadingTime = true
ShowShareButtons = true
ShowPostNavLinks = true
ShowBreadCrumbs = true
ShowCodeCopyButtons = true
ShowWordCount = true
UseHugoToc = true
disableSpecial1stPost = false
disableScrollToTop = false
comments = false
hidemeta = false
hideSummary = false
showtoc = false
tocopen = false
[params.homeInfoParams]
Title = "Welcome to Your Homelab"
Content = "Your personal website running on your homelab infrastructure"
[[params.socialIcons]]
name = "github"
url = "https://github.com/yourusername"
[menu]
[[menu.main]]
identifier = "home"
name = "Home"
url = "/"
weight = 10
[[menu.main]]
identifier = "posts"
name = "Posts"
url = "/posts/"
weight = 20
[[menu.main]]
identifier = "about"
name = "About"
url = "/about/"
weight = 30
π Step 7: Create Initial Content
Create Your First Post
# Create a new post
docker run --rm -v $(pwd)/site:/src -w /src --user $(id -u):$(id -g) --entrypoint hugo ghcr.io/gohugoio/hugo:latest new posts/homelab-setup.md
Edit site/content/posts/homelab-setup.md
:
---
title: "My Homelab Setup with Hugo"
date: 2025-06-26T12:00:00+02:00
draft: false
tags: ["hugo", "homelab", "self-hosting"]
categories: ["homelab"]
description: "How I set up Hugo on my technovangelist homelab"
---
# Welcome to My Homelab Website!
This website is running on my personal homelab infrastructure using:
## Tech Stack
- **Hugo** - Fast static site generator
- **PaperMod** - Clean and modern theme
- **Docker** - Containerized deployment
- **Caddy** - Automatic HTTPS and reverse proxy
- **Cloudflare** - DNS management and SSL
- **Tailscale** - Secure access to homelab
## Homelab Components
My homelab runs the technovangelist setup with:
- Docker Compose for service orchestration
- Caddy for automatic HTTPS and reverse proxy
- Tailscale VPN for secure external access
- Various self-hosted applications
## Why Self-Host?
Self-hosting gives me:
- **Control** over my data and services
- **Learning opportunities** with new technologies
- **Cost savings** compared to cloud services
- **Privacy** and security benefits
- **Fun!** Building and maintaining systems
## What's Next?
I'll be writing about:
- Homelab projects and experiments
- Docker and container management
- Self-hosting tutorials
- Infrastructure automation
- Privacy and security topics
Stay tuned for more content!
Create About Page
# Create about page
docker run --rm -v $(pwd)/site:/src -w /src --user $(id -u):$(id -g) --entrypoint hugo ghcr.io/gohugoio/hugo:latest new about.md
Edit site/content/about.md
:
---
title: "About"
date: 2025-06-26T12:00:00+02:00
draft: false
description: "About me and this website"
---
# About Me
Welcome to my personal website!
## Who Am I?
I'm a technology enthusiast passionate about self-hosting, privacy, and building efficient systems. This website runs on my own homelab infrastructure.
## My Interests
- **Homelab & Self-Hosting:** Running my own services and infrastructure
- **Privacy & Security:** Maintaining control over personal data
- **Open Source:** Contributing to and using open source software
- **Automation:** Making systems work efficiently with minimal intervention
- **Learning:** Constantly exploring new technologies and approaches
## This Website
This site is powered by:
- **Hugo** for fast, static content generation
- **Docker** for reliable, reproducible deployments
- **Caddy** for automatic HTTPS and reverse proxy
- **Cloudflare** for DNS management and edge security
- **Tailscale** for secure access to my homelab
The entire setup follows the technovangelist homelab approach, emphasizing simplicity and reliability.
## Get In Touch
- **Email:** [[email protected]]
- **GitHub:** [github.com/yourusername]
- **Mastodon:** [@[email protected]]
## Homelab Services
Other services running on my homelab:
- **n8n:** Workflow automation
- **Various other self-hosted applications**
---
*This website is built with Hugo and the PaperMod theme, deployed via Docker on my homelab infrastructure.*
π§ͺ Step 8: Test Hugo Locally
# Start Hugo development server
docker compose up
Test your website locally:
- Direct:
http://[server-ip]:1313
- Via Tailscale: Access your server IP on port 1313
You should see your Hugo website with the PaperMod theme and your content!
π Step 9: DNS Configuration (Critical!)
This is the most important step for Safari iOS compatibility.
In Cloudflare Dashboard β DNS β Records:
Create these DNS records:
-
Root Domain (A Record):
- Type: A
- Name:
@
- IPv4 address:
[your-server-ip]
- Proxy status: π Proxied (orange cloud ON)
- TTL: Auto
-
WWW Subdomain (CNAME):
- Type: CNAME
- Name:
www
- Target:
yourdomain.com
- Proxy status: π Proxied (orange cloud ON)
- TTL: Auto
-
Other Subdomains (CNAME):
- Type: CNAME
- Name:
n8n
(or other services) - Target:
yourdomain.com
- Proxy status: π Proxied (orange cloud ON)
- TTL: Auto
Find Your Server IP:
# On your server
curl ifconfig.me
π§ Step 10: Caddy Configuration
Navigate to your Caddy directory and edit the Caddyfile
:
cd ../caddy # or ../caddy2
nano Caddyfile
Add Hugo configuration:
# Hugo website on both root and www domains
yourdomain.com {
tls /etc/caddy/certs/yourdomain.com.crt /etc/caddy/certs/yourdomain.com.key
reverse_proxy hugo:1313
}
www.yourdomain.com {
tls /etc/caddy/certs/yourdomain.com.crt /etc/caddy/certs/yourdomain.com.key
reverse_proxy hugo:1313
}
# Existing services remain
n8n.yourdomain.com {
tls /etc/caddy/certs/yourdomain.com.crt /etc/caddy/certs/yourdomain.com.key
reverse_proxy n8n:5678
}
Note: Adjust certificate paths and service names according to your existing setup.
βοΈ Step 11: Cloudflare SSL/TLS Settings
Configure optimal SSL settings in Cloudflare Dashboard:
SSL/TLS β Overview:
- Encryption mode: Full (strict) β
SSL/TLS β Edge Certificates:
- Always Use HTTPS: ON β
- HTTP Strict Transport Security (HSTS): OFF (initially)
- Minimum TLS Version: TLS 1.2 β
- Opportunistic Encryption: ON β
- TLS 1.3: ON β
π Step 12: Deploy to Production
# Stop local testing
cd ../hugo
docker compose down
# Start in production mode
docker compose up -d
# Restart Caddy to load new configuration
cd ../caddy
docker compose restart
β Step 13: Testing and Verification
Test Both Domains:
# Test root domain
curl https://yourdomain.com
# Test www subdomain
curl https://www.yourdomain.com
# Both should return your Hugo website HTML
Test All Browsers:
- Desktop browsers: Chrome, Firefox, Safari, Edge
- Mobile browsers: Especially Safari iOS (critical!)
- Different devices: iPhone, Android, tablet
π± Safari iOS Compatibility (Important!)
Critical Issue: Safari iOS may show a white screen on the root domain (yourdomain.com
) while working fine on the www subdomain (www.yourdomain.com
).
Solution: Both domains are configured in Caddy, so users can access either:
https://yourdomain.com
(works on most browsers)https://www.yourdomain.com
(works on all browsers including Safari iOS)
π Daily Content Management
Creating New Posts:
cd homelab/hugo/site
docker run --rm -v $(pwd):/src -w /src --user $(id -u):$(id -g) --entrypoint hugo ghcr.io/gohugoio/hugo:latest new posts/my-new-post.md
Managing the Hugo Container:
cd homelab/hugo
# View logs
docker compose logs -f
# Restart
docker compose restart
# Stop
docker compose down
# Start
docker compose up -d
Content Updates:
Hugo automatically detects changes in the site/
directory and reloads the website. No manual rebuilds needed!
π οΈ Troubleshooting
Website Not Accessible
Check container status:
docker ps | grep hugo
docker ps | grep caddy
Check logs:
docker compose logs hugo
docker compose logs caddy
Test connectivity:
# Test if Caddy can reach Hugo
docker exec caddy ping hugo
# Test Hugo directly
docker run --rm --network caddy2_default alpine/curl curl http://hugo:1313
Permission Errors
# Fix ownership
sudo chown -R $USER:$USER site/
# Update UID/GID in .env
echo "UID=$(id -u)" > .env
echo "GID=$(id -g)" >> .env
Theme Not Loading
# Check theme directory
ls -la site/themes/PaperMod/
# Reinstall theme if needed
cd site
git submodule update --init --recursive
Safari iOS White Screen
This is the most common issue!
Symptoms:
- Website works on desktop browsers
- Website works on Chrome/Firefox mobile
- Safari iOS shows white screen
Solution:
- Use
https://www.yourdomain.com
instead ofhttps://yourdomain.com
- Both URLs are configured and work
- This is a known Safari iOS quirk with certain SSL configurations
Testing:
- Test on actual iOS device with Safari
- Try both root domain and www subdomain
- Clear Safari cache if needed
Network Connection Issues
# Check Docker networks
docker network ls
# Verify Hugo is on correct network
docker inspect hugo | grep -A 10 Networks
# Test network connectivity
docker run --rm --network caddy2_default alpine/curl curl http://hugo:1313
DNS Issues
Check DNS propagation:
# Check if DNS has propagated
dig yourdomain.com
dig www.yourdomain.com
# Check from different locations
nslookup yourdomain.com 8.8.8.8
Cloudflare settings:
- Ensure proxy status is ON (orange cloud)
- Check for conflicting Page Rules
- Verify SSL mode is “Full (strict)”
Hugo Content Issues
Check content directory:
ls -la site/content/
ls -la site/content/posts/
Verify Hugo configuration:
cat site/hugo.toml | grep baseURL
Test Hugo directly:
docker exec hugo hugo version
docker exec hugo ls -la /src/content/
π― Advanced Configuration
Custom CSS
Add custom styling by creating files in site/assets/css/
:
mkdir -p site/assets/css
cat > site/assets/css/extended.css << 'EOF'
/* Custom styles for your site */
.custom-header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 20px;
border-radius: 8px;
}
EOF
Performance Optimization
Enable minification in Hugo config:
[minify]
disableXML = true
minifyOutput = true
[markup]
[markup.goldmark]
[markup.goldmark.renderer]
unsafe = true
Backup Strategy
Regular backups of your site content:
# Simple backup
tar -czf hugo-backup-$(date +%Y%m%d).tar.gz site/
# With git (recommended)
cd site
git add .
git commit -m "Content update $(date)"
git push origin main
Automated Deployments
For advanced setups, consider:
- GitHub Actions for automated builds
- Webhooks for content updates
- CI/CD pipelines for testing
π Security Considerations
Current Security Layers:
- Tailscale VPN - Primary access control
- Cloudflare Proxy - DDoS protection and edge security
- Full SSL/TLS - End-to-end encryption
- Container Isolation - Hugo runs in isolated container
- No Exposed Ports - Hugo only accessible via Caddy
Additional Security:
- Regular Hugo updates via container image updates
- Monitor Cloudflare security events
- Keep Caddy and Docker updated
- Regular backup testing
π Performance and Scaling
Current Setup Benefits:
- Fast Loading - Hugo generates static files
- CDN Integration - Cloudflare edge caching
- Efficient Resource Usage - Minimal server requirements
- High Availability - Container restart policies
Scaling Options:
- Multi-server deployment with load balancing
- CDN optimization with Cloudflare Workers
- Database integration for dynamic content
- Search functionality with client-side search
π Conclusion
You now have a fully functional Hugo website integrated into your homelab! This setup provides:
- β Professional Website - Fast, secure, and reliable
- β Safari iOS Compatible - Works on all browsers and devices
- β Easy Management - Simple content creation workflow
- β Secure Access - Protected by Tailscale and Cloudflare
- β Scalable Architecture - Easy to expand and modify
- β Modern Stack - Docker, Caddy, Hugo, and Cloudflare
Key Lessons Learned:
- DNS Configuration is Critical - Proper A and CNAME records prevent many issues
- Safari iOS Compatibility - www subdomain works better than root domain
- Network Configuration - Ensure containers can communicate
- Security Layers - Multiple levels of protection work together
Next Steps:
- Write more content and build your audience
- Explore Hugo’s advanced features
- Add more homelab services
- Share your homelab journey with the community
Happy blogging and enjoy your new homelab website! π
This tutorial was tested with the technovangelist homelab setup. Adjust commands and configurations according to your specific environment.
Troubleshooting Quick Reference:
Issue | Solution |
---|---|
Safari iOS white screen | Use www.yourdomain.com instead |
Hugo not accessible | Check Docker networks and container status |
DNS not resolving | Verify Cloudflare proxy settings |
SSL certificate errors | Check Cloudflare SSL mode (Full strict) |
Permission denied | Fix file ownership and UID/GID |
Theme not loading | Reinstall git submodules |
Container won’t start | Check logs and volume mounts |
For additional help, consult the Hugo documentation, Caddy documentation, or the technovangelist community.