//nbkelley /homelab

Self-Hosted CMS Options & Landscape

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).
  • 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 in themes/
  • buildDraftstrue during development, false for production
  • paginate — 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/blog on 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

Sources#

  • ingested/chats/106-Beginner Guide to Building Websites with Ubuntu.md
  • ingested/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)

Varda Server (Ubuntu)

Varda Server (Ubuntu)#

Overview#

Varda is an Ubuntu Server VM at 192.168.1.131 used for web hosting and development. It serves as the primary host for the ilmare.nbkelley.com website.

Note: Varda is a different VM from servarr (192.168.1.112), which runs the media automation stack. These were previously conflated in some wiki pages.

Key Details#

  • Hypervisor: Proxmox (Minas Tirith)
  • Management: Cockpit GUI (Port 9090)
  • Web Server: Nginx for static content
  • Firewall: UFW enabled (ports 22, 80, 443)
  • Development: VS Code Remote-SSH

Nginx Site Structure#

/var/www/ilmare.nbkelley.com/
├── Assets/
│   └── Images/  (Case-sensitive: capital I)
├── html/
│   └── index.html
├── Scripts/
│   └── scripts.js
└── Styles/
    └── styles.css

Nginx Server Block#

/etc/nginx/sites-available/ilmare.nbkelley.com:

Linux Server Optimization

Linux Server Optimization#

What Was Established#

Optimizations for headless Ubuntu servers (specifically HP Pavilion and Thinkpad T480) to prevent sleep/suspend when the lid is closed.

Key Decisions#

Modify systemd-logind to ignore lid switch events to ensure the server remains active when the laptop lid is closed.

Current Configuration#

Prevent Sleep on Lid Close#

Edit /etc/systemd/logind.conf:

sudo nano /etc/systemd/logind.conf

Ensure the following lines are uncommented and set to ignore:

HandleLidSwitch=ignore
HandleLidSwitchExternalPower=ignore
HandleLidSwitchDocked=ignore

Apply the changes:

Web Server Stack (Nginx + Apache)

Web Server Stack (Nginx + Apache)#

What Was Established#

In this setup, Nginx is utilized as a high-performance reverse proxy to handle incoming traffic and static content, while Apache serves as the backend for dynamic content (e.g., PHP/WordPress) due to its flexible .htaccess support.

Key Decisions#

  • Architecture: Nginx acts as the entry point (Port 80/443) and proxies requests to Apache running on a non-standard port (e.g., 8080).
  • Rationale: Leverages Nginx’s superior concurrency and static content handling with Apache’s ease of use for per-directory configuration.

Current Configuration#

Apache Backend Configuration#

Modify /etc/apache2/ports.conf to listen on a different port to avoid conflict with Nginx:

Web Server Deployment Pattern (Beginner)

Web Server Deployment Pattern (Beginner)#

What Was Established#

For a beginner-friendly, lightweight, and scalable homelab setup, a stack consisting of Ubuntu Server LTS and Nginx is the recommended standard. This provides a balance of ease of use, extensive documentation, and low resource overhead.

Key Decisions#

  • Operating System: Ubuntu Server LTS (chosen for stability, community support, and ease of management).
  • Web Server: Nginx (chosen over Apache for being lightweight, faster for static content, and better suited for future use as a reverse proxy).
  • Resource Allocation (Small Site): 1-2 CPU cores, 1-2 GB RAM, 10-2/GB Disk.

Current Configuration#

Nginx Site Configuration#

Default root directory: /var/www/html