{"id":715,"date":"2024-07-13T17:11:29","date_gmt":"2024-07-13T15:11:29","guid":{"rendered":"https:\/\/www.codeschoepfer.de\/?p=715"},"modified":"2024-07-15T19:45:20","modified_gmt":"2024-07-15T17:45:20","slug":"automate-your-proxmox-vms-with-ansible","status":"publish","type":"post","link":"https:\/\/www.codeschoepfer.de\/en\/automate-your-proxmox-vms-with-ansible\/","title":{"rendered":"Automate Your Proxmox VM Deployment with Ansible"},"content":{"rendered":"<h2>Introduction<\/h2>\n<p><img decoding=\"async\" alt=\"Proxmox\" class=\"img-float-left\" src=\"https:\/\/www.codeschoepfer.de\/wp-content\/uploads\/2024\/05\/proxmox-blog-960_480.jpg\"> This article is a introduction to deploying virtual machines on the <a href=\"https:\/\/www.proxmox.com\/en\/proxmox-virtual-environment\/overview\">Proxmox VE<\/a> environment.<\/p>\n<p>First, there are multiple ways to deploy virtual machines on Proxmox. Let&#8217;s consider using <a href=\"https:\/\/www.terraform.io\/\">Terraform<\/a> as an alternative to Ansible. With Terraform, we gain state management, meaning Terraform records each activity, which is useful for clean-up later. However, Ansible offers a robust implementation of the Proxmox API. Using Ansible allows us to handle many of these tasks seamlessly without interrupting our workflow.<\/p>\n<p>We are going to demonstrate the deployment of a <a href=\"https:\/\/www.debian.org\/\">Debian GNU\/Linux<\/a> VM. To keep it simple, we will use a stripped-down Ansible role. When using Ansible, you have several options for deploying a VM, such as using a <a href=\"https:\/\/cloud.debian.org\/images\/cloud\/\">Debian Cloud Image<\/a>. However, we decided to create and use a VM template because several necessary configurations are already deployed in this template. Furthermore, we are going to use <a href=\"https:\/\/cloud-init.io\/\">cloud-init<\/a> to configure the VM for its target use.<\/p>\n<blockquote><p>\nBasic knowledge in dealing with Ansible, Proxmox and cloud-init are required.\n<\/p><\/blockquote>\n<p>We have the following file tree for this demo:<\/p>\n<pre><code class=\"language-bash\">\u279c tree\n.\n\u251c\u2500\u2500 hosts.ini\n\u251c\u2500\u2500 proxmox_create_demo_vm.yaml\n\u251c\u2500\u2500 proxmox_prepare.yaml\n\u2514\u2500\u2500 roles\n    \u251c\u2500\u2500 proxmox_create_demo_vm\n    \u2502\u00a0\u00a0 \u251c\u2500\u2500 defaults\n    \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 main.yaml\n    \u2502\u00a0\u00a0 \u251c\u2500\u2500 tasks\n    \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 main.yaml\n    \u2502\u00a0\u00a0 \u2514\u2500\u2500 templates\n    \u2502\u00a0\u00a0     \u2514\u2500\u2500 user-data.yml.j2\n    \u2514\u2500\u2500 proxmox_prepare\n        \u2514\u2500\u2500 tasks\n            \u2514\u2500\u2500 main.yaml<\/code><\/pre>\n<h2>Creating the VM template<\/h2>\n<p>Ensure you have a Proxmox VE template on your VM. If you don&#8217;t have one, create it by right-clicking on the VM and selecting <code>Convert to template<\/code> We will be working with a template named <code>Debian12<\/code> furtherdown.<\/p>\n<blockquote><p>\nPlease ensure that your VM supports cloud-init, which should be the case, if you have a recent installation.\n<\/p><\/blockquote>\n<h2>Prepare Proxmox<\/h2>\n<p>We need a wrapper to control the Proxmox API called <a href=\"https:\/\/proxmoxer.github.io\/docs\/latest\/\">Proxmoxer<\/a>. You have the option to install it on the Ansible server or on the Proxmox VE hosts.<\/p>\n<p>Pay attention to the target server you specify in your Ansible playbooks. If you choose to install it on the Ansible server, you need to use <code>localhost<\/code> as the host in your playbook. We chose the latter option and installed it on the Proxmox VE hosts to keep our playbooks more consistent.<\/p>\n<p>When installing Proxmoxer, you need to decide on the version. The version that comes with Proxmox VE is likely too old to work with the most recent Ansible version. For this reason, we installed it using <a href=\"https:\/\/pip.pypa.io\/\">Python pip<\/a>. If you decide to use the official Debian package, just remove the comments (#) in the role file commands.<\/p>\n<pre><code class=\"language-yaml\">---\n# roles\/proxmox_prepare\/tasks\/main.yaml\n# Prepare the Proxmox hosts\n\n#- name: Ensure pip is installed\n#  ansible.builtin.apt:\n#    name: python3-proxmoxer\n#    state: present\n#  become: yes\n\n- name: Ensure python3-pip is installed\n  ansible.builtin.apt:\n    name: python3-pip\n    state: present\n  become: yes\n\n- name: Install Proxmoxer Python module\n  ansible.builtin.pip:\n    name: proxmoxer\n    state: present\n    executable: pip3\n  become: yes<\/code><\/pre>\n<p>Our playbook for this role is as follows:<\/p>\n<pre><code class=\"language-yaml\">---\n# Prepare Proxmox nodes\n- name: Prepare Proxmox nodes\n  hosts: compute_cluster\n  roles:\n    - role: proxmox_prepare<\/code><\/pre>\n<p>This can be applied by using the following command:<\/p>\n<pre><code class=\"language-bash\">\u279c ansible-playbook proxmox_prepare.yaml -i hosts.ini\n\nPLAY [Prepare Proxmox nodes] *********************************************************\n\nTASK [Gathering Facts] ***************************************************************\nok: [compute0]\nok: [compute2]\nok: [compute1]\n\nTASK [proxmox_prepare : Ensure python3-pip is installed] *****************************\nok: [compute1]\nok: [compute2]\nok: [compute0]\n\nTASK [proxmox_prepare : Install Proxmoxer Python module] *****************************\nchanged: [compute2]\nchanged: [compute1]\nchanged: [compute0]\n\nPLAY RECAP ***************************************************************************\ncompute0                   : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 \ncompute1                   : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 \ncompute2                   : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0\n<\/code><\/pre>\n<h2>API Tokens<\/h2>\n<p>Again multiple ways exist to access to Proxmox API. We decided to use API keys, because it is convienant. As we want it be able to access the full API give the token root access. If you want to can create a dedicated user for it.<\/p>\n<p>Go to <code>Datacenter &gt; Permissions &gt; Add<\/code>:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.codeschoepfer.de\/wp-content\/uploads\/2024\/07\/Screenshot_20240710_182807.png\" alt=\"Add Token\" \/><\/p>\n<p>Ensure to deactivate <em>Privilege Separation<\/em>, we need to give the API key full privileges of the associated user.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.codeschoepfer.de\/wp-content\/uploads\/2024\/07\/Screenshot_20240710_182920.png\" alt=\"Copy Token\" \/><\/p>\n<p>Copy the token, it will only be displayed once. And put it to <code>roles\/proxmox_create_demo_vm\/defaults\/main.yaml<\/code>. And yes you should work with a Ansible vault to be save. For the sake of simplicity, we have omitted it here.<\/p>\n<p>You can find more information of the Proxmox <a href=\"https:\/\/pve.proxmox.com\/wiki\/User_Management#pveum_tokens\">User Management<\/a> in the Proxmox Wiki.<\/p>\n<h2>Preparing the Snippet Storage<\/h2>\n<p>We need to prepare the Proxmox VE Snippet Storage to upload the cloud-init config. Many users utilize the <code>local<\/code> storage and activate the snippet property. The downside to this approach is that you have to copy the cloud-init file to each node. Our cluster uses <a href=\"https:\/\/ceph.io\/\">Ceph<\/a> for storage, and the <code>ISO<\/code> storage uses <strong>CephFS<\/strong>, making it available to each node. This means we only need to copy the file once.<\/p>\n<p>In the Proxmox GUI, navigate to <code>Datacenter &gt; Storage &gt; &lt;your storage&gt; &gt; Edit<\/code>.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.codeschoepfer.de\/wp-content\/uploads\/2024\/07\/Screenshot_20240712_093515.png\" alt=\"ISO Snippet Storage\" \/><\/p>\n<h2>Used Ansible Modules<\/h2>\n<p>First, we need to determine the proper Ansible modules to set up the VM. While there are many modules available, for this example, we only need the following two:<\/p>\n<ul>\n<li><code>community.general.proxmox_kvm<\/code><\/li>\n<li><code>community.general.proxmox_disk<\/code><\/li>\n<\/ul>\n<p>A common mistake is to use the module <code>community.general.proxmox<\/code>, which only controls LXC containers, not virtual machines. If you plan to use a real virtual machine, you must use the <code>community.general.proxmox_kvm<\/code> module. Additionally, we need the <code>community.general.proxmox_disk<\/code> module.<\/p>\n<h2>Preparing the Ansible Role<\/h2>\n<p>Our role is coded under <code>roles\/proxmox_create_demo_vm<\/code>.<\/p>\n<h3>defaults\/main.yaml<\/h3>\n<p>First, let&#8217;s look at the file <code>defaults\/main.yaml<\/code> where our variables are defined. This file is intended to be self-explanatory, and we believe our explanations throughout the file will help you understand it better.<\/p>\n<pre><code class=\"language-yaml\">---\n# defaults\/main.yaml\n# API\napi_host: \"compute0\"\napi_user: \"root@pam\"\napi_token_id: \"ansible\"\napi_token_secret: \"9628193b-900f-4bb6-ab70-321e37bfcb42\"\n\n# Node where the VM shall be started\nproxmox_node: \"compute0\"\n\n# Name of the Debian Clone Template\nclone_name: \"Debian12\"\n\n# For cloud-init\ndomain_name: codeschoepfer.de\ntimezone: \"Europe\/Berlin\"\nlocale: \"en_US.UTF-8\"\n\n# Snippet-Storage \nsnippets_path: \"\/mnt\/pve\/ISO\/snippets\/\"\nsnippets_storage: \"ISO\"\n\n# VM-Storage\nvm_storage: \"SSD-Pool\"\n\n# Vars for the VM itself DemoVM\nvm_name: \"demoVM\"\nvm_memory: 2048\nvm_cores: 2\nvm_disk_size: \"32G\"\nvm_disk_type: \"scsi0\"\ncloudinit_user: \"demo\"\nvm_bridge: \"vmbr0\"\nvlan_id: 77\nfw_enabled: 0<\/code><\/pre>\n<h3>templates\/user-data.yml.j2<\/h3>\n<p>We created an Ansible template <code>templates\/user-data.yml.j2<\/code> that references the variables in <code>defaults\/main.yaml<\/code>.<\/p>\n<blockquote><p>\nPlease note: The first line must be <code>#cloud-config<\/code>.\n<\/p><\/blockquote>\n<p>This file is intended to be self-explanatory. If you need more information about the cloud-init syntax, please refer to the <a href=\"https:\/\/cloudinit.readthedocs.io\/en\/latest\/reference\/\">cloud-init documentation on readthedocs.io<\/a>.<\/p>\n<blockquote><p>\nIt is important to know the this user-data replaces the config setup in the Proxmox VE GUI.\n<\/p><\/blockquote>\n<pre><code class=\"language-yaml\">#cloud-config\n\nhostname: {{ vm_name }}\ntimezone: {{ timezone }}\n\nuser: {{ cloudinit_user }}\n\nmanage_etc_hosts: localhost\nfqdn: {{ vm_name }}.{{ domain_name }}\n\nssh_authorized_keys:\n  - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKwljN8BQnU3PAp4RGij\/QPPihXqZNXGv7NlLCJxVB4U demokey@codeschoepfer.de\n\nchpasswd:\n  expire: false\nusers:\n  - default\n\npackage_update: true\npackage_upgrade: true\n\npackages:\n  - needrestart\n  - qemu-guest-agent\n\nruncmd:\n  - timedatectl set-ntp true\n  - locale-gen {{ locale }}\n  - localectl set-locale LANG={{ locale }}\n  - systemctl enable qemu-guest-agent\n  - systemctl start qemu-guest-agent\n\npower_state:\n  mode: reboot<\/code><\/pre>\n<h3>tasks\/main.yaml<\/h3>\n<p>Our main tasks file for deploying a single VM is structured as follows. We will explain the different sections below. <\/p>\n<pre><code class=\"language-yaml\">---\n- name: Clone Debian template\n  community.general.proxmox_kvm:\n    api_host: \"{{ api_host }}\"\n    api_user: \"{{ api_user }}\"\n    api_token_id: \"{{ api_token_id }}\"\n    api_token_secret: \"{{ api_token_secret }}\"\n    node: \"{{ proxmox_node }}\"\n    clone: \"{{ clone_name }}\"\n    # newid: \"{{ vm_id }}\"  # Control to the given ID\n    name: \"{{ vm_name }}\"\n    full: true\n    storage: \"{{ vm_storage }}\"\n  register: state\n\n- name: Resize disk, if needed\n  community.general.proxmox_disk:\n    api_host: \"{{ api_host }}\"\n    api_user: \"{{ api_user }}\"\n    api_token_id: \"{{ api_token_id }}\"\n    api_token_secret: \"{{ api_token_secret }}\"\n    vmid: \"{{ state.vmid }}\"\n    disk: \"{{ vm_disk_type }}\"\n    size: \"{{ vm_disk_size }}\"\n    state: \"resized\"\n  when: state.changed\n\n- name: Upload Cloudinit user-data file\n  ansible.builtin.template:\n    src: user-data.yml.j2\n    dest: \"{{ snippets_path }}\/{{ state.vmid }}-user-data.yml\"\n    mode: \"0644\"\n  when: state.changed\n\n- name: Modify the Cloned VM, adapt a few parameters, attach cloudinit template\n  community.general.proxmox_kvm:\n    api_host: \"{{ api_host }}\"\n    api_user: \"{{ api_user }}\"\n    api_token_id: \"{{ api_token_id }}\"\n    api_token_secret: \"{{ api_token_secret }}\"\n    node: \"{{ proxmox_node }}\"\n    vmid: \"{{ state.vmid }}\"\n    name: \"{{ vm_name }}\"\n    cores: \"{{ vm_cores }}\"\n    memory: \"{{ vm_memory }}\"\n    net:\n      net0: \"virtio,bridge={{ vm_bridge }},tag={{ vlan_id }},firewall={{ fw_enabled }}\"\n    ide:\n      ide2: \"{{ vm_storage }}:cloudinit\"\n    serial:\n      serial0: \"socket\"\n    vga: serial0\n    citype: nocloud\n    cicustom: \"user={{snippets_storage}}:snippets\/{{ state.vmid }}-user-data.yml\"\n    agent: \"enabled=1\"\n    update: yes\n    update_unsafe: yes\n  when: state.changed\n\n- name: Start the VM\n  community.general.proxmox_kvm:\n    api_host: \"{{ api_host }}\"\n    api_user: \"{{ api_user }}\"\n    api_token_id: \"{{ api_token_id }}\"\n    api_token_secret: \"{{ api_token_secret }}\"\n    node: \"{{ proxmox_node }}\"\n    vmid: \"{{ state.vmid }}\"\n    name: \"{{ vm_name }}\"\n    state: started\n  when: state.changed<\/code><\/pre>\n<h4>Authentification<\/h4>\n<p>Almost every task in here contains those lines to connect to Proxmox API:<\/p>\n<pre><code class=\"language-yaml\">    api_host: \"{{ api_host }}\"\n    api_user: \"{{ api_user }}\"\n    api_token_id: \"{{ api_token_id }}\"\n    api_token_secret: \"{{ api_token_secret }}\"<\/code><\/pre>\n<p>These lines are for authentification, referring to variables defined in <code>defaults\/main.yaml<\/code>.<\/p>\n<h4>Create VM out of the Proxmox Template<\/h4>\n<p>This will create a <code>full<\/code> clone on the storage <code>{{ vm_storage }}<\/code> from the template <code>{{ clone_name }}<\/code> with the name <code>{{ vm_name }}<\/code>. The VM ID is chosen by Proxmox VE itself, but you can specify a VM ID using the <code>newid<\/code> field if you prefer.<\/p>\n<pre><code class=\"language-yaml\">- name: Clone Debian template\n  community.general.proxmox_kvm:\n    node: \"{{ proxmox_node }}\"\n    clone: \"{{ clone_name }}\"\n    # newid: \"{{ vm_id }}\"  # Control to the given ID\n    name: \"{{ vm_name }}\"\n    full: true\n    storage: \"{{ vm_storage }}\"\n  register: state<\/code><\/pre>\n<h4>Resize Disk<\/h4>\n<p>The VM template contains only a small disk, so we will likely want to resize the disk to <code>{{ vm_disk_size }}<\/code>. Note that the module <code>community.general.proxmox_disk<\/code> needs to know the VM ID <code>state.vmid<\/code>, which is already registered in the dictionary <code>state<\/code> by the previous section.<\/p>\n<pre><code class=\"language-yaml\">- name: Resize disk, if needed\n  community.general.proxmox_disk:\n    vmid: \"{{ state.vmid }}\"\n    disk: \"{{ vm_disk_type }}\"\n    size: \"{{ vm_disk_size }}\"\n    state: \"resized\"\n  when: state.changed<\/code><\/pre>\n<h4>Copying the Cloud-init User-data<\/h4>\n<p>We will send the prepared cloud-init user-data to the snippet storage we configured earlier.<\/p>\n<pre><code class=\"language-yaml\">- name: Upload Cloudinit user-data file\n  ansible.builtin.template:\n    src: user-data.yml.j2\n    dest: \"{{ snippets_path }}\/{{ state.vmid }}-user-data.yml\"\n    mode: \"0644\"\n  when: state.changed<\/code><\/pre>\n<h4>Copying the Cloud-init User-data<\/h4>\n<p>Then we adopt the VM hardware config. To give it the desired number of CPU cores, memory, network. To activate the VM agent.<\/p>\n<pre><code class=\"language-yaml\">- name: Modify the Cloned VM, adapt a few parameters, attach cloudinit template\n  community.general.proxmox_kvm:\n    node: \"{{ proxmox_node }}\"\n    vmid: \"{{ state.vmid }}\"\n    name: \"{{ vm_name }}\"\n    cores: \"{{ vm_cores }}\"\n    memory: \"{{ vm_memory }}\"\n    net:\n      net0: \"virtio,bridge={{ vm_bridge }},tag={{ vlan_id }},firewall={{ fw_enabled }}\"\n    agent: \"enabled=1\"<\/code><\/pre>\n<p>The essential part for cloud-init follows. Please note, if your template already has a cloud-init storage, you can omit the <code>ide<\/code> part. The <code>citype<\/code> value is the default for GNU\/Linux machines. The <code>cicustom<\/code> parameter is a pointer to the user-data. As mentioned, it will overwrite any cloud-init configuration specified by the Proxmox VE GUI.<\/p>\n<pre><code class=\"language-yaml\">    ide:\n      ide2: \"{{ vm_storage }}:cloudinit\"\n    citype: nocloud\n    cicustom: \"user={{snippets_storage}}:snippets\/{{ state.vmid }}-user-data.yml\"<\/code><\/pre>\n<p>Most cloud images come only with a serial console enabled. If you have such an image, you need the following lines, otherwise, you can omit them.<\/p>\n<pre><code class=\"language-yaml\">    serial:\n      serial0: \"socket\"\n    vga: serial0<\/code><\/pre>\n<p>We need to use the <code>update<\/code> parameter because of the changed hardware configuration. The <code>update_unsafe<\/code> parameter is required because we modified the <code>net<\/code> parameter and created a new storage for cloud-init. For more information, refer to the <a href=\"https:\/\/docs.ansible.com\/ansible\/latest\/collections\/community\/general\/proxmox_kvm_module.html#parameter-update\">Ansible Documentation<\/a>.<\/p>\n<pre><code class=\"language-yaml\">    update: yes\n    update_unsafe: yes<\/code><\/pre>\n<h4>Start of the VM<\/h4>\n<p>Finally, we start the VM with the following code block:<\/p>\n<pre><code class=\"language-yaml\">- name: Start the VM\n  community.general.proxmox_kvm:\n    node: \"{{ proxmox_node }}\"\n    vmid: \"{{ state.vmid }}\"\n    name: \"{{ vm_name }}\"\n    state: started\n  when: state.changed<\/code><\/pre>\n<h2>Executing the Ansible Role<\/h2>\n<p>After submitting the following playbook, which refers to the role <code>proxmox_create_demo_vm<\/code>:<\/p>\n<pre><code class=\"language-yaml\">---\n# Create Demo VM\n- name: Create Demo VM\n  hosts: pve_compute0\n  roles:\n    - role: proxmox_create_demo_vm<\/code><\/pre>\n<pre><code class=\"language-bash\">\u279c ansible-playbook proxmox_create_demo_vm.yaml -i hosts.ini \n\nPLAY [Create Demo VM] *********************************************************************\n\nTASK [Gathering Facts] ********************************************************************\nok: [compute0]\n\nTASK [proxmox_create_demo_vm : Clone Debian template] *************************************\nchanged: [compute0]\n\nTASK [proxmox_create_demo_vm : Resize disk, if needed] ************************************\nchanged: [compute0]\n\nTASK [proxmox_create_demo_vm : Upload Cloudinit user-data file] ***************************\nok: [compute0]\n\nTASK [proxmox_create_demo_vm : Modify the Cloned VM, adapt a few parameters, attach cloudinit template] ***\nchanged: [compute0]\n\nTASK [proxmox_create_demo_vm : Start the VM] **********************************************\nchanged: [compute0]\n\nPLAY RECAP ********************************************************************************\ncompute0                   : ok=7    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   <\/code><\/pre>\n<p>The new VM is now configured and starting in the Proxmox VE GUI, and cloud-init begins its work.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.codeschoepfer.de\/wp-content\/uploads\/2024\/07\/Screenshot_20240713_151105-1.png\" alt=\"Starting VM\" \/><\/p>\n<h2>Final Thoughts<\/h2>\n<p>Deploying a VM on Proxmox VE using Ansible simplifies the process and enhances efficiency. By leveraging the Proxmox API for VM integration and cloud-init for VM configuration, you can achieve a streamlined and automated deployment workflow. We used a simple Debian GNU\/Linux VM for demonstration, but this method works with any operating system supported by Proxmox.<\/p>\n<p>With the steps outlined, you can easily adapt and expand the process to suit your specific needs, allowing you to roll out multiple virtual machines within minutes. Automation tools like Ansible not only save time but also ensure consistency across your deployments, making them invaluable for managing virtualized environments.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This article shows how to deploy a Debian VM on Proxmox PVE using Ansible, leveraging the Proxmox API and cloud-init for automated deployment. This process serves as a building block to enhance your automation workflow.<\/p>\n","protected":false},"author":3,"featured_media":562,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[19,21],"tags":[],"class_list":["post-715","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-install-en","category-linux-en"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Automate Your Proxmox VM Deployment with Ansible - Codesch\u00f6pfer GmbH<\/title>\n<meta name=\"description\" content=\"This guide shows how to deploy a Debian VM on Proxmox PVE using Ansible, leveraging the Proxmox API and cloud-init for automated deployment. This process serves as a building block to enhance your automation workflow.\" \/>\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.codeschoepfer.de\/en\/automate-your-proxmox-vms-with-ansible\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Automate Your Proxmox VM Deployment with Ansible - Codesch\u00f6pfer GmbH\" \/>\n<meta property=\"og:description\" content=\"This guide shows how to deploy a Debian VM on Proxmox PVE using Ansible, leveraging the Proxmox API and cloud-init for automated deployment. This process serves as a building block to enhance your automation workflow.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.codeschoepfer.de\/en\/automate-your-proxmox-vms-with-ansible\/\" \/>\n<meta property=\"og:site_name\" content=\"Codesch\u00f6pfer GmbH\" \/>\n<meta property=\"article:published_time\" content=\"2024-07-13T15:11:29+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-07-15T17:45:20+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.codeschoepfer.de\/wp-content\/uploads\/2024\/05\/proxmox-blog-960_480.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"960\" \/>\n\t<meta property=\"og:image:height\" content=\"480\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Volker Dormeyer\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@codeschoepfer\" \/>\n<meta name=\"twitter:site\" content=\"@codeschoepfer\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Volker Dormeyer\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.codeschoepfer.de\\\/en\\\/automate-your-proxmox-vms-with-ansible\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.codeschoepfer.de\\\/en\\\/automate-your-proxmox-vms-with-ansible\\\/\"},\"author\":{\"name\":\"Volker Dormeyer\",\"@id\":\"https:\\\/\\\/www.codeschoepfer.de\\\/en\\\/#\\\/schema\\\/person\\\/5df1f228a7dccfed918d6d38c90e40c6\"},\"headline\":\"Automate Your Proxmox VM Deployment with Ansible\",\"datePublished\":\"2024-07-13T15:11:29+00:00\",\"dateModified\":\"2024-07-15T17:45:20+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.codeschoepfer.de\\\/en\\\/automate-your-proxmox-vms-with-ansible\\\/\"},\"wordCount\":1206,\"publisher\":{\"@id\":\"https:\\\/\\\/www.codeschoepfer.de\\\/en\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.codeschoepfer.de\\\/en\\\/automate-your-proxmox-vms-with-ansible\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.codeschoepfer.de\\\/wp-content\\\/uploads\\\/2024\\\/05\\\/proxmox-blog-960_480.jpg\",\"articleSection\":[\"Install\",\"Linux\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.codeschoepfer.de\\\/en\\\/automate-your-proxmox-vms-with-ansible\\\/\",\"url\":\"https:\\\/\\\/www.codeschoepfer.de\\\/en\\\/automate-your-proxmox-vms-with-ansible\\\/\",\"name\":\"Automate Your Proxmox VM Deployment with Ansible - Codesch\u00f6pfer GmbH\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.codeschoepfer.de\\\/en\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.codeschoepfer.de\\\/en\\\/automate-your-proxmox-vms-with-ansible\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.codeschoepfer.de\\\/en\\\/automate-your-proxmox-vms-with-ansible\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.codeschoepfer.de\\\/wp-content\\\/uploads\\\/2024\\\/05\\\/proxmox-blog-960_480.jpg\",\"datePublished\":\"2024-07-13T15:11:29+00:00\",\"dateModified\":\"2024-07-15T17:45:20+00:00\",\"description\":\"This guide shows how to deploy a Debian VM on Proxmox PVE using Ansible, leveraging the Proxmox API and cloud-init for automated deployment. This process serves as a building block to enhance your automation workflow.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.codeschoepfer.de\\\/en\\\/automate-your-proxmox-vms-with-ansible\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.codeschoepfer.de\\\/en\\\/automate-your-proxmox-vms-with-ansible\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.codeschoepfer.de\\\/en\\\/automate-your-proxmox-vms-with-ansible\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.codeschoepfer.de\\\/wp-content\\\/uploads\\\/2024\\\/05\\\/proxmox-blog-960_480.jpg\",\"contentUrl\":\"https:\\\/\\\/www.codeschoepfer.de\\\/wp-content\\\/uploads\\\/2024\\\/05\\\/proxmox-blog-960_480.jpg\",\"width\":960,\"height\":480,\"caption\":\"Proxmox\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.codeschoepfer.de\\\/en\\\/automate-your-proxmox-vms-with-ansible\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Startseite\",\"item\":\"https:\\\/\\\/www.codeschoepfer.de\\\/en\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Automate Your Proxmox VM Deployment with Ansible\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.codeschoepfer.de\\\/en\\\/#website\",\"url\":\"https:\\\/\\\/www.codeschoepfer.de\\\/en\\\/\",\"name\":\"Codesch\u00f6pfer GmbH\",\"description\":\"Codesch\u00f6pfer GmbH\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.codeschoepfer.de\\\/en\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.codeschoepfer.de\\\/en\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.codeschoepfer.de\\\/en\\\/#organization\",\"name\":\"Codesch\u00f6pfer GmbH\",\"url\":\"https:\\\/\\\/www.codeschoepfer.de\\\/en\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.codeschoepfer.de\\\/en\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.codeschoepfer.de\\\/wp-content\\\/uploads\\\/2024\\\/04\\\/logo_cs_vlinks_rgb.png\",\"contentUrl\":\"https:\\\/\\\/www.codeschoepfer.de\\\/wp-content\\\/uploads\\\/2024\\\/04\\\/logo_cs_vlinks_rgb.png\",\"width\":723,\"height\":202,\"caption\":\"Codesch\u00f6pfer GmbH\"},\"image\":{\"@id\":\"https:\\\/\\\/www.codeschoepfer.de\\\/en\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/x.com\\\/codeschoepfer\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/codeschoepfer\\\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.codeschoepfer.de\\\/en\\\/#\\\/schema\\\/person\\\/5df1f228a7dccfed918d6d38c90e40c6\",\"name\":\"Volker Dormeyer\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/2398e76b7a7613d977afcc28ec5267b5815134f989dca7e750e64d31ff46634b?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/2398e76b7a7613d977afcc28ec5267b5815134f989dca7e750e64d31ff46634b?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/2398e76b7a7613d977afcc28ec5267b5815134f989dca7e750e64d31ff46634b?s=96&d=mm&r=g\",\"caption\":\"Volker Dormeyer\"},\"url\":\"https:\\\/\\\/www.codeschoepfer.de\\\/en\\\/author\\\/vdormeyer\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Automate Your Proxmox VM Deployment with Ansible - Codesch\u00f6pfer GmbH","description":"This guide shows how to deploy a Debian VM on Proxmox PVE using Ansible, leveraging the Proxmox API and cloud-init for automated deployment. This process serves as a building block to enhance your automation workflow.","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.codeschoepfer.de\/en\/automate-your-proxmox-vms-with-ansible\/","og_locale":"en_US","og_type":"article","og_title":"Automate Your Proxmox VM Deployment with Ansible - Codesch\u00f6pfer GmbH","og_description":"This guide shows how to deploy a Debian VM on Proxmox PVE using Ansible, leveraging the Proxmox API and cloud-init for automated deployment. This process serves as a building block to enhance your automation workflow.","og_url":"https:\/\/www.codeschoepfer.de\/en\/automate-your-proxmox-vms-with-ansible\/","og_site_name":"Codesch\u00f6pfer GmbH","article_published_time":"2024-07-13T15:11:29+00:00","article_modified_time":"2024-07-15T17:45:20+00:00","og_image":[{"width":960,"height":480,"url":"https:\/\/www.codeschoepfer.de\/wp-content\/uploads\/2024\/05\/proxmox-blog-960_480.jpg","type":"image\/jpeg"}],"author":"Volker Dormeyer","twitter_card":"summary_large_image","twitter_creator":"@codeschoepfer","twitter_site":"@codeschoepfer","twitter_misc":{"Written by":"Volker Dormeyer","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.codeschoepfer.de\/en\/automate-your-proxmox-vms-with-ansible\/#article","isPartOf":{"@id":"https:\/\/www.codeschoepfer.de\/en\/automate-your-proxmox-vms-with-ansible\/"},"author":{"name":"Volker Dormeyer","@id":"https:\/\/www.codeschoepfer.de\/en\/#\/schema\/person\/5df1f228a7dccfed918d6d38c90e40c6"},"headline":"Automate Your Proxmox VM Deployment with Ansible","datePublished":"2024-07-13T15:11:29+00:00","dateModified":"2024-07-15T17:45:20+00:00","mainEntityOfPage":{"@id":"https:\/\/www.codeschoepfer.de\/en\/automate-your-proxmox-vms-with-ansible\/"},"wordCount":1206,"publisher":{"@id":"https:\/\/www.codeschoepfer.de\/en\/#organization"},"image":{"@id":"https:\/\/www.codeschoepfer.de\/en\/automate-your-proxmox-vms-with-ansible\/#primaryimage"},"thumbnailUrl":"https:\/\/www.codeschoepfer.de\/wp-content\/uploads\/2024\/05\/proxmox-blog-960_480.jpg","articleSection":["Install","Linux"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.codeschoepfer.de\/en\/automate-your-proxmox-vms-with-ansible\/","url":"https:\/\/www.codeschoepfer.de\/en\/automate-your-proxmox-vms-with-ansible\/","name":"Automate Your Proxmox VM Deployment with Ansible - Codesch\u00f6pfer GmbH","isPartOf":{"@id":"https:\/\/www.codeschoepfer.de\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.codeschoepfer.de\/en\/automate-your-proxmox-vms-with-ansible\/#primaryimage"},"image":{"@id":"https:\/\/www.codeschoepfer.de\/en\/automate-your-proxmox-vms-with-ansible\/#primaryimage"},"thumbnailUrl":"https:\/\/www.codeschoepfer.de\/wp-content\/uploads\/2024\/05\/proxmox-blog-960_480.jpg","datePublished":"2024-07-13T15:11:29+00:00","dateModified":"2024-07-15T17:45:20+00:00","description":"This guide shows how to deploy a Debian VM on Proxmox PVE using Ansible, leveraging the Proxmox API and cloud-init for automated deployment. This process serves as a building block to enhance your automation workflow.","breadcrumb":{"@id":"https:\/\/www.codeschoepfer.de\/en\/automate-your-proxmox-vms-with-ansible\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.codeschoepfer.de\/en\/automate-your-proxmox-vms-with-ansible\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.codeschoepfer.de\/en\/automate-your-proxmox-vms-with-ansible\/#primaryimage","url":"https:\/\/www.codeschoepfer.de\/wp-content\/uploads\/2024\/05\/proxmox-blog-960_480.jpg","contentUrl":"https:\/\/www.codeschoepfer.de\/wp-content\/uploads\/2024\/05\/proxmox-blog-960_480.jpg","width":960,"height":480,"caption":"Proxmox"},{"@type":"BreadcrumbList","@id":"https:\/\/www.codeschoepfer.de\/en\/automate-your-proxmox-vms-with-ansible\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Startseite","item":"https:\/\/www.codeschoepfer.de\/en\/"},{"@type":"ListItem","position":2,"name":"Automate Your Proxmox VM Deployment with Ansible"}]},{"@type":"WebSite","@id":"https:\/\/www.codeschoepfer.de\/en\/#website","url":"https:\/\/www.codeschoepfer.de\/en\/","name":"Codesch\u00f6pfer GmbH","description":"Codesch\u00f6pfer GmbH","publisher":{"@id":"https:\/\/www.codeschoepfer.de\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.codeschoepfer.de\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.codeschoepfer.de\/en\/#organization","name":"Codesch\u00f6pfer GmbH","url":"https:\/\/www.codeschoepfer.de\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.codeschoepfer.de\/en\/#\/schema\/logo\/image\/","url":"https:\/\/www.codeschoepfer.de\/wp-content\/uploads\/2024\/04\/logo_cs_vlinks_rgb.png","contentUrl":"https:\/\/www.codeschoepfer.de\/wp-content\/uploads\/2024\/04\/logo_cs_vlinks_rgb.png","width":723,"height":202,"caption":"Codesch\u00f6pfer GmbH"},"image":{"@id":"https:\/\/www.codeschoepfer.de\/en\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/codeschoepfer","https:\/\/www.linkedin.com\/company\/codeschoepfer\/"]},{"@type":"Person","@id":"https:\/\/www.codeschoepfer.de\/en\/#\/schema\/person\/5df1f228a7dccfed918d6d38c90e40c6","name":"Volker Dormeyer","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/2398e76b7a7613d977afcc28ec5267b5815134f989dca7e750e64d31ff46634b?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/2398e76b7a7613d977afcc28ec5267b5815134f989dca7e750e64d31ff46634b?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/2398e76b7a7613d977afcc28ec5267b5815134f989dca7e750e64d31ff46634b?s=96&d=mm&r=g","caption":"Volker Dormeyer"},"url":"https:\/\/www.codeschoepfer.de\/en\/author\/vdormeyer\/"}]}},"_links":{"self":[{"href":"https:\/\/www.codeschoepfer.de\/en\/wp-json\/wp\/v2\/posts\/715","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.codeschoepfer.de\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.codeschoepfer.de\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.codeschoepfer.de\/en\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/www.codeschoepfer.de\/en\/wp-json\/wp\/v2\/comments?post=715"}],"version-history":[{"count":17,"href":"https:\/\/www.codeschoepfer.de\/en\/wp-json\/wp\/v2\/posts\/715\/revisions"}],"predecessor-version":[{"id":758,"href":"https:\/\/www.codeschoepfer.de\/en\/wp-json\/wp\/v2\/posts\/715\/revisions\/758"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.codeschoepfer.de\/en\/wp-json\/wp\/v2\/media\/562"}],"wp:attachment":[{"href":"https:\/\/www.codeschoepfer.de\/en\/wp-json\/wp\/v2\/media?parent=715"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.codeschoepfer.de\/en\/wp-json\/wp\/v2\/categories?post=715"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.codeschoepfer.de\/en\/wp-json\/wp\/v2\/tags?post=715"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}