diff --git a/app/network/forms.py b/app/network/forms.py
index cd89d472358acfe2a79be8066a611f3aba646a5d..ab58a88308a8142737f730fb8f9b162b326430cb 100644
--- a/app/network/forms.py
+++ b/app/network/forms.py
@@ -231,6 +231,7 @@ class CreateVMForm(CSEntryForm):
     cores = SelectField("Cores", default=2, coerce=int)
     memory = SelectField("Memory (GB)", default=2, coerce=int)
     disk = SelectField("Disk (GB)", default=15, coerce=int)
+    skip_post_install_job = BooleanField("Skip post install job", default=False)
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
diff --git a/app/network/views.py b/app/network/views.py
index 2a539d86557fb193e06b221813175faf7b4286fa..756d35ccbbf3ee03d00681efdfbe76bd975687a2 100644
--- a/app/network/views.py
+++ b/app/network/views.py
@@ -192,7 +192,7 @@ def view_host(name):
                 try:
                     host.ansible_vars.update(csentry_vars)
                     # If we don't flag the field as modified, it's not saved to the database
-                    # Might be because we update an existing directory
+                    # Might be because we update an existing dict
                     sa.orm.attributes.flag_modified(host, "ansible_vars")
                 except AttributeError:
                     host.ansible_vars = csentry_vars
@@ -202,6 +202,7 @@ def view_host(name):
                     interface,
                     csentry_vars["csentry_vm_memory"],
                     csentry_vars["csentry_vm_cores"],
+                    skip_post_install_job=form.skip_post_install_job.data,
                 )
                 db.session.commit()
                 current_app.logger.info(f"Creation of {name} requested: task {task.id}")
diff --git a/app/settings.py b/app/settings.py
index f7fd21102a06988fcf5bee46ca8e84391493a6a6..47043995bb85eae0f6928c0000ff02b1679ef37d 100644
--- a/app/settings.py
+++ b/app/settings.py
@@ -94,6 +94,14 @@ AWX_CORE_SERVICES_UPDATE = "ics-ans-core @ DHCP test"
 AWX_CREATE_VM = "deploy-vm-in-proxmox"
 AWX_CREATE_VIOC = "ics-ans-deploy-vioc"
 AWX_ZTP_CONFIGURATION = "ics-ans-ztp"
+AWX_POST_INSTALL = {
+    "VIOC": {"esss.lu.se": "", "tn.esss.lu.se": "", "cslab.esss.lu.se": ""},
+    "VM": {
+        "esss.lu.se": "",
+        "tn.esss.lu.se": "",
+        "cslab.esss.lu.se": "customize-LabVM",
+    },
+}
 
 AWX_JOB_ENABLED = False
 AWX_VM_CREATION_ENABLED = False
diff --git a/app/tasks.py b/app/tasks.py
index 3ba23b15136c505c92da0c5dd2d7e0c5a5d9a4aa..d260ac3152768e442d8f4662f8f9bcbc2c7dbebf 100644
--- a/app/tasks.py
+++ b/app/tasks.py
@@ -81,8 +81,9 @@ class TaskWorker(Worker):
         super().prepare_job_execution(job)
 
 
-def trigger_vm_creation(name, interface, memory, cores):
+def trigger_vm_creation(name, interface, memory, cores, skip_post_install_job):
     """Trigger a job to create a virtual machine or virtual IOC"""
+    domain = interface.network.domain.name
     extra_vars = [
         f"vmname={name}",
         f"memory={memory}",
@@ -95,13 +96,15 @@ def trigger_vm_creation(name, interface, memory, cores):
     if interface.is_ioc:
         task_name = "trigger_vioc_creation"
         job_template = current_app.config["AWX_CREATE_VIOC"]
+        post_job_template = current_app.config["AWX_POST_INSTALL"]["VIOC"].get(domain)
     else:
         task_name = "trigger_vm_creation"
         job_template = current_app.config["AWX_CREATE_VM"]
+        post_job_template = current_app.config["AWX_POST_INSTALL"]["VM"].get(domain)
         extra_vars.extend(
             [
                 f"ip_address={interface.ip}",
-                f"domain={interface.network.domain.name}",
+                f"domain={domain}",
                 f"netmask={interface.network.netmask}",
                 f"gateway={interface.network.gateway}",
             ]
@@ -116,6 +119,19 @@ def trigger_vm_creation(name, interface, memory, cores):
         extra_vars=extra_vars,
         timeout=500,
     )
+
+    if post_job_template and not skip_post_install_job:
+        current_user.launch_task(
+            "trigger_post_install_job",
+            func="launch_job_template",
+            job_template=post_job_template,
+            limit=f"{name}.{domain}",
+            depends_on=task.id,
+            timeout=500,
+        )
+        current_app.logger.info(
+            f"Trigger post install job: run {post_job_template} on {name}.{domain}"
+        )
     return task
 
 
diff --git a/app/templates/_helpers.html b/app/templates/_helpers.html
index 4c1f01af4ec88e31269682a56121bb5b7a4f9a1d..29c208444355d2644b858c8a8fc551640896d619 100644
--- a/app/templates/_helpers.html
+++ b/app/templates/_helpers.html
@@ -100,7 +100,7 @@
     {% if field.type == 'BooleanField' %}
       <div class="col-sm-{{ input_size }} offset-sm-{{ label_size }}">
         <div class="form-check">
-          {{ field(class_="form-check-input") }}
+          {{ field(class_="form-check-input", **kwargs) }}
           {{ field.label(class_="form-check-label") }}
         </div>
       </div>
diff --git a/app/templates/network/view_host.html b/app/templates/network/view_host.html
index 544ab6e9c9f9a5c0cac6cfadc561713f475d1711..38c9b450f7149cae3ba11f4e30b2c10992769f31 100644
--- a/app/templates/network/view_host.html
+++ b/app/templates/network/view_host.html
@@ -19,7 +19,7 @@
 
 {% block hosts_main %}
   <div class="row">
-    <div class="col-sm-9">
+    <div class="col-sm-8">
       <dl class="row">
         <dt class="col-sm-3">Hostname</dt>
         <dd class="col-sm-9">
@@ -70,17 +70,20 @@
       {% else %}
         {% set vm_type = 'VM' %}
       {% endif %}
-      <div class="col-sm-3">
+      <div class="col-sm-4">
         <form id="createVMForm" method="POST">
           {{ form.hidden_tag() }}
-          {{ render_field(form.cores, label_size='6', input_size='6') }}
-          {{ render_field(form.memory, label_size='6', input_size='6') }}
-          {{ render_field(form.disk, label_size='6', input_size='6') }}
+          {{ render_field(form.cores, label_size='5', input_size='7') }}
+          {{ render_field(form.memory, label_size='5', input_size='7') }}
+          {{ render_field(form.disk, label_size='5', input_size='7') }}
+          {% if current_user.is_admin %}
+          {{ render_field(form.skip_post_install_job, label_size='5', input_size='7') }}
+          {% endif %}
           {{ submit_button_with_confirmation('Create ' + vm_type, 'Do you really want to create the ' + vm_type + ' ' + host.name + '?') }}
         </form>
       </div>
     {% elif host.device_type.name == 'Network' and host.model and current_user.is_admin %}
-      <div class="col-sm-3">
+      <div class="col-sm-4">
         <form id="generateZTPForm" method="POST">
           {{ form.hidden_tag() }}
           {{ submit_button_with_confirmation('Generate ZTP configuration', 'Do you really want to generate the ZTP configuration for ' + host.name + '?') }}
diff --git a/docs/_static/create_vioc.png b/docs/_static/create_vioc.png
index 8febd8a537f74bb0d371a39c07a9c42c604231cc..c7878ba683e67765734f2ff4fa6e9de6c2891631 100644
Binary files a/docs/_static/create_vioc.png and b/docs/_static/create_vioc.png differ
diff --git a/docs/_static/create_vm.png b/docs/_static/create_vm.png
index df0b4f85b6df2fc8a4bc1d7abb0567a17124eb0f..16033163b3bcb4054e3327e1cda5a1a78cb2e8e4 100644
Binary files a/docs/_static/create_vm.png and b/docs/_static/create_vm.png differ
diff --git a/docs/_static/create_vm_confirmation.png b/docs/_static/create_vm_confirmation.png
index 1ec33d60b6b5bd333b04b24560d703b6fb645607..49482bfc7ffb3cdf1c8c5518af2e075039403de5 100644
Binary files a/docs/_static/create_vm_confirmation.png and b/docs/_static/create_vm_confirmation.png differ
diff --git a/docs/network.rst b/docs/network.rst
index 050d6bb54d9c102d1a6308af3df1bf415e72d54c..78cbb2c7b5cb7049abd92c6f76892114d631d082 100644
--- a/docs/network.rst
+++ b/docs/network.rst
@@ -137,6 +137,13 @@ In both case, a confirmation dialog will be displayed when you submit the form.
 
 .. image:: _static/create_vm_confirmation.png
 
+To create a VM or VIOC, a job template is triggered on AWX (**AWX_CREATE_VM** or **AWX_CREATE_VIOC**).
+If a post install job template is defined, a task is enqueued to run after the successful completion of the first one.
+The post install job name can be defined per domain in the **AWX_POST_INSTALL** dictionary.
+
+Admin users can disable the post install job run by selecting the *Skip post install job* checkbox.
+This checkbox is only visible to admin users.
+
 Ansible inventory
 -----------------