This repo is an Ansible control project; site.yml is the primary playbook orchestrating roles under roles/. Each role keeps tasks, handlers, and templates in its standard subfolders; consult roles/<role>/README.md before changing behavior. Global defaults live in group_vars/all/, host-specific overrides go in host_vars/, and inventory definitions sit in inventory/hosts.ini. Targeted verification plays such as test-docker.yml, test-atuin.yml, and test-rust.yml exercise individual stacks. Shared dependencies are pinned in requirements.yml.
Run ansible-galaxy collection install -r requirements.yml to sync Ansible collections before provisioning. Use ansible-playbook -i inventory/hosts.ini site.yml --ask-vault-pass for a full install, or add --limit and --tags when iterating on specific hosts or roles. Validate lint and syntax with ansible-lint roles/* and ansible-playbook site.yml --syntax-check. For dry runs, append --check (e.g., ansible-playbook -i inventory/hosts.ini test-docker.yml --check) to confirm idempotence without changes.
Write YAML with two-space indentation, aligning lists under their parent keys, and keep dictionaries alphabetical when practical. Variables are snake_case; role names and tags mirror their directory names (cli_tools, tailscale). Always provide descriptive name fields for tasks and prefer include_role over ad-hoc tasks for reuse. Jinja expressions use spaced braces ({{ var }}), and templates belong inside the owning role’s templates/ directory.
Treat ansible-playbook site.yml --check --ask-vault-pass as your regression gate before opening a PR. Component test plays follow the test-<focus>.yml naming pattern—run them with the production inventory but a --limit pointing at staging. Maintain lint cleanliness with ansible-lint and capture module-level issues early with ansible-playbook site.yml --syntax-check. Document new roles with smoke-test instructions in their README.md.
Commit history follows Conventional Commits with scoped prefixes (feat(config):, refactor(core):), so match that style and keep messages under 72 characters in the subject line. Each PR should explain the motivation, impacted roles, toggled tags, and reference any linked issues. Paste the exact commands you ran for validation (lint, check mode, targeted tests) and note vault or inventory changes for reviewers. Request at least one maintainer review before merging and update docs whenever behavior or defaults change.
Never commit decrypted secrets; edit group_vars/all/vault.yml via ansible-vault edit and share passwords out-of-band. Verify external downloads through existing GPG tasks rather than introducing curl pipes. When introducing new credentials or endpoints, add them to group_vars/all/versions.yml or vault.yml instead of hardcoding values in roles.