3 minutes
Read My Blog Over SSH
Try it
In your terminal, run: ssh ssh.naveensrinivasan.com, and you don’t need any authentication. The host key fingerprint for this server is SHA256:hK3ttqzsSBKUN18Wxu6eB0JB6lu4v4UBt6n8BX2WkIw.
Why SSH?
I have enjoyed the minimalism of the man pages, and it is also cool to have the blog accessible via SSH.
The added benefits include no browsers, no cookies, no accounts, and no scrapers. Most of my content is words and code, and there are a few images that won’t be rendered, which is fine. I don’t have gifs, or videos. IMO, most of the tech blogs should be like man pages. Also, I think most of my readers are on the terminal, and they already trust the transport.
What happens if the server is compromised?
I assumed that this box is going to be compromised and built things around this premise to reduce the blast radius. I have this server on a DigitalOcean $6.00/month droplet, and I don’t have any other resources on the DigitalOcean account, which means lateral movement should not be an issue.
There aren’t any CI jobs pushing updates to the server for the SSH TUI, and the blog content is pulled from https://naveensrinivasan.com/index.json on a schedule, which means there aren’t any keys. If there is an update, I scp the TUI app from my laptop.
I have the blog running with a dedicated user and not root. The SSH TUI service binds to port 22 (more on this later) with CAP_NET_BIND_SERVICE only. There is a separate host key for the blog, and another for OpenSSH.
Readers will trust the blog’s keys, not my OpenSSH keys on 222. And I run the blog as a systemd service with hardened settings to reduce the blast radius.
What does the reader get?
A list of articles to read with a simple keyboard shortcut and an About link, a minimalist blog that emulates something like Linux man pages.
Writing without images pushes me to make my posts clearer and more engaging so readers understand everything easily!
What’s under the hood?
It is a Go app built on https://github.com/charmbracelet/wish and https://github.com/charmbracelet/bubbletea, running on Ubuntu 24.0.
How is it configured to serve on port 22 and still have admin access to the server?
The default SSH port is 22, and when they SSH into my blog, I don’t want them to use a custom port. When a reader hits ssh.naveensrinivasan.com , I want them to land on my blog and not a default shell, and I also need a real OpenSSH login, and two of them cannot run on port 22.
So I have configured the blog app to run on 22 and moved OpenSSH to 222. My blog readers will get the TUI, and I can get in with ssh -p 222.
I have explicitly avoided authentication, comments, and personalization. There’s no state on the blog side, so there’s no state to protect. Anyone with an SSH client gets the same read-only view, and that’s the entire security model.