Infrastructure as Code for People, Not Just Servers
A proposal: treat developer machines like any other infrastructure, with a shared baseline, personal overlays, versioned roles and a golden path that gets a new starter productive on day one.
On this page
We treat servers as cattle: declared in code, rebuilt at will, never hand-edited. Developer laptops are still mostly pets. Each one is set up by hand from a wiki page that was accurate two years ago, and each one drifts in its own direction. A new starter’s first week often goes on installing things.
I’ve automated my own machine for years (Dotfiles: An Environment That Follows Me, Provisioning My Laptop with Ansible). This note is a proposal, not a case study: what it would look like to take the same idea to a team or an organisation. I haven’t rolled this out across a team, so read it as reflection on what I’d do, built from what worked and what didn’t on my own machines.
The goal: clone, run one command, productive on day one
The test I’d hold any setup to: a new developer gets a laptop, clones one repo, runs one command, and by lunch they can build, test and run the main services. That’s a golden path for devices. It’s the same idea as the Web Accelerator I built at Elanco for new web projects: put the decisions in the starting point, not in a document.
A shared baseline plus personal overlays
The mistake would be one giant playbook that tries to make everyone’s machine identical. Developers care about their tools, and a setup that fights them gets abandoned. I’d split it in layers:
- Organisation baseline. The non-negotiables: security agent, disk encryption checks, VPN, approved runtimes, the CLI tools every repo assumes, the right git hooks.
- Team layer. What a team’s stack needs: language toolchains, local databases, cloud CLIs, editor extensions that the repo’s linting relies on.
- Personal overlay. Your dotfiles, your editor, your shell prompt. Optional, pulled from your own repo, never required.
In Ansible terms that’s roles and variables: the baseline and team layers as roles, the personal overlay as a final role that clones a dotfiles repo if you’ve set one. My own playbook already did a tiny version of this: the last task cloned my dotfiles and ran their Stow script.
Share it like code: versioned roles and collections
Copying a playbook into every team’s repo is how you get forty slightly different playbooks. Instead:
- Publish the baseline and team layers as versioned roles or a collection, in an internal Galaxy-style repository or simply tagged git repos.
- Teams pin a version and upgrade deliberately, like any other dependency.
- Changes go through pull requests and CI that applies the roles to a clean container or VM, twice, to prove they’re idempotent.
That’s the same trick that made shared front-end components work across many sites: a versioned package beats a copied template, because improvements flow to everyone instead of rotting in forks.
Where each tool fits
There isn’t one tool for this, and pretending there is causes most of the pain.
| Tool | Best at | Not great at |
|---|---|---|
| MDM (Jamf, Intune, Kandji…) | Org-wide policy: encryption, OS updates, security agents, app catalogue, compliance reporting | Developer toolchains and per-team detail; usually owned by IT, not engineers |
| Ansible | Readable, agentless, works on macOS and Linux, good for “install and configure” across layers | Exact reproducibility; it converges state rather than guaranteeing it |
| Nix / nix-darwin / Home Manager | Reproducible, declarative environments, rollbacks, per-project shells | Steep learning curve; a big ask for a whole organisation |
| Devcontainers / Codespaces | The project’s toolchain in a container, identical for everyone, laptop-agnostic | Native GUI tools, performance-sensitive work, offline use |
My rough split: MDM for policy, a provisioning tool (Ansible or Nix) for the machine baseline, devcontainers for
per-project toolchains, dotfiles for personal taste. The more you can push into the repo itself (devcontainers, version
files like .nvmrc, a make setup), the less the laptop matters at all.
Drift and self-healing
On my laptop, a cron job re-ran the playbook every ten minutes, so drift fixed itself. At organisation scale I’d be more careful:
- Report before you remediate. Run in check mode on a schedule and surface drift (a dashboard, or a message to the machine’s owner) before anything changes automatically.
- Self-heal only the baseline. Security settings and required tools can converge automatically; personal overlays never should.
- Least privilege. My personal setup gave its automation user passwordless sudo for everything. That’s not acceptable on a fleet. Scope privileges to specific commands, pull only from protected, reviewed branches, and treat the provisioning repo as production code, because it effectively is.
Secrets
No secrets in the repo, ever. The provisioning should fetch them at run time from the organisation’s secret store or the
developer’s password manager CLI, or use short-lived credentials from SSO. If something must be committed, encrypt it
with ansible-vault or SOPS, and rotate anything that ever leaked.
Optional but attractive
The best platform work I’ve seen, and the best I’ve done, wins adoption by being the easiest option, not by mandate (Internal Developer Platform, Golden Paths and the Recommended Routine). Device provisioning is no different.
- Make the baseline genuinely save time on day one, so new starters choose it.
- Let experienced developers keep their own setup, as long as the baseline checks pass.
- Measure it: time from laptop to first merged pull request is a good onboarding metric.
- Keep the docs short, because the code is the documentation.
Echoes from network automation
At Sky I worked on a low-code platform where network engineers built automation from reusable tasks, including configuration templates, wrapped as building blocks in a workflow (Building a Low-Code BPMN Workflow Platform). The lesson carries over directly: the value isn’t the automation tool, it’s packaging repeatable configuration as tested, reusable pieces that people who didn’t write them can safely use. Developer machines deserve the same treatment.
What I’d try first
If I were starting tomorrow, I’d begin small: one team, a baseline role for the tools every repo needs, a devcontainer for
the main service, and a single make setup that does both. Measure a new starter’s first week before and after. If it
works, publish the role, let the next team pin it, and grow from there. Progressive overload, not a big bang.
- #infrastructure-as-code
- #developer-experience
- #onboarding
- #golden-paths
- #ansible
- #platform-engineering
↩ Linked from (1)
…a password manager's CLI. Roles instead of loose task files, so the same pieces can be shared, which is where Infrastructure as Code for People, Not Just Servers picks up.
↪ Links to (7)
Related by topic
- Growing
Books That Shaped How I Build
Career - Growingcase study
A Resumable CMS Migration Tool
Distributed systems - Growingcase study
Building a Web Platform for 80 Sites
Platform engineering - Seed
Explore, Expand, Extract
Platform engineering