Standing Up a Control Plane
What I Learned the Hard Way About SSH, Identity, and Trust
This is not a tutorial. It’s a snapshot of how I’m thinking about a system at a point in time.
- I created a dedicated ops machine because “it works on my laptop” is not an access model.
- SSH keys are identities with scope and intent, not random files you copy around until things work.
- Writing down who can log into what eliminated most of the self-inflicted problems.
I set out to do something simple. I wanted to stand up a small observability stack alongside a personal Ghost blog.
What I did not expect was that the hardest part would not be metrics, dashboards, or containers. It would be identity and trust.
This post is a reflection on what I learned while building a small but intentional control plane using DigitalOcean droplets. It also explains why SSH key management turned out to be the most important and uncomfortable part of the work.
The problem was not tooling. It was mental models.
I have used SSH for years. I knew how to connect to servers. I knew how to copy keys around until things worked.
What I did not have was a clear mental model for who an SSH key represents, where trust should flow, and how access should be revoked cleanly.
When systems are small, you can get away with fuzzy thinking. When you start designing intentionally, you cannot.
I realized I was treating SSH keys as convenience files instead of identities. That worked right up until it didn’t.
Why I created a control plane at all
At first, I planned to manage everything directly from the blog server. It already existed. It already had Docker. It felt good enough.
That assumption broke down the moment I started touching SSH keys.
I was mixing responsibilities without realizing it. A machine that ran workloads was also becoming the place where identity, access, and orchestration lived. That felt convenient. It also felt wrong once I slowed down.
So I created a separate operations host on purpose.
Not because I needed scale. Not because I needed high availability. But because I needed clarity.
This machine exists for a very narrow purpose:
- Git access
- Orchestration
- Administrative SSH into other machines
It does not run workloads. It is safe to rebuild. If it breaks, nothing user facing goes down.
That separation changed how I thought about the entire system.
A simple rule that clarified everything
Once the control plane existed, a single rule emerged.
All control flows downward. Nothing flows back up.
The model became:
- Local machine connects to the ops host
- Ops host connects to workload machines
- Workload machines never connect back
That rule eliminated an entire category of ambiguity. There was no longer any confusion about where keys belonged or why they existed.
Trust had direction.
SSH keys are identities, not files
The real breakthrough came when I reframed SSH keys.
An SSH keypair is not just a file. It is an identity with scope.
Once I saw it that way, everything changed.
- Each machine became an actor
- Each key had a purpose
- Revocation became obvious and predictable
Instead of one key everywhere, I ended up with separate keys for:
- Git access
- Droplet to droplet access
- Local fallback access
At first it felt excessive. In practice, it created calm.
Documentation as a forcing function
The most uncomfortable part was documenting everything.
Hostnames. IP addresses. Users. Keys. Fingerprints. Trust relationships.
It felt like overkill while I was doing it. It turned out to be the most valuable step.
Writing it all down exposed assumptions I did not realize I was making. It also revealed access paths I could not easily explain.
By the end, I had a single document that answered one critical question:
Who can log into this system, from where, and how do I turn that off?
That is not over documentation. That is operational clarity.
What this unlocked
Once identity and trust were clear, several things happened quickly:
- SSH stopped being stressful
- Adding new machines became predictable
- Future steps like observability and automation felt safe instead of risky
The foundation mattered more than the features.
Final takeaway
This work was not really about SSH.
It was about learning to think like an operator instead of a tinkerer.
Small systems deserve good design too, especially if you want them to grow.
Where I intentionally paused
This was the right place to stop.
- The control plane exists
- The trust model is explicit
- Access is documented
- Mental fatigue is acknowledged
The next step is building the observability stack and actually seeing data.
That work is much easier when the foundation feels solid.