Ansible playbook for provisioning and maintaining my personal workstation and server environments.
Install Galaxy dependencies:
ansible-galaxy install -r roles/requirements.ymlRun the playbook:
ansible-playbook playbook.yml -KRoles live in roles/ and are applied via playbook.yml. Each role installs and configures a specific tool or application.
Roles are tested with Molecule using Docker containers and Testinfra for verification.
- Docker
- Python 3
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements-test.txtRun all roles with molecule tests:
make testRun tests for a specific role:
make test ROLE=gh-cliRun individual stages (useful during development):
make converge ROLE=bottom # run the role
make verify ROLE=bottom # run testinfra tests
make destroy ROLE=bottom # tear down the containerAlternatively, run molecule directly from the role directory:
cd roles/<role-name>
molecule testNot all roles have molecule tests yet. Roles with tests have a molecule/default/ directory containing:
molecule.yml— platform config (driver, provisioner, verifier, and test sequence are inherited from.config/molecule/config.yml)converge.yml— playbook that applies the roletests/test_default.py— testinfra assertionsprepare.yml(optional) — pre-test setup (e.g. installing dependencies)
Some roles adapt their behavior based on environment variables:
| Variable | Role | Effect |
|---|---|---|
GH_TOKEN |
gh-cli |
When set, gh extensions are installed and tested. When unset, extension tasks and tests are skipped gracefully. |
To run gh-cli tests with extension coverage:
GH_TOKEN=ghp_xxx molecule test-
Create the molecule scenario directory:
roles/<role-name>/molecule/default/ -
Add
molecule.yml(only platforms — shared config is auto-discovered from.config/molecule/config.yml):--- platforms: - name: <role-name> image: geerlingguy/docker-ubuntu2204-ansible:latest privileged: true pre_build_image: true
-
Add
converge.yml:--- - name: Converge hosts: all become: true roles: - role: "{{ playbook_dir }}/../.."
-
Add
tests/test_default.pywith testinfra assertions:def test_binary_exists(host): binary = host.file("/usr/bin/<tool>") assert binary.exists assert binary.is_file
-
Run
make test ROLE=<role-name>from the repo root.