Public request
Internet → Cloudflare
:80 / :443
Kamal Proxy
TLS via Let's Encrypt
app.<domain>
Your web app
news.<domain>
Beacon
<domain>, www.<domain>
Marketing site
Every project we take on lands on the same layout. We could invent a new one each time. We don’t, because a layout you’ve seen fifty times is a layout you can fix at two in the morning.
One project, one server
Each client gets a dedicated machine of their own. Nobody else’s code runs on it. There’s no shared cluster, no noisy neighbour, no “logical isolation” that turns out to be a label in a config file. The hardware, the address and the disks belong to one team.
That’s also how we keep the door open. If you decide to run things yourself, or hire someone else, we hand over the keys: root access, the data, the backups and the repository that describes the whole setup. Nothing in the design ties you to us.
One front door, separate rooms
Kamal Proxy sits on ports 80 and 443. It fetches certificates from Let’s Encrypt, handles TLS, and sends each request to the right app based on the hostname:
app.<domain>→ your web app (the product itself)status.<domain>→ a status page (so customers know what’s happening)<domain>andwww.<domain>→ your marketing site
Each app runs in its own Docker container. Containers can’t reach each other’s ports, and they don’t share data unless we wire it up on purpose. Restart one and the rest carry on.
Why we build it this way
It’s easy to reason about. The full picture fits on a single whiteboard. A request goes from the internet to the proxy to a container. That’s it.
It moves. The setup is a handful of containers, some config files and a backup. All of it is open source. A new engineer can pick it up without a tour guide.
It has fewer seams. Things tend to break where two systems meet. We keep the meeting points to a minimum, so the whole thing stays small enough for one person to understand.
We live in it too. Shipped runs on exactly this layout. This website, our project tracker and our internal tools sit on a server built the way this page describes.
