Migrating from self-hosted in Kubernetes Databases to managed hosted at Digital Ocean or the story of how I started working on Opportunistic TLS in ReactPHP
One of the things I’ve been planning for months, is to move my self-hosted
MySQL servers from hosting it inside my
Kubernetes cluster to managed hosted at
At $15 each, I would have to save at least $45 on
Kubernetes cluster resources (nodes and volumes) by moving them. In the end, I succeeded at that and probably will end up saving even more as I’m
Prometheus exporters for certain things into my home
Kubernetes cluster. (Less expensive per month to run and not super important to have a high uptime/availability, to be honest.) Plus I’ve
been cutting down on services. On the plus side it comes with shiny graphs to look inside how the managed databases are doing
But all of that isn’t why I include this in my update.
TLS when connecting to their managed databases. Something that works out of the box for all of the things I’ve been running,
except for those powered by
ReactPHP and use
PostgreSQL. For that, at the low level, I use
voryx/pgasync to connect to it. And it doesn’t support
TLS out of the box, which I initially
thought as well until I started looking into why. The wire protocol for
Opportunistic TLS when you required a secure connection. Unless all other services, I’ve worked with so far either
TLS from the start or stay plain text.
PostgreSQL is different however, it requires you to upgrade the plain text connection to a
TLS encrypted connection. Something we don’t support yet in
we either do plain text or
TLS from the start.
This is where I had to make a call, a) abort and figure out all of this later, or b) figure out all of this now within a reasonable timeframe or fall back to a). It turned out to be b) as two hours into
all of this I figured out why my
tls:// URL wasn’t connecting and how to
PostgreSQL wire protocol handles this. After diving into
ReactPHP’s socket component to see how big of an effort this would be I
decided to MVP is in a low traffic project, just the bare bones to make it work and proof the idea before creating PR’s for it. The initial version was passing flags all around like there is no tomorrow,
and it wasn’t anything close to what it is now, but it worked.
After that, I started iterating over the code to make it robust and easy to use without having to pass around all the flags. Resulting in this PR: reactphp/socket#302
Just as the initial
react/socket, the initial pgasync implementation was also very naive and assumed you always wanted to encrypt the connection after connecting. After getting a few iterations in I got to
the point where my specific use case was fully covered. But I didn't have support for all the
TLS modes yet. My initial thought was This can't be that hard right?, well it is a fun challenge that can’t be
resolved with a few flags in one location.
Of all the modes disable was the quickest to implement, when that mode is used don’t try to upgrade the connection to
TLS. All the other modes (
verify-full) will try to
upgrade with various different
TLS stream flags depending on the mode. And that is where I’m currently at with that PR, figuring out which flags go with which mode.