Skip to main content
  1. Posts/

Setting Up the Blog You're Reading Right Now, Using an AI in My Terminal

·995 words·5 mins
Author
Rudy

This one’s a bit meta. The blog you’re reading was set up entirely by an AI tool running in my terminal. I didn’t write a single config file. I described what I wanted, and it happened. Twice, actually, because the first attempt was overkill and I scrapped it.


Why a blog at all
#

I’d been documenting the home server build in markdown files on my laptop. Notes for myself, mostly. But the more I wrote, the more it started reading like something other people might find useful. The information I wished I’d had when I started.

I didn’t want to use Medium or Substack. The whole point of this project is owning my own stuff. So a self-hosted blog felt right.


Claude Code
#

I’ve mentioned using AI tools throughout this series. Early on it was mostly Claude and Gemini in a browser window, copying and pasting commands back and forth. It works, but there’s friction. You’re constantly switching between the chat, your terminal, and whatever file you’re editing.

Recently I’ve been using Claude Code, which is Anthropic’s CLI tool. It runs directly in the terminal and can execute commands, read and edit files, and SSH into remote machines. Instead of copying a command from a chat window and pasting it into your terminal, you just tell it what you want and it does it. It asks for permission before running anything, so you’re still in control, but the loop is much tighter.

For this particular setup, it made a noticeable difference.


First attempt: Ghost
#

My first instinct was Ghost, a full-featured blogging platform. Open source, clean editor, runs in Docker. I told Claude Code to set it up and it did the whole thing in one go: created a Docker Compose file with Ghost and MySQL, added the Caddy reverse proxy block, put it on the Homepage dashboard. A couple of minutes, most of which was waiting for images to pull.

Ghost worked. It looked good. I switched it to dark mode, removed the subscribe banner, set up a Content API key so Homepage could show a post count widget. It was a proper blogging platform running on my server.

But the more I looked at it, the more it felt like too much. Ghost runs a Node.js application and a MySQL database, permanently. It has user accounts, an admin panel, a members system, email newsletters, a full REST API. I have a handful of markdown files and no readers. It was like buying a commercial kitchen to make toast.


Second attempt: Hugo
#

What I actually needed was something that takes markdown files and turns them into a website. That’s it. No database, no running application, no admin panel.

Hugo does exactly that. It’s a static site generator: you give it markdown files, it outputs plain HTML. No JavaScript, no backend, nothing running. Just files on disk.

The setup was even simpler than Ghost. Hugo doesn’t run as a server, so there’s no persistent Docker container. Instead, you run the Hugo Docker image once to build the site, and it exits. Caddy serves the output as static files:

blog.yourdomain.com {
    import tls_common
    root * /opt/docker/hugo/public
    file_server
}

The markdown files I’d already been writing just needed a small front matter block at the top of each:

---
title: "Your Post Title"
date: 2026-02-01
draft: false
---

Hugo builds the entire site in about 130 milliseconds. There’s a rebuild script on the server, so publishing a new post is: drop the markdown file in the content folder, run the script, done.


Making it public
#

Everything else on my server is internal only, accessible from home WiFi or VPN. But a blog that nobody can read isn’t much of a blog.

I already had a Cloudflare Tunnel set up for Immich share links. Adding the blog was just another entry in the tunnel config pointing blog.yourdomain.com to Caddy, plus a CNAME record in Cloudflare DNS.

The security picture here is as good as it gets. There’s no application to exploit, no database to breach, no login page to brute force. It’s static HTML behind Cloudflare’s network. Someone visiting the blog hits Cloudflare’s edge, which sends the request through the tunnel to Caddy, which serves a file. That’s the entire attack surface: files on disk.


What surprised me
#

The whole journey, from “I want a blog” to “there’s a public blog with six posts”, happened in a single conversation with Claude Code. It set up Ghost, I used it for a bit, decided it was too much, asked about alternatives, and it tore the approach down and rebuilt with Hugo. It read my existing posts, added the right front matter, picked a dark theme, configured the tunnel, updated the dashboard.

There was one small hiccup early on. SSH password authentication doesn’t work non-interactively by default, so it needed sshpass installed on my Mac to send commands to the server. A minor detour, but it figured that out on its own after the first connection failed.

The thing that would have taken me the longest manually wasn’t any single config, it was the back-and-forth of researching options, reading docs, checking compatibility, and iterating. Having something that can do all of that in context, while also executing the commands, collapses the whole process.


Where things stand
#

The blog is live at blog.yourdomain.com, publicly accessible through Cloudflare Tunnel. It’s a static Hugo site using the Blowfish theme in dark mode. Ghost is still running on the server too, because why not. Maybe I’ll use it for something else later, or maybe I’ll clean it up eventually.

Publishing a new post means writing a markdown file and running a one-line rebuild. No editor, no CMS, no deploy pipeline. Just markdown in, HTML out.

There’s something satisfying about the blog running on the same server it’s documenting. The infrastructure is the content, and the content runs on the infrastructure. It’s home servers all the way down.