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:
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¶
- Export WordPress content to Markdown
- Preserve URL structure with redirects
- Optimize images for static hosting
- 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 sites ✅ Technical blogs ✅ Portfolio websites ✅ Company brochure sites ✅ Personal websites ✅ Knowledge bases ✅ Project 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¶
- Start small: Create a test site with a few pages
- Migrate gradually: Move content piece by piece
- Automate deployment: Set up CI/CD for updates
- Monitor performance: Track the improvements
- 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.