Self-Hosted CMS Options & Landscape#
What Was Established#
- User seeks a self-hosted CMS for an Ubuntu VM, explicitly rejecting WordPress due to business practices.
- Preference for tools respected by the web development and self-hosting communities.
- Exploration of CMS categories: Monolithic, Flat-file, Static Site Generators (SSG), Headless CMS, and Custom.
Key Decisions#
- Rejected WordPress: Cited business practices as a dealbreaker.
- Favoring Developer-Respected Alternatives: Leaned towards headless or modern flat-file CMS options.
- Top Contenders Identified: Directus (Headless), Strapi (Headless), Kirby (Flat-file), Payload CMS (Headless/TS), Ghost (Blogging).
CMS Landscape & Options#
Monolithic CMS#
- WordPress: Dominant (60% market), huge ecosystem, but rejected by user.
- Drupal: Flexible, steep learning curve.
- Joomla: Balanced ease/power, smaller community.
Flat-file CMS (No Database)#
- Grav: Fast, simple, file-based.
- Kirby: Beautiful UI, file-based, commercial license (~$129), highly respected by designers/devs.
Static Site Generators (SSG)#
- Jekyll: GitHub Pages compatible.
- Hugo: Blazing fast, Go-based.
- Eleventy: Flexible, JS-based.
- Next.js: React-based, hybrid.
Headless CMS (API-Driven)#
- Directus: Community favorite. Node.js/Vue.js. Provides REST/GraphQL APIs, beautiful admin UI. Excellent for full frontend control.
- Strapi: Most popular headless. Node.js/React. Strong plugin ecosystem.
- Payload CMS: Rising star. TypeScript-first, excellent DX.
- Ghost: Primarily for blogging/publishing. Markdown-native.
- Contentful/Sanity: Enterprise/Developer friendly, but often cloud-hosted (though self-hostable options exist).
Custom / Build-Your-Own#
- The Guardian’s “Composer”: Fully custom-built in Scala/Play Framework. Not recommended for small projects.
- Server-Side: PHP includes, Python (Django/Flask), Node.js (Express).
Recommended Stack for Ubuntu#
- For Maximum Control & Flexibility: Directus or Payload CMS.
- For Content-Focused Sites: Kirby or Statamic.
- For API-Driven Projects: Strapi.
- Quick Start (Directus on Ubuntu):
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - sudo apt-get install -y nodejs npm create directus-project@latest my-cms cd my-cms npm install npx directus start
Historical Notes#
- Conversation date: 2025-11-17.
- User explicitly stated a preference against WordPress due to business practices.
- Focus remains on self-hosted, developer-respected tools.
- Note: Directus and Strapi have evolved significantly since late 2025; verify current self-hosting requirements, licensing, and Docker compatibility for homelab deployment.
Hugo-Specific Configuration#
Project Structure#
myblog/
├── config.toml -- Main configuration (baseURL, languageCode, title, theme)
├── content/ -- Blog posts in Markdown
├── themes/ -- Installed themes (git submodules)
├── static/ -- Static assets (images, JS, CSS)
└── public/ -- Generated static files (deployed to Nginx)Key config.toml Settings#
baseURL— Domain URL (e.g.,https://blog.nbkelley.com)theme— Must match theme folder name inthemes/buildDrafts—trueduring development,falsefor productionpaginate— Posts per page
Creating Posts#
hugo new posts/my-post.md # Draft in content/posts/
hugo -D # Build including drafts
hugo # Production build to public/Deployment Options#
- Manual rsync:
rsync -avz --delete public/ user@server:/var/www/html/blog - Git webhook: Server-side script that
git pull && hugo && cp -r public /var/www/html/blogon push - Cloudflare Pages: Push Hugo source to GitHub, Cloudflare builds and deploys automatically
Comments for Static Sites#
- Utterances — GitHub issues-based, no backend
- Disqus — Traditional, JS-based
- Hyvor Talk — Self-hostable alternative
Related Pages#
- Hugo Deployment to Cloudflare Pages - Troubleshooting
- Hugo Git Submodule Extraction Pattern
- Web Server Stack (Nginx + Apache)
Sources#
ingested/chats/106-Beginner Guide to Building Websites with Ubuntu.mdingested/chats/036-Setting Up Self-Hosted Blogs with Nginx.md- DeepSeek conversation: “Self-Hosted Websites on Ubuntu Server” (historical)
- DeepSeek conversation: “Setting Up Self-Hosted Blogs with Nginx” (chat 036)