{"id":4652,"date":"2025-11-25T18:08:24","date_gmt":"2025-11-25T18:08:24","guid":{"rendered":"https:\/\/www.it-react.com\/?p=4652"},"modified":"2025-12-06T11:56:12","modified_gmt":"2025-12-06T11:56:12","slug":"building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware","status":"publish","type":"post","link":"https:\/\/www.it-react.com\/index.php\/2025\/11\/25\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\/","title":{"rendered":"Building a Multi-OS Provisioning and Configuration Framework with Ansible and VMware (1st part)"},"content":{"rendered":"\n<p>If you\u2019ve ever deployed a VM in vSphere and caught yourself thinking, \u201cThere must be a faster way to do this,\u201d you\u2019re definitely not alone. After clicking through the same wizard more times than I\u2019d like to admit, I decided it was time to build something cleaner, smarter, and fully automated.<\/p>\n\n\n\n<p>In this series, I\u2019ll walk through how I built a multi-OS provisioning and configuration framework using Ansible and VMware\u2014flexible enough to handle Linux servers, Windows Server, and even Windows clients.<\/p>\n\n\n\n<p>We\u2019ll cover the full workflow:<\/p>\n\n\n\n<p>\u2013 structuring a clean and scalable Ansible repository<br>\u2013 provisioning VMs from vSphere templates<br>\u2013 bootstrapping access with SSH keys or WinRM<br>\u2013 applying OS-specific configuration logic (Debian, RedHat, Windows)<br>\u2013 integrating the workflow with manual triggers or CI\/CD pipelines<\/p>\n\n\n\n<p>The goal is simple: save time, reduce repetitive work, and deploy consistent, ready-to-use systems with a single command.<\/p>\n\n\n\n<p>So grab your favorite drink, open the terminal, and let\u2019s get started.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Project Overview<\/h2>\n\n\n\n<p>Before diving into templates, roles, and automation magic, it\u2019s important to understand what this project is trying to accomplish. The goal is simple: build a unified automation framework that can provision and configure multiple operating systems on VMware\u2014cleanly, consistently, and without the usual copy-paste chaos.<\/p>\n\n\n\n<p>At its core, the framework follows three guiding principles:<\/p>\n\n\n\n<p><strong>1. Separation of concerns<\/strong><br>Provisioning, configuration, OS logic, and environment-specific data each live in their own clearly defined place. This keeps the repository clean and prevents the \u201cspaghetti Ansible\u201d effect we\u2019ve all seen at least once.<\/p>\n\n\n\n<p><strong>2. OS-agnostic high-level workflow<\/strong><br>Whether you\u2019re deploying a Debian-based server, a RedHat box, a Windows Server instance, or even a Windows client, the overall flow stays the same. What changes is only the OS-specific logic underneath.<\/p>\n\n\n\n<p><strong>3. Environment-based inventories<\/strong><br>The structure remains identical across lab, test, and production. Only the data\u2014like hostnames, credentials, templates, or datastores\u2014changes per environment.<\/p>\n\n\n\n<p>From a high-level perspective, the automation workflow looks like this:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Provision a VM from a vSphere template<\/strong><br>A clean, pre-configured golden image (Linux or Windows) is cloned and customized automatically.<\/li>\n\n\n\n<li><strong>Apply static network configuration<\/strong><br>Each VM receives a predefined static IP address, subnet, gateway and DNS configuration based on its host_vars definition. The same data is later used by Ansible to connect to the system for post-provisioning tasks.<\/li>\n\n\n\n<li><strong>Bootstrap remote access<\/strong>\n<ul class=\"wp-block-list\">\n<li>For Linux: install the public SSH key for the automation user<\/li>\n\n\n\n<li>For Windows: enable and configure WinRM<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Apply OS-specific configuration<\/strong><br>Package installation, baseline settings, services, domain join (for Windows), or any custom logic you want to enforce.<\/li>\n\n\n\n<li><strong>Extend with application-level automation<\/strong><br>Optional steps such as deploying agents, monitoring exporters, middleware, or full application stacks.<\/li>\n\n\n\n<li><strong>Integrate with CI\/CD<\/strong><br>The entire workflow can run manually or be fully automated through GitLab CI, Jenkins, or any other pipeline.<\/li>\n<\/ol>\n\n\n\n<p>The end result is a flexible and scalable provisioning framework that eliminates repetitive tasks, enforces consistency, and makes spinning up new systems feel like a quick, predictable operation rather than an endless sequence of manual steps.<\/p>\n\n\n\n<p>With the overview in place, it\u2019s time to walk through the repository structure and start building the framework piece by piece.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Creating the Base Repository Layout<\/h2>\n\n\n\n<p>A clean and predictable repository layout is essential for any automation project\u2014especially when dealing with multiple operating systems and several environments. The structure below keeps provisioning, configuration, variables, and OS-specific logic separated in a way that scales well as the framework grows.<\/p>\n\n\n\n<p>Here is the high-level directory layout used in this project:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>infra-ansible\/\n\u251c\u2500\u2500 ansible.cfg\n\u251c\u2500\u2500 collections\/\n\u2502   \u2514\u2500\u2500 requirements.yml\n\u251c\u2500\u2500 inventories\/\n\u2502   \u251c\u2500\u2500 lab\/\n\u2502   \u2502   \u251c\u2500\u2500 inventory.yml\n\u2502   \u2502   \u2514\u2500\u2500 group_vars\/\n\u2502   \u2502       \u251c\u2500\u2500 all.yml\n\u2502   \u2502       \u251c\u2500\u2500 linux_debian.yml\n\u2502   \u2502       \u251c\u2500\u2500 linux_redhat.yml\n\u2502   \u2502       \u251c\u2500\u2500 win_servers.yml\n\u2502   \u2502       \u2514\u2500\u2500 win_clients.yml\n\u2502   \u251c\u2500\u2500 test\/\n\u2502   \u2514\u2500\u2500 prod\/\n\u251c\u2500\u2500 playbooks\/\n\u2502   \u251c\u2500\u2500 provision\/\n\u2502   \u2502   \u251c\u2500\u2500 vmware_linux_debian.yml\n\u2502   \u2502   \u2514\u2500\u2500 vmware_windows_server.yml\n\u2502   \u251c\u2500\u2500 configure\/\n\u2502   \u2502   \u251c\u2500\u2500 linux_base.yml\n\u2502   \u2502   \u2514\u2500\u2500 windows_base.yml\n\u2502   \u251c\u2500\u2500 patch\/\n\u2502   \u2514\u2500\u2500 stacks\/\n\u251c\u2500\u2500 roles\/\n\u2502   \u251c\u2500\u2500 os_linux_base\/\n\u2502   \u251c\u2500\u2500 os_windows_base\/\n\u2502   \u251c\u2500\u2500 vmware_guest_provision\/\n\u2502   \u2514\u2500\u2500 monitoring\/\n\u251c\u2500\u2500 vars\/\n\u2502   \u251c\u2500\u2500 vm_sizes.yml\n\u2502   \u2514\u2500\u2500 images.yml\n\u2514\u2500\u2500 docs\/\n    \u251c\u2500\u2500 architecture.md\n    \u2514\u2500\u2500 runbooks.md<\/code><\/pre>\n\n\n\n<p>The sections below explain how each part is created and why it exists.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1: Create the Repository Folder<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir infra-ansible\ncd infra-ansible<\/code><\/pre>\n\n\n\n<p>This will be our root directory for the entire automation framework.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Step 2: Create the Core Folder Structure<\/h3>\n\n\n\n<p>Inside the repository, create all the necessary directories:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir -p collections\nmkdir -p inventories\/lab\nmkdir -p playbooks\/{provision,configure,patch,stacks}\nmkdir -p roles\nmkdir -p vars\nmkdir -p docs<\/code><\/pre>\n\n\n\n<p>Each directory has a specific purpose:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>collections\/<\/strong> \u2013 holds external Ansible collections<\/li>\n\n\n\n<li><strong>inventories\/<\/strong> \u2013 separate inventories for each environment (lab\/test\/prod)<\/li>\n\n\n\n<li><strong>playbooks\/<\/strong> \u2013 provisioning, configuration, patching, and stack-level automation<\/li>\n\n\n\n<li><strong>roles\/<\/strong> \u2013 reusable logic (OS-specific, provisioning, monitoring, etc.)<\/li>\n\n\n\n<li><strong>vars\/<\/strong> \u2013 shared variables such as template names<\/li>\n\n\n\n<li><strong>docs\/<\/strong> \u2013 architecture notes and operational runbooks<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Step 3: Create ansible.cfg<\/h3>\n\n\n\n<p>This file ensures that Ansible knows where to find roles, collections, and the default inventory.<\/p>\n\n\n\n<p>Create it at the repository root:<\/p>\n\n\n\n<p><strong>ansible.cfg<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;defaults]\ninventory = inventories\/lab\/inventory.yml\nroles_path = roles\ncollections_path = collections\nhost_key_checking = False\nretry_files_enabled = False\ndeprecation_warnings = False<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Step 4: Define Required Collections<\/h3>\n\n\n\n<p>The automation relies on a few Ansible collections, such as:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>community.vmware provides the VMware modules we use to clone VMs, customize guests, and run commands inside the VM through VMware Tools.<\/li>\n\n\n\n<li>ansible.windows contains the core Windows modules such as win_ping, win_file, win_optional_feature, and win_reboot.<\/li>\n\n\n\n<li>community.windows adds additional Windows-related functionality from the community ecosystem.<\/li>\n\n\n\n<li>microsoft.ad gives us the microsoft.ad.membership module, which we will use later to join Windows machines to Active Directory in a clean, supported way.<\/li>\n<\/ul>\n\n\n\n<p>Create the requirements file:<\/p>\n\n\n\n<p><strong>collections\/requirements.yml<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>collections:\n  - name: community.vmware\n  - name: ansible.windows\n  - name: community.windows\n  - name: microsoft.ad<\/code><\/pre>\n\n\n\n<p>At this stage we are only defining which collections the framework depends on. The actual installation of these collections will be done later, from within a dedicated Python virtual environment, to avoid version conflicts with the system-wide Ansible installation.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Step 5: Create the Inventory Structure<\/h3>\n\n\n\n<p>We begin with a <strong>lab<\/strong> environment and a clean OS-oriented grouping.<\/p>\n\n\n\n<p>Create:<\/p>\n\n\n\n<p><strong>inventories\/lab\/inventory.yml<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Root inventory structure\nall:\n  children:\n\n    # Debian-based Linux servers (Debian, Ubuntu)\n    linux_debian:\n      hosts: {}\n\n    # RedHat-based Linux servers (RHEL, Rocky, AlmaLinux, CentOS)\n    linux_redhat:\n      hosts: {}\n\n    # Windows Server machines\n    win_servers:\n      hosts: {}\n\n    # Windows Client machines (Windows 10\/11)\n    win_clients:\n      hosts: {}\n\n    # Group containing all Linux systems (Debian + RedHat)\n    linux:\n      children:\n        linux_debian: {}\n        linux_redhat: {}\n\n    # Group containing all Windows systems (Servers + Clients)\n    windows:\n      children:\n        win_servers: {}\n        win_clients: {}\n\n    # vCenter endpoint\n    vcenter:\n      hosts: {}<\/code><\/pre>\n\n\n\n<p>This layout allows us to target:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Debian-only<\/li>\n\n\n\n<li>RedHat-only<\/li>\n\n\n\n<li>All Linux<\/li>\n\n\n\n<li>Only Windows Server<\/li>\n\n\n\n<li>All Windows<\/li>\n\n\n\n<li>vCenter<\/li>\n<\/ul>\n\n\n\n<p>without duplicating logic.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Step 6: Create group_vars for Each OS Family<\/h3>\n\n\n\n<p>Each OS type gets its own variables file.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Debian Linux<\/h4>\n\n\n\n<p><strong>inventories\/lab\/group_vars\/linux_debian.yml<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Settings specific to Debian-based Linux systems (Debian, Ubuntu)\nansible_connection: ssh\nansible_user: \"ansible\"\nansible_become: true\nansible_become_method: sudo\n\nlinux_package_manager: \"apt\"\nlinux_common_packages:\n  - curl\n  - vim\n  - htop<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">RedHat Linux<\/h4>\n\n\n\n<p><strong>inventories\/lab\/group_vars\/linux_redhat.yml<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Settings specific to RedHat-based Linux systems (RHEL, Rocky, AlmaLinux, CentOS)\nansible_connection: ssh\nansible_user: \"ansible\"\nansible_become: true\nansible_become_method: sudo\n\nlinux_package_manager: \"dnf\"\nlinux_common_packages:\n  - curl\n  - vim-enhanced\n  - htop<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Windows Server<\/h4>\n\n\n\n<p><strong>inventories\/lab\/group_vars\/win_servers.yml<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Placeholder for future Windows Server group settings\n#\n# This file is intentionally empty for now.  \n# When multiple Windows Server hosts are introduced, \n# shared configuration (baseline policies, defaults, \n# package lists, WinRM options, role mappings, etc.)\n# can be added here instead of duplicating them in host_vars.<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Windows Clients<\/h4>\n\n\n\n<p><strong>inventories\/lab\/group_vars\/win_clients.yml<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Placeholder for future Windows Client group settings\n#\n# At this stage, all configuration for Windows 10 is \n# host-specific, so this file remains empty.\n#\n# As the environment expands (multiple workstations, shared \n# hardening rules, security policies, software baselines, \n# or centralized parameters), this file will become the \n# natural location for settings that apply to all Windows \n# client VMs.<\/code><\/pre>\n\n\n\n<p><strong>Note: Why Keep These Files If They\u2019re Empty?<\/strong><\/p>\n\n\n\n<p>Because a mature automation environment evolves.<br>Today you may have a single Windows client and no Windows servers \u2014 but later you might add:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>20 Windows workstations<\/li>\n\n\n\n<li>several Windows Server VMs<\/li>\n\n\n\n<li>common security settings<\/li>\n\n\n\n<li>shared WinRM defaults<\/li>\n\n\n\n<li>policies applicable to all Windows machines<\/li>\n<\/ul>\n\n\n\n<p>When that moment comes, you will not want to refactor your repository.<br>The structure will already be in place.<\/p>\n\n\n\n<p>Keeping group_vars empty-but-ready is the cleanest way to support future expansion.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">vCenter Connection Configuration<\/h4>\n\n\n\n<p><strong>inventories\/lab\/group_vars\/vcenter.yml<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># vCenter API connection settings\n\nansible_connection: local\n\nvcenter_hostname: \"vcsa.racklab.local\"\nvcenter_username: \"ansible@vsphere.local\"\nvcenter_password: \"{{ vault_vcenter_password }}\"\nvcenter_validate_certs: false<\/code><\/pre>\n\n\n\n<p>A few important notes:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The password is securely stored in <strong>Ansible Vault<\/strong> and never in plain text.<\/li>\n\n\n\n<li>The <code>ansible_connection: local<\/code> setting ensures that provisioning tasks run on the Ansible control node instead of a remote host.<\/li>\n<\/ul>\n\n\n\n<p>This separation keeps the configuration clean, avoids duplication, and allows each VM to define its own provisioning metadata in a separate location.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Step 7: Create the Linux Base Role<\/h3>\n\n\n\n<p>We create one role that works for both Debian and RedHat families.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">defaults<\/h4>\n\n\n\n<p><strong>roles\/os_linux_base\/defaults\/main.yml<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Default variables for Linux base configuration\nlinux_base_packages_extra: &#91;]<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">main entry point<\/h4>\n\n\n\n<p><strong>roles\/os_linux_base\/tasks\/main.yml<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Main entry point for os_linux_base role\n\n- name: Include Debian-family tasks\n  include_tasks: debian.yml\n  when: ansible_os_family == \"Debian\"\n\n- name: Include RedHat-family tasks\n  include_tasks: redhat.yml\n  when: ansible_os_family == \"RedHat\"<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Debian logic<\/h4>\n\n\n\n<p><strong>roles\/os_linux_base\/tasks\/debian.yml<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Base configuration for Debian-based systems\n\n- name: Update APT cache\n  apt:\n    update_cache: true\n    cache_valid_time: 3600\n\n- name: Install common packages on Debian systems\n  apt:\n    name: \"{{ linux_common_packages + linux_base_packages_extra }}\"\n    state: present<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">RedHat logic<\/h4>\n\n\n\n<p><strong>roles\/os_linux_base\/tasks\/redhat.yml<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Base configuration for RedHat-based systems\n\n- name: Ensure DNF metadata is up to date\n  dnf:\n    update_cache: true\n\n- name: Install common packages on RedHat systems\n  dnf:\n    name: \"{{ linux_common_packages + linux_base_packages_extra }}\"\n    state: present<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Step 8: Create Central Template Mapping<\/h3>\n\n\n\n<p>Each operating system family (Debian, RedHat, Windows Server, Windows Client) uses its own golden image stored in vSphere. To avoid hardcoding template names inside the playbooks, the framework stores them in a central variable file.<\/p>\n\n\n\n<p>Create the following file:<\/p>\n\n\n\n<p><strong>vars\/templates.yml<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Template names used for OS provisioning\n\nlinux_debian_template: \"ubuntu-22-base\"\nlinux_redhat_template: \"rockylinux-9-base\"\nwin_server_template: \"win2022-golden\"\nwin_client_template: \"win10-template-no-sysprep\"<\/code><\/pre>\n\n\n\n<p>Why store template names separately?<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Playbooks remain clean and OS-agnostic<\/li>\n\n\n\n<li>Changing a template requires editing only one file<\/li>\n\n\n\n<li>Different environments (lab\/test\/prod) can override templates if needed<\/li>\n\n\n\n<li>Provisioning logic becomes reusable across multiple systems<\/li>\n<\/ul>\n\n\n\n<p>During provisioning, the appropriate template is selected by referencing these variables instead of embedding string literals.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Using a Python virtual environment for Ansible and installing collections<\/h2>\n\n\n\n<p>On most Linux distributions, Ansible packages are available directly from the system repositories. While this is convenient, it often leads to version mismatches between ansible-core and external collections such as community.vmware. To keep this framework stable and reproducible, all Ansible commands are executed from a dedicated Python virtual environment.<\/p>\n\n\n\n<p>This has a few important advantages:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>we control the exact ansible-core version used by the project<\/li>\n\n\n\n<li>we can install additional Python libraries (pyvmomi, requests, etc.) without touching the system Python<\/li>\n\n\n\n<li>Ansible collections are installed in an isolated environment, avoiding conflicts with system-wide installations<\/li>\n<\/ul>\n\n\n\n<p>The setup is straightforward. From the repository root:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cd ~\/infra-ansible\npython3 -m venv .venv\nsource .venv\/bin\/activate<\/code><\/pre>\n\n\n\n<p>Next, upgrade pip and install the required Python packages inside the virtual environment:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>pip install --upgrade pip\npip install ansible-core pyvmomi requests<\/code><\/pre>\n\n\n\n<p>With Ansible installed in the virtualenv, you can now install the collections defined earlier in collections\/requirements.yml:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ansible-galaxy collection install -r collections\/requirements.yml<\/code><\/pre>\n\n\n\n<p>From this point on, every Ansible command related to this project should be executed from the virtual environment:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>source .venv\/bin\/activate\ncd ~\/infra-ansible\nansible-playbook ...<\/code><\/pre>\n\n\n\n<p>If you skip the virtual environment and run Ansible from the system packages, you may run into compatibility issues between ansible-core and the community.vmware collection, leading to errors such as missing support modules or StrictVersion import problems.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Using Ansible Vault for Secure Credentials<\/h2>\n\n\n\n<p>When you start automating VMware and Windows deployments, there\u2019s one thing you absolutely don\u2019t want floating around in plain text: <strong>passwords<\/strong>.<br>vCenter passwords, Windows local admin passwords, domain join credentials, service accounts\u2026 All perfect candidates for leaking into Git history and ruining your day.<\/p>\n\n\n\n<p>That\u2019s where <strong>Ansible Vault<\/strong> comes in.<\/p>\n\n\n\n<p>Vault lets you store sensitive variables in encrypted files and keep your repository clean, safe, and shareable. Everything looks like YAML, but the content is encrypted. Ansible decrypts it automatically at runtime when you pass the vault password.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What We Store in Vault<\/h3>\n\n\n\n<p>In this project, the Vault holds:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>the vCenter administrator password<br><code>vault_vcenter_password<\/code><\/li>\n\n\n\n<li>the Windows local administrator password (used for WinRM bootstrap and later for user creation)<br><code>vault_win_admin_password<\/code><\/li>\n<\/ul>\n\n\n\n<p>Basically: <em>anything that makes a security auditor raise an eyebrow<\/em>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Where We Store the Vault and Why<\/h3>\n\n\n\n<p>All sensitive values live in:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>inventories\/lab\/group_vars\/all\/vault.yml<\/code><\/pre>\n\n\n\n<p>Putting the Vault inside <code>group_vars\/all\/<\/code> has a big advantage:<br><strong>Ansible loads it automatically for every playbook and every host.<\/strong><br>This means:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>we don\u2019t need <code>vars_files:<\/code> everywhere<\/li>\n\n\n\n<li>ad-hoc commands like <code>ansible HOST -m win_ping<\/code> also get access to the encrypted values<\/li>\n\n\n\n<li>credentials stay in one central, predictable location<\/li>\n<\/ul>\n\n\n\n<p>This layout keeps things clean, avoids accidental leaks in inventory files, and makes the entire project easier to reason about \u2014 exactly what you want when working with VMware automation, WinRM bootstrap, and multi-OS provisioning.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Creating the Vault File<\/h3>\n\n\n\n<p>We initialize the vault like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ansible-vault create inventories\/lab\/group_vars\/all\/vault.yml<\/code><\/pre>\n\n\n\n<p>Ansible asks for a vault password (you\u2019ll use the same one later with <code>--ask-vault-pass<\/code>).<br>Inside the file, we add our encrypted variables:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>vault_vcenter_password: \"YourVCPasswordHere\"\nvault_win_admin_password: \"YourWindowsPasswordHere\"<\/code><\/pre>\n\n\n\n<p>Once saved, the file on disk is fully encrypted and unreadable.<\/p>\n\n\n\n<p>If we ever need to edit the values:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ansible-vault edit inventories\/lab\/group_vars\/all\/vault.yml<\/code><\/pre>\n\n\n\n<p>If you want to view it (read-only):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ansible-vault view inventories\/lab\/group_vars\/all\/vault.yml<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Using Vault Variables in Playbooks<\/h3>\n\n\n\n<p>We never store plaintext passwords in playbooks or inventory.<br>Instead, we reference the encrypted values like any other variable:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>vcenter_password: \"{{ vault_vcenter_password }}\"\nansible_password: \"{{ vault_win_admin_password }}\"<\/code><\/pre>\n\n\n\n<p>Ansible decrypts everything on the fly when you run:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ansible-playbook ... --ask-vault-pass<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Wrap-Up<\/h2>\n\n\n\n<p>In this first part, we focused entirely on building the foundation of our automation framework: a clean repository layout, structured inventories, OS-specific group variables, secure vCenter settings, and a central mapping for all base templates. With these pieces in place, the project is now ready for actual provisioning work.<\/p>\n\n\n\n<p>In the next post, we\u2019ll take the first real step: deploying a Windows 10 virtual machine from a vSphere template using the structure we created here. We\u2019ll define the VM\u2019s metadata, assign a static IP address, set the correct network adapter, and build the full provisioning playbook.<\/p>\n\n\n\n<p>Now that the framework is prepared, we can finally start putting it to use. Stay tuned for Part 2: <em>Provisioning a Windows 10 Client from a vSphere Template<\/em>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>If you\u2019ve ever deployed a VM in vSphere and caught yourself thinking, \u201cThere must be a faster way to do this,\u201d you\u2019re definitely not alone. After clicking through the same wizard more times than I\u2019d like to admit, I decided it was time to build something cleaner, smarter, and fully automated. In this series, I\u2019ll [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":4654,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"_FSMCFIC_featured_image_caption":"","_FSMCFIC_featured_image_nocaption":"","_FSMCFIC_featured_image_hide":"","footnotes":""},"categories":[7,15,8],"tags":[94,25,31,26,36],"class_list":["post-4652","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-linux","category-vmware","category-windows","tag-ansible","tag-vcenter","tag-vm","tag-vmware","tag-vsphere"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Building a Multi-OS Provisioning and Configuration Framework with Ansible and VMware (1st part) - IT-REACT<\/title>\n<meta name=\"description\" content=\"vmware ansible automatization\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.it-react.com\/index.php\/2025\/11\/25\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Building a Multi-OS Provisioning and Configuration Framework with Ansible and VMware (1st part) - IT-REACT\" \/>\n<meta property=\"og:description\" content=\"vmware ansible automatization\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.it-react.com\/index.php\/2025\/11\/25\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\/\" \/>\n<meta property=\"og:site_name\" content=\"IT-REACT\" \/>\n<meta property=\"article:published_time\" content=\"2025-11-25T18:08:24+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-12-06T11:56:12+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.it-react.com\/wp-content\/uploads\/2025\/11\/vishal-vasnani-QMhF0-q8oKg-unsplash-e1763730592241.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1024\" \/>\n\t<meta property=\"og:image:height\" content=\"540\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Ioan Penu\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Ioan Penu\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.it-react.com\\\/index.php\\\/2025\\\/11\\\/25\\\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.it-react.com\\\/index.php\\\/2025\\\/11\\\/25\\\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\\\/\"},\"author\":{\"name\":\"Ioan Penu\",\"@id\":\"https:\\\/\\\/www.it-react.com\\\/#\\\/schema\\\/person\\\/bf08cffeb4b02ee6baff5d56ab17c8f0\"},\"headline\":\"Building a Multi-OS Provisioning and Configuration Framework with Ansible and VMware (1st part)\",\"datePublished\":\"2025-11-25T18:08:24+00:00\",\"dateModified\":\"2025-12-06T11:56:12+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.it-react.com\\\/index.php\\\/2025\\\/11\\\/25\\\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\\\/\"},\"wordCount\":1871,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.it-react.com\\\/#\\\/schema\\\/person\\\/bf08cffeb4b02ee6baff5d56ab17c8f0\"},\"image\":{\"@id\":\"https:\\\/\\\/www.it-react.com\\\/index.php\\\/2025\\\/11\\\/25\\\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.it-react.com\\\/wp-content\\\/uploads\\\/2025\\\/11\\\/vishal-vasnani-QMhF0-q8oKg-unsplash-e1763730592241.jpg\",\"keywords\":[\"ansible\",\"vCenter\",\"VM\",\"VMWare\",\"vSphere\"],\"articleSection\":[\"Linux\",\"VMWare\",\"Windows\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.it-react.com\\\/index.php\\\/2025\\\/11\\\/25\\\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.it-react.com\\\/index.php\\\/2025\\\/11\\\/25\\\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\\\/\",\"url\":\"https:\\\/\\\/www.it-react.com\\\/index.php\\\/2025\\\/11\\\/25\\\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\\\/\",\"name\":\"Building a Multi-OS Provisioning and Configuration Framework with Ansible and VMware (1st part) - IT-REACT\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.it-react.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.it-react.com\\\/index.php\\\/2025\\\/11\\\/25\\\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.it-react.com\\\/index.php\\\/2025\\\/11\\\/25\\\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.it-react.com\\\/wp-content\\\/uploads\\\/2025\\\/11\\\/vishal-vasnani-QMhF0-q8oKg-unsplash-e1763730592241.jpg\",\"datePublished\":\"2025-11-25T18:08:24+00:00\",\"dateModified\":\"2025-12-06T11:56:12+00:00\",\"description\":\"vmware ansible automatization\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.it-react.com\\\/index.php\\\/2025\\\/11\\\/25\\\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.it-react.com\\\/index.php\\\/2025\\\/11\\\/25\\\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.it-react.com\\\/index.php\\\/2025\\\/11\\\/25\\\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.it-react.com\\\/wp-content\\\/uploads\\\/2025\\\/11\\\/vishal-vasnani-QMhF0-q8oKg-unsplash-e1763730592241.jpg\",\"contentUrl\":\"https:\\\/\\\/www.it-react.com\\\/wp-content\\\/uploads\\\/2025\\\/11\\\/vishal-vasnani-QMhF0-q8oKg-unsplash-e1763730592241.jpg\",\"width\":1024,\"height\":540,\"caption\":\"Photo by Vishal Vasnani\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.it-react.com\\\/index.php\\\/2025\\\/11\\\/25\\\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.it-react.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Building a Multi-OS Provisioning and Configuration Framework with Ansible and VMware (1st part)\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.it-react.com\\\/#website\",\"url\":\"https:\\\/\\\/www.it-react.com\\\/\",\"name\":\"it-react\",\"description\":\"Ctrl\u2022Alt\u2022Automate\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.it-react.com\\\/#\\\/schema\\\/person\\\/bf08cffeb4b02ee6baff5d56ab17c8f0\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.it-react.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.it-react.com\\\/#\\\/schema\\\/person\\\/bf08cffeb4b02ee6baff5d56ab17c8f0\",\"name\":\"Ioan Penu\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/2a2a1b6be0f322a113eea11669895227e284c6091424d65be6c3c706c2822975?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/2a2a1b6be0f322a113eea11669895227e284c6091424d65be6c3c706c2822975?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/2a2a1b6be0f322a113eea11669895227e284c6091424d65be6c3c706c2822975?s=96&d=mm&r=g\",\"caption\":\"Ioan Penu\"},\"logo\":{\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/2a2a1b6be0f322a113eea11669895227e284c6091424d65be6c3c706c2822975?s=96&d=mm&r=g\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Building a Multi-OS Provisioning and Configuration Framework with Ansible and VMware (1st part) - IT-REACT","description":"vmware ansible automatization","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.it-react.com\/index.php\/2025\/11\/25\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\/","og_locale":"en_US","og_type":"article","og_title":"Building a Multi-OS Provisioning and Configuration Framework with Ansible and VMware (1st part) - IT-REACT","og_description":"vmware ansible automatization","og_url":"https:\/\/www.it-react.com\/index.php\/2025\/11\/25\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\/","og_site_name":"IT-REACT","article_published_time":"2025-11-25T18:08:24+00:00","article_modified_time":"2025-12-06T11:56:12+00:00","og_image":[{"width":1024,"height":540,"url":"https:\/\/www.it-react.com\/wp-content\/uploads\/2025\/11\/vishal-vasnani-QMhF0-q8oKg-unsplash-e1763730592241.jpg","type":"image\/jpeg"}],"author":"Ioan Penu","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Ioan Penu","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.it-react.com\/index.php\/2025\/11\/25\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\/#article","isPartOf":{"@id":"https:\/\/www.it-react.com\/index.php\/2025\/11\/25\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\/"},"author":{"name":"Ioan Penu","@id":"https:\/\/www.it-react.com\/#\/schema\/person\/bf08cffeb4b02ee6baff5d56ab17c8f0"},"headline":"Building a Multi-OS Provisioning and Configuration Framework with Ansible and VMware (1st part)","datePublished":"2025-11-25T18:08:24+00:00","dateModified":"2025-12-06T11:56:12+00:00","mainEntityOfPage":{"@id":"https:\/\/www.it-react.com\/index.php\/2025\/11\/25\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\/"},"wordCount":1871,"commentCount":0,"publisher":{"@id":"https:\/\/www.it-react.com\/#\/schema\/person\/bf08cffeb4b02ee6baff5d56ab17c8f0"},"image":{"@id":"https:\/\/www.it-react.com\/index.php\/2025\/11\/25\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\/#primaryimage"},"thumbnailUrl":"https:\/\/www.it-react.com\/wp-content\/uploads\/2025\/11\/vishal-vasnani-QMhF0-q8oKg-unsplash-e1763730592241.jpg","keywords":["ansible","vCenter","VM","VMWare","vSphere"],"articleSection":["Linux","VMWare","Windows"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.it-react.com\/index.php\/2025\/11\/25\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.it-react.com\/index.php\/2025\/11\/25\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\/","url":"https:\/\/www.it-react.com\/index.php\/2025\/11\/25\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\/","name":"Building a Multi-OS Provisioning and Configuration Framework with Ansible and VMware (1st part) - IT-REACT","isPartOf":{"@id":"https:\/\/www.it-react.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.it-react.com\/index.php\/2025\/11\/25\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\/#primaryimage"},"image":{"@id":"https:\/\/www.it-react.com\/index.php\/2025\/11\/25\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\/#primaryimage"},"thumbnailUrl":"https:\/\/www.it-react.com\/wp-content\/uploads\/2025\/11\/vishal-vasnani-QMhF0-q8oKg-unsplash-e1763730592241.jpg","datePublished":"2025-11-25T18:08:24+00:00","dateModified":"2025-12-06T11:56:12+00:00","description":"vmware ansible automatization","breadcrumb":{"@id":"https:\/\/www.it-react.com\/index.php\/2025\/11\/25\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.it-react.com\/index.php\/2025\/11\/25\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.it-react.com\/index.php\/2025\/11\/25\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\/#primaryimage","url":"https:\/\/www.it-react.com\/wp-content\/uploads\/2025\/11\/vishal-vasnani-QMhF0-q8oKg-unsplash-e1763730592241.jpg","contentUrl":"https:\/\/www.it-react.com\/wp-content\/uploads\/2025\/11\/vishal-vasnani-QMhF0-q8oKg-unsplash-e1763730592241.jpg","width":1024,"height":540,"caption":"Photo by Vishal Vasnani"},{"@type":"BreadcrumbList","@id":"https:\/\/www.it-react.com\/index.php\/2025\/11\/25\/building-a-multi-os-provisioning-and-configuration-framework-with-ansible-and-vmware\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.it-react.com\/"},{"@type":"ListItem","position":2,"name":"Building a Multi-OS Provisioning and Configuration Framework with Ansible and VMware (1st part)"}]},{"@type":"WebSite","@id":"https:\/\/www.it-react.com\/#website","url":"https:\/\/www.it-react.com\/","name":"it-react","description":"Ctrl\u2022Alt\u2022Automate","publisher":{"@id":"https:\/\/www.it-react.com\/#\/schema\/person\/bf08cffeb4b02ee6baff5d56ab17c8f0"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.it-react.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.it-react.com\/#\/schema\/person\/bf08cffeb4b02ee6baff5d56ab17c8f0","name":"Ioan Penu","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/2a2a1b6be0f322a113eea11669895227e284c6091424d65be6c3c706c2822975?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/2a2a1b6be0f322a113eea11669895227e284c6091424d65be6c3c706c2822975?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/2a2a1b6be0f322a113eea11669895227e284c6091424d65be6c3c706c2822975?s=96&d=mm&r=g","caption":"Ioan Penu"},"logo":{"@id":"https:\/\/secure.gravatar.com\/avatar\/2a2a1b6be0f322a113eea11669895227e284c6091424d65be6c3c706c2822975?s=96&d=mm&r=g"}}]}},"_links":{"self":[{"href":"https:\/\/www.it-react.com\/index.php\/wp-json\/wp\/v2\/posts\/4652","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.it-react.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.it-react.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.it-react.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.it-react.com\/index.php\/wp-json\/wp\/v2\/comments?post=4652"}],"version-history":[{"count":17,"href":"https:\/\/www.it-react.com\/index.php\/wp-json\/wp\/v2\/posts\/4652\/revisions"}],"predecessor-version":[{"id":4713,"href":"https:\/\/www.it-react.com\/index.php\/wp-json\/wp\/v2\/posts\/4652\/revisions\/4713"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.it-react.com\/index.php\/wp-json\/wp\/v2\/media\/4654"}],"wp:attachment":[{"href":"https:\/\/www.it-react.com\/index.php\/wp-json\/wp\/v2\/media?parent=4652"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.it-react.com\/index.php\/wp-json\/wp\/v2\/categories?post=4652"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.it-react.com\/index.php\/wp-json\/wp\/v2\/tags?post=4652"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}