In short

Until October 12, our websites ran on two different stacks. The company and product sites were hand-built PHP, each one a copy of the same shared setup that we maintained by hand. The two documentation sites were MkDocs with the Material theme. We moved all of them to HotDog CMS, our own open-source site builder, in one afternoon and evening, about seven and a half hours.

Every site now ships as plain files from the same small, locked-down web server. No language runtime runs when someone visits a page. Across the nine sites, the software we deploy is 64% smaller, and the known vulnerabilities in each site's image dropped from 48 (37 for the docs) to 4. All 449 documentation pages kept their addresses and their links.

What we moved

Site Was Pages Now
cairnobs.org Hand-built PHP 2 HotDog
coffeylabs.org Hand-built PHP 22 HotDog
ihasvpn.org Hand-built PHP 2 HotDog
ihasmail.org Hand-built PHP 2 HotDog
inbuxa.org Hand-built PHP, asked our git server for the latest release on every visit 2 HotDog, rebuilt when a release comes out
jcoffey.dev, the founder's blog Hand-built PHP with server-side search 1,753 HotDog, search in the browser
hotdogcms.org HotDog already, on the PHP image 87 HotDog on the static image
docs.ihasmail.org MkDocs + Material 19 HotDog, in ihasmail.org's design
docs.inbuxa.org MkDocs + Material 430 HotDog, in inbuxa.org's design

The PHP sites were mostly static pages passed through PHP: a header, a footer and a sitemap written in code, the same on every site, copied by hand whenever one changed. That repetition is why HotDog exists in the first place.

How long it took

All times are Arizona time on October 12.

Time What
3:14 pm Start on cairnobs.org
3:53 pm cairnobs.org live on HotDog, with the new static image built for it
3:56 pm hotdogcms.org moved onto the same image
4:17 pm The image hardened: not root, no capabilities, read-only
4:31 pm Start on the other five sites
4:55 pm coffeylabs.org live
5:08 pm ihasvpn.org live
5:17 pm ihasmail.org live
5:35 pm jcoffey.dev live, with its statistics behind a consent banner
5:46 pm inbuxa.org live
7:50 pm Start on the documentation features HotDog was missing
9:00 pm HotDog CMS 0.3.0 released with them
9:25 pm hotdogcms.org's own docs live with the new navigation
9:39 pm docs.ihasmail.org live
9:52 pm docs.inbuxa.org live, all 430 pages
10:45 pm Loose ends done; HotDog 0.3.2 and 0.3.3 released

The first site took 39 minutes, most of it building the static image every site now shares. After that, a site took between 9 and 28 minutes from start to live. The five product and company sites took an hour and a quarter together. The 430-page documentation site took about a quarter of an hour, once the smaller docs site had settled the design both share.

Some honesty about the clock. It started with the engine already written: HotDog was built on October 10 and 11, and three of these sites were ported as trial runs then, which is how we knew the output would match. The gap in the early evening was other work. And AI did a lot of the typing, as it does across our code; every change still went through a pull request and the same automated checks as any other.

What HotDog gained

The documentation sites needed things HotDog didn't have, so we built them into HotDog rather than into the two sites. Anyone running HotDog gets them in version 0.3:

  • MkDocs' writing syntax: notes and warnings, collapsible sections, content tabs, keyboard keys, definition lists, attributes on links and pictures, and Markdown inside HTML.
  • Links between source files: write ../install/linux.md#docker and HotDog links to the page; a link to a page that doesn't exist is an error in hotdog-cms check.
  • Navigation of any depth from one file, with breadcrumbs, previous and next links, and an icon and color per section.
  • "On this page" and search results that land on a section, not just a page.
  • hotdog-cms import mkdocs, which keeps MkDocs' heading anchors so links into the docs from anywhere else still land.
  • Faster builds: social preview images are drawn in parallel and reused, taking a 519-page build from 17.2 seconds to 1.9 seconds, and 72 milliseconds when nothing changed.
  • Locked-down containers: both of HotDog's container images, nginx and Caddy, run with every Linux capability dropped (0.3.3).

The documentation sites also got a new design, built from their product sites' own header, footer and colors: a sidebar with an icon per section, a search box on Ctrl K that searches headings as well as pages, and a contents rail that follows you down the page. Everything except search works without JavaScript.

Nothing moved

A script compared every page of both MkDocs sites, as MkDocs built them, with the HotDog build: the list of pages, every title, every heading anchor in order, every link (checked to exist), and the visible text. All 449 pages kept their address, title, anchors and links, and the text matches apart from code highlighting, which HotDog doesn't do yet. The comparison caught what our unit tests hadn't, including 71 pages whose anchors MkDocs and HotDog spelled differently. Those were fixed in HotDog before release.

Security

PHP sites before MkDocs sites before All nine now
Code that runs per request PHP, on every page and every 404 (17 files, 1,184 lines on cairnobs.org) none none
Language runtime PHP 8.4, 35 extensions, php-fpm none (Python only at build time) none
Known vulnerabilities in the image 48, 13 high 37, 12 high 4, 2 high
Runs as root, for the main processes root an unprivileged user
Linux capabilities Docker's defaults Docker's defaults none, and no way to gain any
Writable space /tmp and /run; a program written there could run the same /tmp only; nothing written there can run
Memory and process limits none none 256 MB, 128 processes
Content Security Policy none none a strict one: scripts and styles from the site only

All nine already ran with a read-only root filesystem; that part didn't change.

Vulnerability counts are from Grype, scanning each site's image on the day of the move. Most of the old high-severity findings were in OpenSSL. The new image is built up from nothing but nginx and what it needs, and the four findings that remain are in the C library, zlib and nginx itself.

The bigger change isn't in the table. A PHP site is a program, and a program can have bugs. A folder of HTML files can't be talked into running anything.

Three live problems were fixed on the way: example email addresses in the docs showed as "[email protected]" because our CDN was hiding them; one docs site's robots.txt pointed search engines at the other's sitemap; and hotdogcms.org was publishing a handful of numbered pages nothing linked to.

Size on disk

Site Before After
cairnobs.org 134 MB 22 MB
coffeylabs.org 140 MB 29 MB
ihasvpn.org 135 MB 24 MB
ihasmail.org 137 MB 27 MB
inbuxa.org 149 MB 25 MB
jcoffey.dev 138 MB 125 MB
hotdogcms.org 242 MB 131 MB
docs.ihasmail.org 101 MB 26 MB
docs.inbuxa.org 134 MB 58 MB
All nine 1,310 MB 468 MB

These are the container images each site ships as. Where a site is mostly its own content, the content is now most of the image: jcoffey.dev carries 1,753 pre-built pages and their pictures, hotdogcms.org its tutorial videos, and docs.inbuxa.org 26 MB of screenshots. The five other PHP sites fell by 79% to 83%.

Each former PHP site also uses less memory when running: about 8 MB and 9 processes, down from about 19 MB and 12.

Performance

The PHP sites were already fast at the server, under a millisecond a page, because they did very little. The one that did real work, jcoffey.dev, went from 8.4 ms to 0.6 ms a page.

The documentation sites got lighter for the reader, because Material's JavaScript, search worker and web fonts are gone:

Page Before After
docs.inbuxa.org, home 495 KB, 18 requests 88 KB, 11 requests
docs.inbuxa.org, a long page 563 KB, 19 requests 156 KB, 12 requests
docs.ihasmail.org, home 309 KB, 16 requests 231 KB, 10 requests
docs.ihasmail.org, a long page 322 KB, 24 requests 242 KB, 10 requests

Load times measured in a browser from Arizona went down for most sites, by up to half for some. They also swing by a few hundred milliseconds from one run to the next, so we don't claim a speed-up from them; the weight and request counts above are what we'd point to.

Builds are quick enough to stop thinking about. The 430-page docs site imports from MkDocs in 0.09 seconds and builds in under a second.

What went wrong

Not everything went first time. Class names in the new docs design collided with the product sites' stylesheets and pushed a footer off the screen. A deploy check archived the wrong folder and stopped the first docs deploy before it reached a server. HotDog left empty folders in builds and kept HTML entities in imported titles. HotDog's Caddy image wouldn't start with every capability dropped. Each of these was caught by a check before it reached a visitor, and each is fixed: the HotDog ones in releases 0.3.2 and 0.3.3.

Doing it yourself

None of this is specific to us. HotDog's docs have the method for moving a hand-built site and moving from MkDocs, and how to run the result locked down. HotDog CMS is open source and an early release; questions are welcome on the forum.

About Coffey Labs

Coffey Labs LLC is an Arizona company that builds, owns and maintains open-source infrastructure software: the inbuxa mail suite, ihasmail webmail, the ihasvpn WireGuard server, Cairn OBS log aggregation and the HotDog CMS website builder, plus the tools around them. Everything it makes runs on the user’s own hardware, is published in full under a copyleft license, and has no paid tier. Coffey Labs started in 2018 as LINUXexpert.org and was organized as an LLC in 2026. Learn more at coffeylabs.org.

Media contact

press@coffeylabs.org · Press and brand kit