My remote blogging workflow

I wrote earlier about reworking my blog so that I can manage it remotely over SSH. Here’s an update on that.

TLDR: success!

Connecting

I use Zed’s Remote Development to edit my blog content and run git commands over SSH. It works really well.

To get it working, I defined the SSH connection to my home server (a Mac Mini) in Zed’s settings like so:

"ssh_connections": [
  {
    "nickname": "blog",
    // `mini.jump` is defined in ~/.ssh/config
    "host": "mini.jump",
    "args": [],
    "projects": [
      { "paths": ["~/repos/sal/blog-11ty"] }
    ],
    // built-in port forwarding!
    "port_forwards": [{ "local_port": 8080, "remote_port": 8080 }]
  }
]

This does a couple cool things. First, when I run Zed’s open-remote dialog (Ctrl-Cmd-O), my blog project shows up as an option. When I select it, Zed manages SSH behind the scenes and gives me a workspace that feels more or less like I’m editing my blog locally. When I open Zed’s terminal, for example, it’s SSH’d into the remote host and in the blog path. Sweet.

Second, when I open the project, Zed starts forwarding port 8080 from my home server to my local machine. That means when I run npm run start to launch the 11ty dev server on the remote machine, I can go to localhost:8080 on my local machine and see my blog. With live reloading!

Best of all, it was easy to get working. No gotchas or head scratching. I was thinking there’s no way this port-forwarding thing is just going to work this easily. But it did!

You can also get this working in other ways, too. For example, before I realized I can do all of the above in the JSON config, I was doing it in the terminal:

# create a Zed project connected to my home server
zed ssh://mini.jump/~/path/to/blog

# start port forwarding
ssh -N -L 8080:localhost:8080 mini.jump

If you’re curious how the SSH config works, I’ll briefly explain.

When I’m away from home, I SSH into the Mac Mini sitting on my home-office desk via a jump server. I chose a VM in OCI as my jump box because OCI’s free tier seems to have a good rep, but any VM that can run Tailscale should do. (The VM connects to my home server via Tailscale.) When I’m home, on the other hand, I connect to my home server directly via the local network.

Meanwhile, in ~/.ssh/config, I have hosts defined for both scenarios: connecting over the public internet using my jump box (mini.jump), and connecting over my LAN when I’m in my house (mini.lan):

Host mini.jump
  Hostname <Mac Mini's hostname in Tailscale>
  User <my username on the Mac Mini>
  ProxyJump <username:IP of my OCI VM>

Host mini.lan
  Hostname <Mac Mini's hostname on my home LAN>
  User <my username on the Mac Mini>

ProxyJump is the config line that makes the jump happen. When I run ssh mini.jump, it routes me directly onto my Mini. Pretty cool.

Writing

I use iA Writer if I want to start a new post with no fuss. It’s fast and peaceful. I can use it on my iPhone, iPad, and Macbooks, and they all stay in sync via iCloud.

Once a post is taking shape or I feel like using Vim mode, I move it into my blog’s git repo and continue writing using Zed. Then I can start previewing the post on the local 11ty dev server.

I do most of my pre-publish writing in a git branch called draft. In the Cloudflare Pages config, I disabled builds for non-main branches, so I can commit and push freely to the draft branch without triggering any Cloudflare jobs. This is how I sync my repo’s drafts between computers (mainly between my Mac Mini and Macbook Air).

Publishing

When I’m ready to publish, I remove draft: true from my frontmatter and make my final git commits. I typically use either lazygit or Zed’s git UI for these commits.

Then I do something like this:

git checkout main
git merge draft

# one more round of previewing
npm run start

# to trigger the publish build:
git push

About 60 seconds later, the changes should be live on my site. I double check them and call it good!

Closing thoughts

My primary goal in moving my blog was to find a writing and publishing workflow that works end-to-end over SSH. Mission accomplished! I’m super impressed how well Zed’s remote-dev feature works for my use case.

I was confident out of the gate that 11ty, Gitlab, and Cloudflare would all do what I wanted once I figured them out. I’ve been down similar roads before.[1] But I wasn’t sure if it’d be comfortable or fun to work the rig over SSH. Zed made it so.

To someone unfamiliar with git and such, all of this may seem highly convoluted compared to just using a CMS like Bear Blog or Wordpress. And … yep, you’re right.

As I’ve written about before, I’m a one-time software engineer, now a people manager for many years. I look for excuses to roll up my sleeves and get a little dirty with the command line. Glory days, I guess. Plus, I find working with git to be satisfying and reassuring due to all the benefits of version control. I know git’s not perfect, but it’s great for my simple use cases.

So, for me, this workflow is fun and rewarding. For a different brain chemistry, it might be a total headache.

TTFN!


  1. One of my prior blogs was built on Hugo, GitHub, and Netlify. Very similar, and I liked it. ↩︎