One repo for your Windows, Ubuntu, and macOS machines
Four machines: a Windows + WSL gaming PC, an Ubuntu laptop, a macOS work laptop, and a personal Mac. You want the same shell, aliases, and git setup on all of them, but each differs. The gaming PC needs WSL and your Kubernetes tooling; the work Mac uses your work email and work repos; the Ubuntu laptop is your daily dev box. One repo handles all four.
All three platforms
Dotfiles Pro applies your Ubuntu, macOS, and Windows/WSL machines from one repo. macOS uses the macos role (Homebrew) in place of ubuntu, with ansible_facts.os_family guards on the shared roles. Even the docker role runs on macOS (via colima); offering more container runtimes there is on the roadmap.
The shape: a shared baseline, per-machine overrides
This is the many layout, for a fleet, vars live in group_vars/ and host_vars/, and the role list is data-driven, so each machine runs its own set:
mydotfiles/
inventory.yaml # every machine, by hostname
group_vars/all.yaml # the baseline every machine gets
host_vars/
game-pc.yaml # Windows + WSL
ubuntu-laptop.yaml # Ubuntu
work-mac.yaml # macOS (work)
home-mac.yaml # macOS (personal)
playbook.yaml
requirements.ymlThe baseline — what every machine shares
---
# group_vars/all.yaml — OS-neutral roles every machine shares. The OS base
# (ubuntu/macos) is not here; the playbook applies it per host from facts.
ansible_roles_all:
- dotpro
- ssh
- git
- starship
git_config:
user:
name: Your Name
email: you@personal.comThe shell framework, aliases, the dotpro commands, your SSH keys, git config, and the Starship prompt, identical everywhere.
The OS base itself isn't in this shared list, each machine needs a different one. The playbook applies it per host from gathered facts (the macos role on a Mac, ubuntu elsewhere), so a new machine gets the right base with no extra config.
Per machine — what each one adds
Each machine adds to the baseline via roles_extra (its own roles, merged onto ansible_roles_all); dicts like git_config merge, so a host overrides only the keys it cares about:
---
# host_vars/game-pc.yaml: Windows + WSL
roles_extra:
- wsl
- windows
- docker
- kubernetes
- googlecloud---
# host_vars/ubuntu-laptop.yaml: your daily dev box
shell: zsh # off-diagonal: zsh on Linux (defaults to bash; macOS defaults to zsh)
roles_extra:
- docker
- terraform
- opentofu---
# host_vars/work-mac.yaml: macOS, work identity (the macos base is applied
# automatically from facts; this host only adds its extra roles and identity)
roles_extra:
- docker
- kubernetes
- aws
git_config:
user:
email: you@work.com # work email on this machine only
git_repositories:
work-project: git@github.com:yourorg/work-project.git---
# host_vars/home-mac.yaml: macOS, personal — no extra roles, just the shared
# baseline plus the macos base the playbook applies automatically from facts
roles_extra: []The game-pc picks up the WSL role, wsl.conf, Windows shims, and WSLENV bridging so Windows-side Lens authenticates to GKE through WSL, plus the Windows role to manage the Windows half itself (winget apps, registry, virtual desktops, hotkeyed workspaces). The work-mac overrides only user.email, so your work commits use your work address while everything else stays shared.
Running it
On each machine, the same command applies that machine, --limit $(hostname) picks up its host_vars automatically:
dotpro applyAdd a machine by dropping a host_vars/<hostname>.yaml and listing it in inventory.yaml. Nothing else changes.
Next steps
- Configuration the full
single→multiple→manyprogression - Managing dotfiles across machines the model this builds on
- macOS role how the Homebrew-based macOS setup works