29 Jun 2026 (7 hours old) |
8477 words
· 0 LoC,
~43 min read
Linux maintenance becomes much easier once you stop seeing the system as one opaque machine and start seeing layers: firmware, bootloader, kernel, init system, filesystems, userspace, shell, services, logs, processes, networking, storage, and permissions. A failure usually belongs to one of those layers, and each layer leaves evidence.
Linux is also unusually discoverable. Most classic tools have a manual page, many commands provide concise --help output, and the system exposes a great deal of its own state through logs and virtual filesystems. You do not need to memorize every flag. You need to know where to look, how to read the output, and how to move from one clue to the next.
Read this compendium as a map, not as a giant list to memorize. Start with the layer that best matches the symptom, inspect the evidence, and follow it.
Read more
27 Jun 2026 (2 days old) |
4219 words
· 0 LoC,
~22 min read
Engineers spend a remarkable amount of time arguing about tools.
Should we use Renovate or Dependabot? Kubernetes or a simpler container platform? Flux or Argo CD? Terraform or OpenTofu? Helm, Kustomize, Docker, GitHub Actions, GitLab CI, Jenkins, Backstage—the list is endless, and every tool has enthusiastic supporters and experienced critics.
Those discussions are not useless. Tools have different capabilities, constraints, costs, and failure modes. But “Is this tool good?” is rarely the most important question.
The same problem appears when teams discuss processes. Someone proposes mandatory approvals, new push rules, another release gate, a branching policy, or a change board because it sounds mature or because another company does it. A process is adopted before anyone has defined which concrete failure it should prevent.
The better questions apply equally to tools and processes: What problem are we solving? Which system behavior should change? How easy will the new flow be to follow and automate? What will happen when it fails? Who will own it? Most importantly, how will we measure whether it worked?
That is the thinking behind my famous formula:
Speed = Process + Automation
Read more
27 Jun 2026 (2 days old) |
4327 words
· 0 LoC,
~22 min read
Keeping dependencies current is healthy engineering.
Old dependencies accumulate security issues, compatibility problems, unsupported APIs, and migration work. Small updates that could have been routine become large upgrade projects after a team ignores them for two years. Nobody seriously argues that letting dependencies rot forever is a good strategy.
But nobody wants developers to spend every morning manually reviewing five patch releases, three lockfile refreshes, two base-image updates, and another minor version of a linting plugin.
Renovate appears to solve that problem neatly: discover updates, open merge requests, keep the project current. In practice, a default installation without policy or reliable automation can quickly become dependency spam. Merge requests pile up, developers become annoyed, and the updates slowly rot somewhere on the roadside.
The real dealbreaker is not Renovate. It is the quality of the pipeline around it. Renovate does not create engineering discipline. It exposes whether a team already has enough discipline and automation to handle continuous change.
Read more
27 Jun 2026 (2 days old) |
3167 words
· 0 LoC,
~16 min read
Using branches as environments sounds attractive at first.
A dev branch, a test branch, a staging branch, and a prod branch feel simple, visible, and comfortable. Developers merge into dev, testers approve what reaches test, and production receives whatever is finally merged into prod. The branch names appear to show exactly where software is in the delivery process.
It looks like control.
In many organizations, however, this model does not remove complexity. It hides complexity until it returns in uglier forms: drift between environments, unclear release states, repeated cherry-picking, back-merges, forgotten hotfixes, merge conflicts at the worst possible moment, and uncertainty about what was actually tested versus what is running in production.
That is why I recommend trunk-based development as the default for modern delivery. Code should flow through one main branch. Short-lived branches may represent work in progress, but environments should represent deployment state, not separate code realities.
Read more
27 Jun 2026 (2 days old) |
3439 words
· 0 LoC,
~18 min read
Infrastructure used to be full of stories that began with, “Ask Alex, they know how that server works.”
Someone had installed a package over SSH, changed a configuration file during an incident, added a cron job six months later, and opened a firewall port that nobody documented. The server might have been stable for years, but its real configuration existed partly on disk, partly in a ticket system, and partly in one person’s memory.
We improved this model with scripts, configuration management, Infrastructure as Code, and immutable images. GitOps takes the next step: it turns Git into the reviewed and versioned declaration of what our systems should look like, then uses software agents to continuously reconcile reality with that declaration.
That makes GitOps much more than “YAML in a repository.” It is an operating model for making infrastructure visible, reproducible, auditable, and less dependent on privileged individuals.
Read more