Hypha Spike: Deployment 1
Wait, what, we’re deploying Hypha (subscribe via RSS) – but we haven’t even built it yet?!
Exactly.
Philosophy
Design and scope limitation for the spike
There are two interrelated processes to deploying your own instance of Hypha:
- Domain registration and/or DNS setup
- VPS server setup
- TLS setup
There is a somewhat cyclic relationship between these three steps as they each depend on the other for certain information.
The DNS setup requires the IP address of the server and the server needs to know the domain that it will be responding for. To complicate things a little more, the domain name has to propagate before we can obtain a free TLS certificate from Let’s Encrypt.
Also, steps 1 and 2 have a commercial aspect.
For the purposes of this spike, I want to concentrate only on Step 2: automating the VPS server setup.
Cloud-init
VPS accounts are available for a couple of euros per month these days and many support cloud-config syntax (examples) via the cloud-init standard by Canonical as part of the new instance provisioning process via a ‘user data’ field on their online forms or via their APIs. Supported operating systems include Ubuntu, Fedora, Debian, RHEL, CentOS, and others.
In this spike, I’m going to explore using cloud-init to set up a server so that we can automatically:
-
Install the latest Long-Term Support (LTS) version of Node.js in a manner that would make it easy to perform updates on it.
-
Clone and run an empty (‘hello world’) version of Hypha.
Thankfully, Canonical has a tool called multipass that lets you easily spin up Ubuntu instances locally and pass them a cloud-init file. I’ll be using that to iterate on the cloud-init script.
Notes
-
cloud-init format supports Gzip compression as user-data is limited to ~16,384 bytes.
Add an account so you can ssh into the instance
#cloud-config
users:
- name: <INSERT ACCOUNT NAME HERE>
groups: sudo
shell: /bin/bash
sudo: ALL=(ALL) NOPASSWD:ALL
ssh-authorized-keys:
<INSERT SSH PUBLIC KEY HERE>
Replace <INSERT ACCOUNT NAME HERE>
with the account name you want (e.g., this is the <account name>@<your instance ip>
that you will use to SSH into the instance).
Replace <INSERT SSH PUBLIC KEY HERE>
with your public SSH key, which you can most likely find in ~/.ssh/id_rsa.pub
.
For example, if your account name is indie, you want the instance to be called hypha, and you save the above file as cloud-init.yaml, you can start up a new instance and connect to it over SSH:
-
Create an launch the hypha instance:
multipass launch --name hypha --cloud-init cloud-init.yaml
-
List the available instances to find the IP address of the new hypha instance (e.g., 10.83.214.166):
multipass list
-
Connect via SSH:
ssh indie@10.83.214.166
Here is a good article on users and groups.
For the final cloud init file, with many more tasks, see cloud-init.yaml and read the comments.
Thoughts/to-dos/questions
-
Since TLS setup with Let’s Encrypt depends on domain name propagation, it is the last thing we must do (and is thus outside the scope of this spike). See dns-01 verification (examples). Can be used along with Lexicon for manipulating DNS records in a standardised way across providers. e.g., See this Dehydrated hook for Namecheap + Let’s Encrypt. Also interesting, IWantMyName has a Dynamic DNS interface which could possibly be used for this.
-
Node.js is perfectly capable as its own server and does not need to be proxied (e.g., by nginx) for single-tenant use.
-
✓
Add link to spike source code repository -
How long does server setup take?
About ~2 minutes 30 seconds. 2 minutes of that is our custom initialisation and 30 seconds the generic server setup. That incudes apt update/upgrade, Node.js install, PM2 install, etc.
-
Test the cloud-init script with a number of different hosts.
To explore in future spikes
-
Domain registration and DNS setup via third-party service and API.
-
Native app that handles onboarding (domain registration, DNS setup, VPS setup, TLS setup, and app setup) in a seamless experience.
-
As above but with the integration of a payment step for the domain registration and hosting.
Postmortem
We can get a server up and running with a Node.js app in ~ 2 minutes 30 seconds without any optimisations. This could be hugely optimised for everyday use later by having prebuilt server images but it is entirely acceptable as-is for use by developer to deploy their own copy of Hypha. Even when TLS is supported, the longest part of a developer getting up and running with their own node of Hypha will be the DNS propagation.
References
TLS
- mkcert: a simple zero-config tool to make locally trusted development certificates with any names you’d like
Server setup
- multipass: orchestrate virtual Ubuntu instances (supports cloud-init)
- cloud-init: the standard for customising cloud instances
- NodeSource Node.js binary distributions: for Ubuntu, etc.
- PM2: Node.js Production Process Manager with a built-in Load Balancer.
Promising discoveries
(Unused in current spike but might be useful in the future.)
- greenlock-express: Free SSL and managed or automatic HTTPS for node.js with Express…
- nodenv: for managing node versions in production