Self-Hosted Markdown Blog Solutions
Static Site Generators + Web Server
-
Hugo with Caddy
FROM klakegg/hugo:0.107.0 AS build COPY . /src RUN hugo --minify FROM caddy:2.6.4-alpine COPY --from=build /src/public /usr/share/caddy
- Features:
- Single-binary deployment
- Automatic HTTPS
- HTTP/3 support
- Features:
-
Jekyll + Nginx
server { listen 80; server_name blog.example.com; root /var/www/blog/_site; location / { try_files $uri $uri/ =404; } }
Self-Hosted CMS Options
- Ghost (Pro)
-
Requirements:
- Node.js 16/18
- MySQL 8
-
Deployment:
ghost install --local
-
- Strapi + Markdown Plugin
-
Markdown field type
-
REST/GraphQL API
-
Docker-compose example:
services: postgres: image: postgres:15 strapi: image: strapi/strapi:4.11.7 depends_on: - postgres
-
Markdown Editors with Self-Hosting
-
Jupyter Notebooks
- Convert .ipynb to Markdown
- JupyterHub deployment
-
Outline (Knowledge base)
- Markdown WYSIWYG
- Docker deployment
Deployment Environments
Environment | Requirements | Setup Complexity |
---|---|---|
VPS | 1GB RAM, 20GB SSD | Medium |
Home Server | Raspberry Pi 4+ | High |
Container | Docker, Kubernetes | Variable |
Serverless | AWS Lambda, Cloudflare | Low |
Automation & CI/CD
# .github/workflows/deploy.yml
name: Deploy Blog
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build Hugo
run: hugo --minify
- name: Deploy to SSH
uses: appleboy/[email protected]
with:
host: ${{ secrets.SSH_HOST }}
key: ${{ secrets.SSH_KEY }}
source: "public/"
target: "/var/www/blog"
Security Considerations
-
SSL/TLS with Let's Encrypt
certbot --nginx -d blog.example.com
-
Firewall rules (UFW example):
ufw allow 22/tcp ufw allow 80/tcp ufw allow 443/tcp ufw enable
-
Regular backups
# Daily backup script 0 2 * * * tar -czf /backups/blog-$(date +\%F).tar.gz /var/www/blog
Monitoring & Maintenance
-
Prometheus + Grafana for metrics
-
Logrotate configuration:
/var/log/nginx/*.log { daily missingok rotate 14 compress delaycompress notifempty create 0640 www-data adm sharedscripts }
-
Systemd Service example for Hugo:
[Unit] Description=Hugo Blog Service After=network.target [Service] User=bloguser WorkingDirectory=/var/www/blog ExecStart=/usr/local/bin/hugo server --bind 0.0.0.0 --baseURL https://blog.example.com Restart=always [Install] WantedBy=multi-user.target
Recommended Stacks
- Simple: Hugo + Caddy + Docker
- Full CMS: Ghost + MySQL + Cloudflare Tunnel
- Dynamic: Strapi + Next.js + AWS Lightsail
Alternative Approaches:
- Cloudflare Pages + Git (Managed self-hosting)