An automated infrastructure-as-code (IaC) and dotfiles repository to bootstrap, configure, and maintain Linux workstations, headless servers, Proxmox virtualization guests, macOS devices, and Windows environments using Ansible (ansible-pull / ansible-playbook) and standalone within my homelab. Although some of the parts are written by AI, I debug, test and validate extensively on multiple machines. You can fork, modify and use this repository as your own. (and I will not be liable if you brick your machines).
- Overview & Architecture
- Supported Platforms
- Repository Structure
- Prerequisites
- 1-Line Quick Start (Installers)
- Manual Step-by-Step Installation
- Roles & Features
- Useful Ansible Tags
- Alerts & Monitoring
- Periodic Provisioning & Cron
- Troubleshooting & Distro Notes
Ansible Machine provisions machines using a pull or push workflow:
graph TD
Node[Target Machine] -->|1. bootstrap.sh / bootstrap.ps1| Init[Bootstrap Tooling & Deps]
Init -->|2. ansible-pull / git clone| Repo[Ansible Machine Repo]
Repo -->|3. Evaluate hosts.yml| LocalYml[local.yml]
LocalYml --> Base[Role: base<br/>Users, SSH, Dotfiles, System Tuning]
LocalYml --> Workstation[Role: workstation<br/>GUI, Brave, Steam, Sunshine, XRDP, Snaps/Flatpaks]
LocalYml --> Server[Role: server<br/>Cockpit, QEMU/Spice Agents, Unattended Upgrades]
LocalYml --> Alerts[Post-tasks<br/>Telegram & Healthchecks.io Alerts]
- Idempotent & Modular: Each role encapsulates its own tasks, variables, files, and handlers.
- Push or Pull Mode: Ideal for local pull bootstrapping (
ansible-pull) or centralized orchestrations (ansible-playbook). - Cross-Platform: Configures Linux distributions (Ubuntu, Debian, Linux Mint), macOS (dotfiles/shell), and Windows (PowerShell profile & modular scripts).
| Platform / OS | Scope / Features | Execution Method |
|---|---|---|
| Ubuntu / Debian / Linux Mint | Full system provisioning (Base + Workstation or Base + Server) | bootstrap.sh, ansible-pull, or ansible-playbook |
| macOS (Darwin) | Dotfiles, Zsh configuration & plugins, Vim bundles, newsyslog | bootstrap.sh -m or ansible-pull --tags mac |
| Windows 10/11 | Modular PowerShell profile, custom aliases, utilities, prompt | bootstrap.ps1 or roles/base/tasks/software/windows_dotfiles.yml |
| Proxmox VMs / Guests | Headless server packages, QEMU Guest Agent, SPICE VDagent | ansible-pull or ansible-playbook |
ansible-machine/
βββ ansible.cfg # Default Ansible configuration (inventory, logging, pipelining)
βββ hosts.yml # Inventory defining host groups and host variables
βββ local.yml # Main playbook entry point orchestrating roles and plays
βββ bootstrap.sh # Interactive / automated Bash bootstrap script (Linux & macOS)
βββ bootstrap.ps1 # Standalone PowerShell bootstrap script (Windows)
βββ agent.json # Agent workspace metadata
βββ collections/
β βββ requirements.yml # Galaxy dependencies (ansible.posix, community.general)
βββ group_vars/
β βββ all.yml # Global variables (Telegram bot tokens, Healthchecks UUIDs)
βββ playbooks/
β βββ send_completion_alert.yml # Telegram & Healthchecks.io success notifications
β βββ send_failure_alert.yml # Telegram failure notifications with task details
βββ roles/
βββ base/ # Core system settings, users, dotfiles, base packages
βββ workstation/ # GUI applications, desktop environments, gaming, streaming
βββ server/ # Server management, virtualization agents, unattended upgrades
Before running the installers or playbooks on Debian / Ubuntu / Linux Mint systems:
# Update package cache and install core prerequisites
sudo apt update && sudo apt install -y zsh curl git pipx python3-passlib
# (Optional) Install Oh My Zsh
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
# Install Ansible via pipx and inject passlib
pipx install --include-deps ansible
pipx ensurepath
pipx inject ansible passlib
source ~/.zshrc # or source ~/.bashrcNote
On newer Ubuntu releases (e.g. 24.04 / 26.04+), if sudo alternatives need to be set to classic binaries:
sudo update-alternatives --set sudo /usr/bin/sudo.wsDownloads and executes bootstrap.sh to install dependencies, ensure your hostname is defined inhosts.yml, set up collections, and run ansible-pull:
curl -fsSL https://raw.githubusercontent.com/brootware/ansible-machine/refs/heads/main/bootstrap.sh -o bootstrap.sh && chmod +x bootstrap.sh
./bootstrap.shApplies only shell dotfiles (Zsh, Bash, Vim, Tmux, Git) for a specified user without modifying system users or packages:
./bootstrap.sh -dBootstraps shell dotfiles and configurations tailored for macOS:
./bootstrap.sh -mInstalls the modular PowerShell profile, aliases, environment helpers, and custom prompt directly into your Documents\WindowsPowerShell:
irm https://raw.githubusercontent.com/brootware/ansible-machine/refs/heads/main/bootstrap.ps1 | iexSet sudo password and ansible galaxy requirements
# Set root password (required if using the su become method)
sudo passwd root
# Install required Ansible Galaxy collections
ansible-galaxy collection install ansible.posix community.generalEnsure your machine's hostname (hostname or hostname -f) is registered in hosts.yml under the appropriate group:
workstation:
hosts:
minty.bruteware.cc: {}
buntu:
gnome: true
ansible_become_method: su
IdeaPad-Flex-5-14ALC05:
gnome: true
ansible_become_method: su
macbookm2:
mac: true
server:
hosts:
mediabox.bruteware.cc: {}
gitrunner.bruteware.cc: {}
proxmoxhosts:
hosts:
10.0.0.12:
proxmox_instance: trueExecute the playbook locally using ansible-pull:
# Full provision (prompts for become/root password and brootware user password)
ansible-pull -U https://github.com/brootware/ansible-machine.git -K -e "user_passwd=$(read -sp 'Enter password: ' p && echo $p)"
# Dotfiles only
ansible-pull -U https://github.com/brootware/ansible-machine.git -K --tags "onlydotfiles" -e "target_username=$(whoami) target_group=$(id -gn) target_user_home=$HOME"
# macOS only
ansible-pull -U https://github.com/brootware/ansible-machine.git -K --tags "mac" -vvIf running against local or remote hosts from a cloned repository:
# Run locally on current machine
ansible-playbook -i hosts.yml local.yml -K -e "user_passwd=yourpassword"
# Run for a specific host group (e.g. workstations)
ansible-playbook -i hosts.yml local.yml --limit workstation -KThe foundation applied to all Linux hosts:
- User & Access Management: Configures
brootware,root, andgoodeggaccounts, sudoers entries (/etc/sudoers.d/), and SSH authorized keys (ed25519/rsa). - SSH Hardening: Deploys a hardened
sshd_configtemplate and/etc/issue.netbanner. - Dotfiles & Shell: Installs managed configurations for Bash, Zsh (modular configs, themes, plugins), Vim (Pathogen, color schemes, Syntastic, NERDTree, CtrlP), Tmux (Continuum, Resurrect), Git, Htop, and MC.
- System Tuning:
earlyoomdaemon installation and activation for low-memory protection.- Swappiness optimization (
vm.swappiness = 5). - Automatic microcode updates (Intel / AMD).
- Time synchronization via
systemd-timesyncdand timezone setting (Asia/Singapore). - Systemd Journal log retention policy (
MaxFileSec=5day). - Locale generation (
en_US.UTF-8).
- Package Management:
- Utilities:
curl,htop,iotop,lsof,mc,mosh,ncdu,nmap,ranger,rsync,screen,sshfs,tmux,fastfetch/neofetch,vim-nox,zsh. - Development tools:
git,tig,fabric,flake8,python3,python3-pip,python3-virtualenv,ruby,rake. - Cleanup: Removes unnecessary packages like
nano,cowsay,exim4.
- Utilities:
Designed for desktop workstations:
- Desktop Environments:
- GNOME: Nautilus file manager enhancements (list view, tree view, single-click to launch, permanent delete option).
- MATE / Cinnamon: Appearance and session integration.
- Applications & Streaming:
- Brave Browser: GPG key, repository setup, and Wayland touchpad gesture flags.
- Steam Gaming: Multiarch
i386activation, license acceptance,steam-devices, and Mesa Vulkan drivers (mesa-vulkan-drivers). - Sunshine: Game streaming server package installation and systemd user service setup.
- XRDP Remote Desktop: Remote desktop server configured for Cinnamon/Xsessions + UFW port 3389 allow.
- App Distribution:
- Snaps (Ubuntu): VS Code, Telegram Desktop, Signal Desktop, Foliate.
- Flatpaks (Linux Mint): Signal, DΓ©jΓ Dup, Telegram, Flatseal, Foliate, Sunshine.
- User Configs:
bpytop.conf, SSH client configuration.
Designed for headless infrastructure and Proxmox VMs:
- Management Console: Installs and starts Cockpit (
cockpit) on port 9090. - Proxmox Virtualization Guests: Installs and enables
qemu-guest-agentandspice-vdagentwhenproxmox_instance: true. - Security & Maintenance: Automated system security updates via
unattended-upgradesand optional UFW firewall policies.
Run specific parts of the configuration using --tags or skip using --skip-tags:
| Tag | Purpose / Target |
|---|---|
base |
Run all base system tasks and configurations |
workstation |
Run workstation-specific apps, desktop configs, and games |
server |
Run server management and virtualization tasks |
onlydotfiles |
Deploy user dotfiles (Zsh, Vim, Tmux, Bash, Git) without altering system packages |
mac |
Deploy macOS-compatible dotfiles and configurations |
windows / powershell |
Deploy Windows PowerShell dotfiles and profile scripts |
users / brootware / goodegg |
Configure user accounts, groups, and SSH keys |
ssh / openssh |
Configure SSH server daemon and client settings |
cron |
Configure periodic automated Ansible cron jobs |
packages |
Install or update system utilities and development packages |
steam / gaming |
Install Steam, 32-bit libraries, and Vulkan drivers |
gnome / nautilus |
Apply GNOME and Nautilus desktop preferences |
Ansible Machine includes built-in reporting hooks in playbooks/send_completion_alert.yml and playbooks/send_failure_alert.yml:
- Telegram Alerts:
- Sends a success notification upon completion.
- Sends a detailed error report on failure including failed task name, action, and JSON error response.
- Healthchecks.io Ping:
- Pings a Healthchecks.io endpoint to confirm scheduled cron jobs completed successfully.
Configure your credentials in group_vars/all.yml:
telegram_chat_id: "YOUR_TELEGRAM_CHAT_ID"
telegram_token: "YOUR_TELEGRAM_BOT_TOKEN"
healthcheck_uuid: "YOUR_HEALTHCHECKS_IO_UUID"When the base role runs, it renders a standalone runner script to /usr/local/bin/provision (from provision.sh.j2) and configures a cron job:
- Schedule: Executes
/usr/local/bin/provisionevery 30 minutes. - Power Management Inhibition: Uses
systemd-inhibitto prevent sleep or system disruption during an active run. - Reboot Refresh: Clears
~/.ansiblecache on boot.
- Password Prompts:
ansible-pull -Kprompts for thesudo/subecome password.-e "user_passwd=..."provides the cleartext password that is SHA-512 hashed by Ansible for user creation.
- Passlib Error on Modern Ubuntu/Debian:
- If you encounter
passlib is requirederrors, installpython3-passliband runpipx inject ansible passlib.
- If you encounter
- Root Password for
suBecome Method:- Some hosts in
hosts.ymluseansible_become_method: su. Ensure a root password is set (sudo passwd root).
- Some hosts in
- Brave Browser Touchpad Gestures:
- The workstation role configures Wayland flags (
--ozone-platform=wayland --enable-features=TouchpadOverscrollHistoryNavigation) for smooth 2-finger navigation.
- The workstation role configures Wayland flags (