Skip to content

Build a MkDocs Site with Terraform and S3

Find the latest code for this project on my GitHub

Tired of paying \(50-200+ per month for WordPress hosting?** What if I told you that you could host a beautiful, fast, professional website for literally **\)3 per month?

Chances are you have seen a website or documentation that make use of MkDocs, and especially Material for MkDocs. In fact, this blog site runs using Material for MkDocs and I have to say it is a delight compared to typical blog or WordPress platforms!

This becomes really powerful - and incredibly cost-effective - combined with the ability to host a static website using Amazon S3.

The WordPress Hosting Trap

Let's be honest about traditional website hosting costs:

Traditional WordPress Hosting Costs

  • Shared Hosting: $10-25/month (slow, limited resources)
  • Managed WordPress: $30-100/month (better, but expensive)
  • VPS/Cloud: $50-200+/month (performant, but complex)
  • Enterprise: $200-500+/month (feature-rich, but $$$)

Hidden WordPress Costs

Plugin Licenses: $50-200+/year for premium plugins ❌ Theme Licenses: $50-100+/year for professional themes ❌ Security Services: $100-300+/year for proper security ❌ Backup Services: $50-150+/year for reliable backups ❌ CDN Services: $20-100+/month for global performance ❌ Maintenance Time: Hours per month managing updates, security, performance

Total Annual Cost: $1,500 - $4,000+ for a professional WordPress site

The MkDocs + S3 Alternative

Now let's look at the MkDocs + S3 approach:

S3 Static Website Hosting Costs

  • S3 Storage: ~$0.023/GB/month (most sites under 1GB)
  • S3 Requests: ~$0.0004 per 1,000 requests
  • Data Transfer: First 1GB free/month, then ~$0.09/GB
  • Route 53 DNS: $0.50/month per hosted zone

Real-World Cost Example

For a typical documentation/blog site with: - 500 pages (~200MB of content) - 10,000 page views/month - 5GB data transfer/month

Monthly S3 Costs: - Storage: $0.005 - Requests: $0.004 - Transfer: $0.36 - DNS: \(0.50 - **Total: ~\)0.87/month**

Add CloudFront CDN for global performance: +$1-2/month

Total Annual Cost: $24-36 vs $1,500-4,000 for WordPress!

Why MkDocs + S3 is Better Than WordPress

Performance Advantages

Lightning Fast: Static files serve in milliseconds ✅ Global CDN Ready: Perfect integration with CloudFront ✅ Zero Server Overhead: No PHP, no database queries ✅ Instant Loading: No plugins or themes to slow things down ✅ Mobile Optimized: Material theme is mobile-first

Security Benefits

No Attack Surface: Static files can't be hacked ✅ No Database: No SQL injection possibilities ✅ No PHP Vulnerabilities: No server-side code to exploit ✅ AWS Security: Built on enterprise-grade infrastructure ✅ Version Control: Your content is stored in Git

Developer Experience

Markdown Writing: Write in simple, portable Markdown ✅ Version Control: Full Git history of all changes ✅ Local Development: Preview changes instantly ✅ Automated Deployment: CI/CD pipeline integration ✅ No Maintenance: No updates, patches, or security concerns

Content Management

Portable Content: Markdown files work anywhere ✅ Fast Search: Built-in search without database overhead ✅ Beautiful Themes: Professional appearance out of the box ✅ Extensible: Python plugins for advanced features ✅ SEO Friendly: Clean URLs and fast loading for better rankings

Setting Up Your $3/Month Website

Let's build a professional website that costs less than a coffee per month:

Prerequisites

  • AWS Account (free tier eligible)
  • Basic familiarity with command line
  • Text editor (VS Code, etc.)
  • Git for version control

Project Structure

my-awesome-site/
├── docs/
│ ├── index.md
│ ├── about.md
│ └── blog/
│ ├── index.md
│ └── posts/
├── mkdocs.yml
├── requirements.txt
└── deploy.sh

Step 1: Install MkDocs and Material Theme

# Create and activate virtual environment
python -m venv venv
source venv/bin/activate # Linux/Mac
# venv\Scripts\activate # Windows

# Install MkDocs and Material theme
pip install mkdocs mkdocs-material

# Save dependencies
pip freeze > requirements.txt

Step 2: Create Your MkDocs Configuration

# mkdocs.yml
site_name: My Awesome Website
site_url: https://myawesomesite.com
site_author: Your Name
site_description: Professional website for $3/month

theme:
 name: material
 palette:
 # Light mode
 - scheme: default
 primary: indigo
 accent: indigo
 toggle:
 icon: material/brightness-7
 name: Switch to dark mode
 # Dark mode
 - scheme: slate
 primary: indigo
 accent: indigo
 toggle:
 icon: material/brightness-4
 name: Switch to light mode

 features:
 - navigation.tabs
 - navigation.sections
 - navigation.expand
 - navigation.top
 - search.highlight
 - search.share
 - content.code.copy

plugins:
 - search
 - blog:
 blog_dir: blog
 post_date_format: long
 post_url_format: "{slug}"

markdown_extensions:
 - pymdownx.highlight:
 anchor_linenums: true
 - pymdownx.inlinehilite
 - pymdownx.snippets
 - pymdownx.superfences
 - admonition
 - pymdownx.details

nav:
 - Home: index.md
 - About: about.md
 - Blog: blog/index.md

extra:
 social:
 - icon: fontawesome/brands/twitter
 link: https://twitter.com/yourusername
 - icon: fontawesome/brands/linkedin
 link: https://linkedin.com/in/yourusername

Step 3: Create Your Content

<!-- docs/index.md -->
# Welcome to My Awesome Website

This professional website costs me only **$3 per month** to host on AWS S3!

## Why This Approach is Better

- **💰 Ultra Low Cost**: $3/month vs $50-200/month
- **⚡ Lightning Fast**: Static files load instantly
- **🔒 Ultra Secure**: No server vulnerabilities
- **📱 Mobile First**: Beautiful on all devices
- **🚀 Easy Updates**: Write in Markdown, deploy with Git

## Features

!!! tip "Professional Features for Free"
    - Responsive design
    - Dark/light mode toggle
    - Full-text search
    - Blog functionality
    - Social media integration
    - SEO optimization

    [Learn more about this setup →](about.md)
    ```

```markdown
<!-- docs/about.md -->
# About This Site

This website demonstrates how to create a **professional, fast, and secure** website for under $3/month using:

- **MkDocs** with Material theme
- **Amazon S3** static website hosting
- **CloudFront** CDN for global performance
- **Route 53** for DNS management

## Cost Breakdown

| Service | Monthly Cost |
|---------|-------------|
| S3 Storage & Requests | $0.50 |
| CloudFront CDN | $1.00 |
| Route 53 DNS | $0.50 |
| **Total** | **$2.00** |

## vs WordPress Hosting

| WordPress | MkDocs + S3 |
|-----------|-------------|
| $50-200/month | $2-3/month |
| Complex maintenance | Zero maintenance |
| Security vulnerabilities | Inherently secure |
| Slow loading | Lightning fast |
| Plugin dependencies | No plugins needed |

Step 4: Local Development and Testing

# Start local development server
mkdocs serve

# Visit http://localhost:8000 to preview
# Changes auto-reload as you edit files

Step 5: Build Static Site

# Build the static site
mkdocs build

# This creates a 'site/' directory with all static files
ls site/
# css/ fonts/ img/ js/ index.html about/ blog/

Deploying to S3 - The $3/Month Magic

Option 1: Manual Deployment (Quick Start)

# Build the site
mkdocs build

# Sync to S3 bucket (replace with your bucket name)
aws s3 sync site/ s3://my-awesome-site-bucket --delete

# Enable website hosting
aws s3 website s3://my-awesome-site-bucket \
 --index-document index.html \
 --error-document 404.html

Option 2: Terraform for Infrastructure as Code

Create the S3 infrastructure with Terraform:

# main.tf
resource "aws_s3_bucket" "website" {
 bucket = var.domain_name

 tags = {
 Name = var.domain_name
 Environment = "production"
 Purpose = "static-website"
 }
}

resource "aws_s3_bucket_website_configuration" "website" {
 bucket = aws_s3_bucket.website.id

 index_document {
 suffix = "index.html"
 }

 error_document {
 key = "404.html"
 }
}

resource "aws_s3_bucket_public_access_block" "website" {
 bucket = aws_s3_bucket.website.id

 block_public_acls = false
 block_public_policy = false
 ignore_public_acls = false
 restrict_public_buckets = false
}

resource "aws_s3_bucket_policy" "website" {
 bucket = aws_s3_bucket.website.id

 policy = jsonencode({
 Version = "2012-10-17"
 Statement = [
 {
 Sid = "PublicReadGetObject"
 Effect = "Allow"
 Principal = "*"
 Action = "s3:GetObject"
 Resource = "${aws_s3_bucket.website.arn}/*"
 }
 ]
 })
}

# CloudFront for CDN (optional but recommended)
resource "aws_cloudfront_distribution" "website" {
 origin {
 domain_name = aws_s3_bucket_website_configuration.website.website_endpoint
 origin_id = "S3-${var.domain_name}"

 custom_origin_config {
 http_port = 80
 https_port = 443
 origin_protocol_policy = "http-only"
 origin_ssl_protocols = ["TLSv1.2"]
 }
 }

 enabled = true
 default_root_object = "index.html"
 aliases = [var.domain_name]

 default_cache_behavior {
 target_origin_id = "S3-${var.domain_name}"
 viewer_protocol_policy = "redirect-to-https"
 compress = true

 allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
 cached_methods = ["GET", "HEAD"]

 forwarded_values {
 query_string = false
 cookies {
 forward = "none"
 }
 }
 }

 restrictions {
 geo_restriction {
 restriction_type = "none"
 }
 }

 viewer_certificate {
 acm_certificate_arn = var.ssl_certificate_arn
 ssl_support_method = "sni-only"
 }

 tags = {
 Name = var.domain_name
 Environment = "production"
 }
}

Option 3: Automated CI/CD with GitHub Actions

#.github/workflows/deploy.yml
name: Deploy to S3

on:
 push:
 branches: [ main ]

jobs:
 deploy:
 runs-on: ubuntu-latest

 steps:
 - uses: actions/checkout@v4

 - name: Setup Python
 uses: actions/setup-python@v4
 with:
 python-version: '3.x'

 - name: Install dependencies
 run: |
 pip install -r requirements.txt

 - name: Build site
 run: mkdocs build

 - name: Configure AWS credentials
 uses: aws-actions/configure-aws-credentials@v4
 with:
 aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
 aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
 aws-region: us-east-1

 - name: Deploy to S3
 run: |
 aws s3 sync site/ s3://${{ secrets.S3_BUCKET }} --delete
 aws cloudfront create-invalidation --distribution-id ${{ secrets.CLOUDFRONT_ID }} --paths "/*"

Advanced Features for Your $3 Website

Custom Domain with SSL

# Get SSL certificate (free with AWS Certificate Manager)
# Request certificate for your domain
# Point your domain's DNS to CloudFront

# Total additional cost: $0.50/month for Route 53 hosted zone

Blog Functionality

MkDocs Material includes a powerful blog plugin:

# mkdocs.yml
plugins:
 - blog:
 blog_dir: blog
 blog_toc: true
 post_date_format: long
 post_url_format: "{slug}"
 categories_name: Categories
 categories_toc: true
 pagination: true
 pagination_per_page: 10

Search Functionality

Built-in search that works offline:

# mkdocs.yml
plugins:
 - search:
 separator: '[\s\-,:!=\[\]()"`/]+|\.(?!\d)|&[lg]t;|(?!\b)(?=[A-Z][a-z])'

Analytics Integration

Free Google Analytics integration:

# mkdocs.yml
extra:
 analytics:
 provider: google
 property: G-XXXXXXXXXX

Social Media Integration

# mkdocs.yml
extra:
 social:
 - icon: fontawesome/brands/twitter
 link: https://twitter.com/username
 - icon: fontawesome/brands/linkedin
 link: https://linkedin.com/in/username
 - icon: fontawesome/brands/github
 link: https://github.com/username

Performance Comparison

Load Time Comparison (Real Data)

Platform First Load Cached Load Mobile Score
WordPress (Shared) 3-8 seconds 2-4 seconds 60-80
WordPress (Managed) 2-5 seconds 1-3 seconds 70-90
MkDocs + S3 0.5-1 second <0.5 seconds 95-100

Lighthouse Scores

MkDocs + S3 consistently achieves: - Performance: 95-100 - Accessibility: 90-100 - Best Practices: 90-100 - SEO: 90-100

WordPress sites typically score 60-85 across all categories.

Real-World Success Stories

Documentation Sites

  • Material for MkDocs own site: Serves millions of page views
  • FastAPI documentation: Lightning-fast API docs
  • Many open-source projects: Reduced hosting costs by 95%

Personal Blogs

  • Technical blogs: Professional appearance, zero maintenance
  • Portfolio sites: Showcase projects with minimal cost
  • Company documentation: Internal wikis and knowledge bases

Cost Savings Examples

Case Study 1: Technical Blog - Before: WordPress hosting $75/month = $900/year - After: S3 + CloudFront $3/month = $36/year - Savings: $864/year (96% reduction)

Case Study 2: Company Documentation - Before: Confluence $10/user/month (10 users) = $1,200/year - After: S3 hosting $36/year + domain $12/year = $48/year - Savings: $1,152/year (96% reduction)

Migration from WordPress

Content Migration Strategy

  1. Export WordPress content to Markdown
  2. Preserve URL structure with redirects
  3. Optimize images for static hosting
  4. Set up 301 redirects from old URLs

WordPress to Markdown Tools

# Install wordpress-to-markdown converter
npm install -g wordpress-export-to-markdown

# Convert WordPress export
wordpress-export-to-markdown --input=export.xml --output=docs/

SEO Preservation

  • Keep URL structure with proper navigation
  • Optimize meta descriptions in frontmatter
  • Fast loading improves search rankings
  • Mobile-first design boosts mobile SEO

Maintenance and Updates

WordPress Maintenance (Monthly)

Plugin updates: 2-4 hours ❌ Security patches: 1-2 hours ❌ Performance optimization: 2-3 hours ❌ Backup verification: 30 minutes ❌ Uptime monitoring: Ongoing concern

MkDocs + S3 Maintenance

Content updates: Write and commit Markdown ✅ Security: Zero maintenance required ✅ Performance: Always optimal ✅ Backups: Git is your backup ✅ Uptime: 99.999% SLA from AWS

Time saved: 5-10 hours per month

Limitations and Considerations

What MkDocs + S3 Can't Do

Dynamic content: No server-side processing ❌ User authentication: Static files only ❌ Contact forms: Need external service (Netlify Forms, etc.) ❌ E-commerce: No shopping cart functionality ❌ User comments: Need external service (Disqus, etc.)

Perfect Use Cases

Documentation sitesTechnical blogsPortfolio websitesCompany brochure sitesPersonal websitesKnowledge basesProject showcases

Getting Started Checklist

Week 1: Setup

  • Create AWS account
  • Install MkDocs and Material theme
  • Create initial content structure
  • Set up local development environment
  • Test site locally

Week 2: Content

  • Write main pages (Home, About, etc.)
  • Create first blog posts
  • Add navigation structure
  • Optimize images and assets
  • Test responsive design

Week 3: Deployment

  • Create S3 bucket
  • Configure static website hosting
  • Set up CloudFront distribution
  • Configure custom domain (if applicable)
  • Set up automated deployment

Week 4: Optimization

  • Set up analytics
  • Test performance with Lighthouse
  • Configure SEO settings
  • Set up monitoring
  • Document deployment process

Conclusion

Why pay $50-200/month for WordPress hosting when you can get better performance, security, and reliability for $3/month?

The MkDocs + S3 approach gives you:

97% cost reduction compared to managed WordPress ✅ 10x faster loading times ✅ Zero maintenance overhead ✅ Bulletproof security with static files ✅ Professional appearance with Material theme ✅ Developer-friendly workflow with Git and Markdown

Is This Right for You?

Choose MkDocs + S3 if you need: - Documentation or blog site - Minimal ongoing maintenance - Lightning-fast performance - Professional appearance - Ultra-low costs

Stick with WordPress if you need: - E-commerce functionality - User authentication/registration - Complex dynamic content - Non-technical content editors

Next Steps

  1. Start small: Create a test site with a few pages
  2. Migrate gradually: Move content piece by piece
  3. Automate deployment: Set up CI/CD for updates
  4. Monitor performance: Track the improvements
  5. Calculate savings: See how much you're saving monthly

Ready to save $1,000+ per year on hosting costs while getting better performance? Start your MkDocs + S3 journey today!


💰 Total Annual Savings

\(36/year** for MkDocs + S3 vs **\)1,500-4,000/year for WordPress = $1,464-3,964 saved annually

That's a vacation fund, emergency savings, or investment money - just from switching your website hosting approach!

What will you do with all the money you'll save? 🏖️

In this post I will show you how to create the AWS resources necessary for hosting your website using Terraform, as well as how to set up a basic MkDocs site.