As an IndieHoster, I offer managed personal server
hosting for around 30 people, on (currently) 3 virtual servers, which I rent from Vultr. I don't develop any
applications or control panels for them, but I do build up some collection of reusable parts each time I install
software on servers for these people.
The reason I write software at all is that most personal server
applications are not designed to run on as the main application on a server, they are designed to run on top of a
webserver. A webserver like for instance Apache is in itself designed to be easily configurable for a number of
situations, including shared hosting: the situation where you host a number of websites on one linux server. So in
its simplest form, the collection of reusable parts I build up would be a webserver configuration file, which
configures Apache so that it runs the right personal server applications for each user. I need to automate the
process of configuring this webserver.
In practice, this webserver is a node application, which does
the SNI offloading (the process that allows multiple https websites to live on one IP address), and that runs each
user's personal server inside a Docker container. Through a contraction of SNI in front of Docker containers, I call it Snickers.
Snickers is designed to stay up, even when
stuff changes. It loads its config on-the-fly, so if I add a new site to a running server, I don't have to
interrupt its execution. But changes to the core code of Snickers itself do require interrupting it, of
course.
Whenever I make such changes, even when I tested them first, I need to have a good way to stop
the running instance of Snickers, start the updated one, and switch back quickly if necessary. The way I do this
is with blue-green
deployment. I actually called my two alternating slices "the blue
team" and and "the red team", since with blue-green, I keep having the association that green is always the
color of the live one.
Whenever I have an updated version of Snicker to deploy, I do a "git pull" in
the folder from which it's not currently running, and kill the running instance. If anything unexpected happens, I
kill the new instance, resulting in instant rollback. If everything is OK, I do a "git pull" in the other folder
as well, and then the deploy is complete.
Simple yet effective! :)