Small network. Considered systems.
Behind
the network.
How I build, deploy, and operate the AboutSharma network, explained with figures you can take apart.
Build quickly at the application layer.
Standardize aggressively underneath.
Twelve application repositories sit in a row at the top. Their deployment paths converge on a single control layer, server-infra, which validates each request, takes a lock, applies the application's role and verifies it. The paths then fan back out to twelve containers on one host, which are reached by visitors through a single Cloudflare tunnel. Each repository is a button that simulates a deployment; requests that arrive while another deployment holds the lock wait their turn.
Around thirty-eight websites and services, each in its own repository, share one way of reaching production. A single infrastructure repository describes the server, owns every deployment, and refuses to call a release successful until the site answers through its real public address. This notebook follows a change from a rough note to a verified hostname, then looks at how the server rebuilds from code and how traffic and mail find their way.
- Websites & services
- ~38
- Docker containers
- ~50
- Centrally deployed apps
- 12
- Infrastructure source
- 01
Every release starts
with an idea.
Ideas on paper. A brief with intent. Independent review. A human decision. Each actor in the loop owns a different responsibility, so the figure gives each one its own lane.
- You: rough notes on paper, a whiteboard, or a notebook.
- ChatGPT: turns the notes into a developer brief.
- Codex or Claude: implements the brief and opens a pull request on GitHub.
- Review: an automated Codex review, with an optional Gemini deep review for large or risky changes. Changes can loop back to implementation.
- You: the human approval.
- GitHub: merge to main, which requests a production deployment.
Make the intent unambiguous.
On a busy day, I move between three or four projects. I start with notes, a whiteboard, or paper. ChatGPT turns that intent into a detailed product and technical brief, leaving implementation choices to the engineering agent.
Deployment is earned.
Gate by gate.
A merge requests a deployment. It doesn't bypass the controls. Seven gates sit between a commit and the words “deployment successful”, and the last two are health checks.
- Source validation on a GitHub-hosted runner: the repository must match the application allowlist and the commit must be a full SHA.
- Production runner: the job moves to a self-hosted runner whose only privilege is one deployment command.
- Deployment lock: a global lock serializes production changes; other requests wait.
- Clean infrastructure: server-infra must have no local changes, then fast-forwards main.
- Ansible applies the application's role and its Docker Compose stack.
- Local health: the origin must return its expected marker, retried up to 15 times.
- Public health: the same marker through the real public hostname and Cloudflare.
- Only then is the deployment reported successful.
Validate the source.
The workflow accepts the app, source repository, and commit SHA. Supplied repository metadata must match the app allowlist, and a supplied SHA must be 40 hexadecimal characters.
- --.-readySelect a gate to read it, or run the sequence.
The self-hosted runner can invoke exactly one restricted deployment command. It has no general-purpose root access.
Workflow queuing and a global controller lock serialize production changes across every application.
Both checks must return the expected origin marker. A failure stops success reporting; it does not trigger an automatic rollback.
Code remembers.
People shouldn’t have to.
The server is reproducible from code, not institutional memory. One playbook sequence turns a clean host into the whole network; one role per application keeps every deployment the same shape.
- bootstrap.yml: base system, swap, web host, Docker and the connector package.
- preflight.yml: prerequisites checked, including protected configuration supplied separately.
- cloudflare.yml: the managed connector service.
- automation.yml: the production runner and the restricted deployment controller.
- deploy.yml: twelve application roles, one container stack each.
- verify.yml: the connector is active and every origin answers locally; guided setup also confirms public routes.
setup.yml defines the order. Secrets and public routes are supplied separately.
| Application role | Checkout | Build | Backup | Stack | Origin | Deep check |
|---|
- Checkout
- Repository at the requested commit
- Build
- Static build or container image
- Backup
- Application data, before anything changes
- Stack
- Docker Compose converged
- Origin
- Expected marker from the origin
- Deep check
- App-specific health beyond the marker
A running container
isn’t a healthy website.
Check the origin directly. Then check the same service through its real public hostname. Two perspectives, one release decision. Break a link below to see why it takes both.
A visitor reaches Cloudflare's edge over HTTPS. An encrypted tunnel, dialed outward from the server by a managed connector service, carries the request to a port bound only to the server's loopback interface, then to the application's nginx container, which serves an origin marker. The deployment controller runs two probes: a local probe straight to the loopback port, and a public probe that leaves the server and returns through the public hostname, Cloudflare and the tunnel.
- Local probe
- controller → loopback → origin
- —
- Public probe
- controller → hostname → edge → tunnel → origin
- —
- Release
- Waiting for both checks
- —
The expected response content matters, not just an open port or an HTTP status. A wrong site answering is a failure.
The public check traverses the hostname and Cloudflare to reach the same origin a visitor would.
Final setup verification explicitly checks that the managed Cloudflare connector is active.
Many addresses.
One mailbox.
Every role has its own public address. Behind them is one mailbox and one way of working. Mail arrives with its context, and replies leave under the address they were sent to.
Seven public addresses at aboutsharma.com appear on both sides of the figure: security, uptime, info, business, dev, refunds and no-reply. On the left, mail addressed to each of them converges on one central mailbox, where every message keeps the address it arrived on. On the right, replies leave the same mailbox and fan back out, each sent as the address its message was addressed to. Each address is a button that sends a message in and a reply out.
-
01 / Incoming
Many ways in.
Role addresses, from
security@tono-reply@, deliver into the same central mailbox. Each message keeps the address it arrived on, so context survives the merge. -
02 / Central
One place to work.
One inbox to read, search and triage, without a separate login or subscription for every role. The whole foundation is one paid mailbox at roughly $2 a month.
-
03 / Outgoing
The right name out.
Replies are sent as the identity the message was addressed to. A question to
business@is answered bybusiness@, never by a personal address.
If the shape looks familiar, it is Fig. 0 again: many independent surfaces, one control layer, nothing flattened on the way through.
Move fast.
Keep the foundations boring.
More applications shouldn’t mean more ways to deploy them. Each principle points back to the figure where it does its work.
- i
Reproducibility
A replacement server starts with a defined sequence.
Fig. 3a - ii
Least privilege
Give the runner a specific job and a restricted entry point.
Fig. 2 · gate 02 - iii
Serialized deployments
One production mutation at a time, across every project.
Fig. 2 · gate 03 - iv
Health-gated releases
Verify the origin locally, then through its public hostname.
Fig. 4 - v
Infrastructure in code
Configuration belongs in the system of record, in the same shape for every app.
Fig. 3b - vi
Human approval
Agents implement and review. A person decides to merge.
Fig. 1 - vii
Centralize operations, not identity
One place to manage many public faces, each kept intact.
Fig. 5
Different projects.
The same engineering discipline.
Notes
- Deployment, reconstruction and verification figures were checked against the server-infra repository on October 15, 2026: the deployment workflow, the centralized controller, the setup, deploy and verify playbooks, and the runner’s sudo policy.
- Interactive deployments, probes and mail traffic are explanatory simulations, not live operations or monitoring. Current service health lives on status.aboutsharma.com.
- Source metadata is optional for manual runs. SHA validation checks format; it is not a cryptographic attestation. A failed check stops success reporting and does not imply an automatic rollback.
- Scale, development habits and the email design are owner-supplied. Email is managed separately from server-infra, and pricing is approximate.
- All figures are schematic. Credentials, private addressing, ports and host configuration are deliberately omitted.
Colophon
This notebook is itself one of the twelve applications in Fig. 0. It is static HTML, CSS and SVG with one small script: no framework, no backend. It is deployed by the pipeline in Fig. 2 and verified by the checks in Fig. 4.
Set in IBM Plex Sans, IBM Plex Mono and Newsreader.