Some of the things I think about when I go to a website:
1. What does the (undoubtedly) dirty backend infrastructure look like?
2. Is it classical on-prem 3-tier or spiffy new serverless architecture perhaps?
3. Does the administrator of this site hate the term "serverless" as much as I do?

There always seems to be some security-through-obscurity with regards to infrastructure. I highly doubt you'll ever go to google.com and see architecture diagrams in the banner.

With that said, I'm going to take this opportunity to answer my own questions, with regards to this site.

First, there was bare metal

As alluded to above, I really dislike terms such as "serverless", or "cloud", or more recently "self-driving vehicle". All of these easy phrases which encompass such wide ranging concepts and functionality do a disservice to the average persons understanding when they hear or speak about it.

Regarding self-driving vehicles- artificial intelligence is outside my scope of understanding, as most people would probably admit. Talking about self-driving cars however, I think... cameras... sensors... compute... compute... success!

Ultimately everything in this world is silicon, or slowly becoming silicon. All information is slowly being assimilated into generic 1's and 0's. These 1's and 0's are most entirely stored on magnetic spinning hard-drives, or more recently, solid-state hard-drives. These are gasp physical "bricks" that are inserted into a gasp physical computer cases inside a physical rack, inside a room, inside a building. Of course everything relies on the burning of fossil fuels for the electricity.

The insanity of jumping from the meat space of reality to the fluffy "clouds" where nothing is lost, everything is always online, systems are infallible is mind boggling sometimes. Solar flares come to mind.

With that said...

Layer 1 - 3: Cloud Hosting with RancherOS

This blog is /proudly/ hosted on a cheapo $10 Digital Ocean droplet(VM)

  • Stunning 1vCPU
  • Whopping 2GB memory
  • 50GB Jackpot of storage

I rolled the dice and decided to provision a RancherOS instance for the purpose of hosting various public resources, such as this Ghost blog. So far I haven't turned this into IaC (infrastructure-as-code), beyond a docker-compose file, but that's the next step.

This is my first experience using RancherOS and it is different from their standard k8s (kubernetes) orchestration solution which is just "Rancher" - slightly confusing and hard to distinguish between in search results and documentation.
Turns out you can run Rancher on RancherOS:
https://rancher.com/docs/os/v1.2/en/running-rancher-on-rancheros/

However, after a small learning curve, I'm fairly happy with it. On initial deployment the default username is rancher - RancherOS comes extremely "minimized" in terms of size and niceties available on the shell. There is a shell made available for SSH (and Console) - but by default it is sandboxed... because... RancherOS is built entirely using containers.

That's right. pid 1 in RancherOS is a docker daemon:

  PID TTY      STAT   TIME COMMAND
    1 ?        Sl     4:56 system-dockerd
...

root@rancheros-s-1vcpu-2gb-nyc1-01:~# system-docker ps
CONTAINER ID        IMAGE                              COMMAND                  CREATED             STATUS              PORTS               NAMES
ebbcd318eeca        rancher/os-ubuntuconsole:v1.4.2    "/usr/bin/ros entr..."   3 days ago          Up 3 days                               console
e1ef4cabe316        rancher/os-docker:18.03.1          "ros user-docker"        7 days ago          Up 2 days                               docker
90f67e22fbc3        rancher/os-base:v1.4.2             "/usr/bin/ros entr..."   7 days ago          Up 3 days                               ntp
c1cfc6445ec1        rancher/os-base:v1.4.2             "/usr/bin/ros entr..."   7 days ago          Up 3 days                               network
4a436a57dc89        rancher/os-base:v1.4.2             "/usr/bin/ros entr..."   7 days ago          Up 3 days                               udev
16841e6f22cf        rancher/container-crontab:v0.4.0   "container-crontab"      7 days ago          Up 3 days                               system-cron
2a172c46b39a        rancher/os-acpid:v1.4.2            "/usr/bin/ros entr..."   7 days ago          Up 3 days                               acpid
d643e44fecfd        rancher/os-syslog:v1.4.2           "/usr/bin/entrypoi..."   7 days ago          Up 3 days                               syslog

As you may have noticed there, I replaced the default sandboxed busybox with a persistent Ubuntu console as outlined here.

Setting up the persistent Ubuntu console also gives you access to apt as you would normally expect. I was able to override the Digital Ocean monitoring agent to work on this (despite RancherOS being unlisted/unsupported).

Now, looking closer you can see there are actually 2 docker daemons running, and looking at the output above, you'll note that the "os-docker" runs from the "system-docker"

root         1  0.1  1.6 540736 33256 ?        Sl   Oct26   4:56 system-dockerd --exec-root /var/run/system-docker --group root --graph /var/lib/system-docker --pidfile /var/run/system-docker.pid --restart=false --config-file /etc/docker/system-docker.json --bip 172.18.42.1/16 --storage-driver overlay2 --userland-proxy=false --log-opt max-file=2 --log-opt max-size=25m --host unix:///var/run/system-docker.sock

root     25452  0.2  3.4 771744 69904 ?        Ssl  Oct27   7:30 dockerd --host unix:///var/run/docker.sock --log-opt max-file=2 --log-opt max-size=25m --group docker

Ultimately, this gives us a pretty typical docker experience as the default user, which is part of the standard docker group, and has access to the "os-docker" instance transparently via docker

Since I switched this to an Ubuntu console, I was also able to install
docker-compose locally. I went that route instead of picking up rancher-compose which is a separate tool, and I'm not entirely sure if it's related to RancherOS or just "Rancher".

Layer 4 - 5: NginX

I am using nginx as a frontend load balancer for this site, hosted of course as a container. This is the only container that exposes ports, everything else is linked (in docker-compose.yml) for hostname resolution and then configured in the nginx.conf for proxying.

I set it up this way to abstract any single function (ie. this site or a different site) as a unique container, allowing unique resource limitations and flexible administration without affecting other functions.

Docker compose snippet:

version: '3'
services:
  lb:
    image: "nginx:alpine"
    restart: unless-stopped
    ports:
     - "80:80"
     - "443:443"
    volumes:
     - ./lb-nginx.conf:/etc/nginx/conf.d/default.conf
    links:
     - ghost
    networks:
     - backend
##
## Individual site containers
##
  ghost:
    image: ghost
    restart: unless-stopped
    volumes:
     - ./ghost/content:/var/lib/ghost/content
    environment:
     - url=http://linux.icu
    networks:
     - backend
networks:
  backend:

Layer 6-7: Ghost Blog

Ghost blog is a NodeJS based application that provides a simple, direct blogging interface. For example, most everything happens in the Admin UI located at:
<site url>/ghost

The benefit of this is that you have a consistent interface to work in across desktop and mobile. Drafts are automatically saved, so you can jot stuff down frequently.

This is compared to SSG (Static Site Generator) solutions such as Jekyll hosted on GitHub Pages, which requires making git commits to update the site.
Jekyll is awesome and I have used it for my online resume at: https://gabe.tech

So far I am using the default theme, Casper, since I find it very clean and neat. I would prefer a darker theme, and something that condenses information a bit more.