Ansible Automation Portal VM Appliance: Deploy on RHEL, KVM, OpenShift Virtualization, and VMware in AAP 2.7
By Luca Berton · Published 2026-06-30 · Category: installation
Deploy the Ansible Automation Portal as a pre-built VM appliance on KVM, OpenShift Virtualization, or VMware vSphere using QCOW2 or VMDK images in AAP 2.7.
Ansible Automation Platform 2.7 ships the Ansible automation portal as a pre-built virtual machine appliance — a QCOW2 or VMDK disk image you deploy on your existing virtualization infrastructure without running the AAP containerized or RPM installer. Built on RHEL 9 image mode (bootc), it supports atomic upgrades and rollback, cloud-init first-boot configuration, and deployment on KVM, Red Hat OpenShift Virtualization, and VMware vSphere.
What Is the Portal Appliance?
The Ansible automation portal provides self-service access to Ansible job templates for users who don't need (or shouldn't have) full AAP UI access. Teams use it to expose approved automation as a simple catalog: users pick a template, fill in parameters, and launch — without knowing anything about Ansible.
The appliance packaging means you no longer need to deploy the full containerized AAP stack just to run the portal. The appliance connects to an existing AAP instance over HTTPS using an OAuth credential you supply at first boot.
Deployment Options
| Platform | Image Format | Notes |
|---|---|---|
| RHEL with KVM / libvirt | QCOW2 | Standard virt-install or Cockpit VM manager |
| Red Hat OpenShift Virtualization | QCOW2 | Import via DataVolume or VirtualMachine CRD |
| VMware vSphere | VMDK | Deploy with vSphere client or govc |
Cloud-Init First-Boot Configuration
The appliance configures itself entirely from a cloud-init user-data file supplied at deployment time — no interactive setup required. A minimal user-data for KVM:
#cloud-config
# Ansible Automation Portal appliance — first-boot configuration
hostname: ansible-portal
fqdn: portal.corp.example.com
users:
- name: ansible-admin
groups: wheel
sudo: ALL=(ALL) NOPASSWD:ALL
ssh_authorized_keys:
- ssh-ed25519 AAAAC3Nza... your-public-key
write_files:
- path: /etc/ansible-portal/config.yml
content: |
aap:
host: https://aap.corp.example.com
oauth_client_id: portal-appliance
oauth_client_secret: "{{ vault_portal_oauth_secret }}"
verify_ssl: true
portal:
title: "IT Self-Service Automation"
support_url: "https://helpdesk.corp.example.com"
enable_rbac_nav: true
runcmd:
- systemctl enable --now ansible-portal
- ansible-portal --validate-config /etc/ansible-portal/config.ymlThe oauth_client_id and oauth_client_secret correspond to an Application credential created in AAP:
# Create the portal OAuth application in AAP (ansible.platform module)
cat <<EOF | ansible-playbook -i localhost, /dev/stdin
---
- name: Create portal OAuth application
hosts: localhost
connection: local
tasks:
- name: Create application
ansible.platform.application:
name: portal-appliance
organization: Default
client_type: confidential
authorization_grant_type: password
redirect_uris: "https://portal.corp.example.com/callback"
state: present
EOFKVM Deployment
# Download the QCOW2 appliance from Red Hat registry
podman pull registry.redhat.io/ansible-automation-platform/portal-appliance-rhel9:2.7
podman save registry.redhat.io/ansible-automation-platform/portal-appliance-rhel9:2.7 \
-o portal-appliance-2.7.tar
# Extract the disk image
mkdir -p /var/lib/libvirt/images/portal
tar xf portal-appliance-2.7.tar --wildcards '*.qcow2' \
-C /var/lib/libvirt/images/portal/
# Generate cloud-init ISO
genisoimage -output /tmp/portal-cloud-init.iso \
-volid cidata -joliet -rock \
user-data meta-data
# Deploy the VM
virt-install \
--name ansible-portal \
--memory 4096 \
--vcpus 2 \
--disk /var/lib/libvirt/images/portal/portal-appliance.qcow2,format=qcow2 \
--disk /tmp/portal-cloud-init.iso,device=cdrom \
--os-variant rhel9.4 \
--network bridge=br0 \
--import \
--noautoconsoleSee also: Renew and Change SSL/TLS Certificates in AAP 2.7: Operator-Based OpenShift Installation
OpenShift Virtualization Deployment
# portal-vm.yaml — OpenShift Virtualization VirtualMachine
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: ansible-portal
namespace: automation
spec:
running: true
template:
spec:
domain:
cpu:
cores: 2
memory:
guest: 4Gi
devices:
disks:
- name: rootdisk
disk:
bus: virtio
- name: cloudinit
cdrom:
bus: sata
volumes:
- name: rootdisk
dataVolume:
name: portal-appliance-dv
- name: cloudinit
cloudInitNoCloud:
userData: |
#cloud-config
hostname: ansible-portal
users:
- name: ansible-admin
ssh_authorized_keys:
- ssh-ed25519 AAAAC3Nza...
write_files:
- path: /etc/ansible-portal/config.yml
content: |
aap:
host: https://aap.corp.example.com
oauth_client_id: portal-appliance
oauth_client_secret: "REPLACE_ME"
runcmd:
- systemctl enable --now ansible-portal
---
apiVersion: cdi.kubevirt.io/v1beta1
kind: DataVolume
metadata:
name: portal-appliance-dv
namespace: automation
spec:
source:
registry:
url: "docker://registry.redhat.io/ansible-automation-platform/portal-appliance-rhel9:2.7"
pvc:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20GiAtomic Upgrades with bootc
The appliance is built on RHEL 9 image mode (bootc). Upgrades are atomic and rollback-safe — the running system is never modified in place:
# On the running appliance VM
# Check current image version
bootc status
# Pull and stage the next version
bootc upgrade
# Reboot to activate the new image
systemctl reboot
# If something goes wrong, roll back to the previous version
bootc rollback
systemctl rebootBecause the appliance is container-image-backed, upgrades are as simple as pulling a new image tag. Configuration in /etc/ansible-portal/ and portal data persist across upgrades — only the OS and application binaries change.
See also: Install Ansible Automation Platform in Red Hat Ansible OpenShift Platform operator via Operator
Portal Configuration Features in AAP 2.7
RBAC Navigation Menus
Administrators control which users can access portal sections based on their AAP roles. Configure permitted navigation items in the portal administration section:
| Role | Navigation Access |
|---|---|
| Portal Administrator | All sections |
| Template Operator | Templates, History |
| EE Developer | EE definitions, Collections |
| Viewer | History only |
GitHub Apps Authentication
In addition to personal access tokens, the portal now supports GitHub Apps for source control integration:
- Fine-grained repository permissions scoped to exactly what the portal needs
- Higher GitHub API rate limits compared to PATs
- App credentials rotate automatically via GitHub's installation token mechanism
Job Template Filtering with excludeLabels
Use the excludeLabels Helm chart value (for OCP deployments) or portal config key to hide specific job templates from the self-service catalog without managing an explicit inclusion list:
# portal values for OpenShift Helm chart
portal:
excludeLabels:
- "visibility=internal"
- "tier=infrastructure"
- "env=staging"Job templates in AAP tagged with any of these labels are hidden from portal users. Add the labels in AAP under the job template's Labels section or via ansible.platform:
- name: Tag infrastructure templates as excluded from portal
ansible.platform.job_template:
name: "Database Schema Migration"
labels:
- "visibility=internal"
- "tier=infrastructure"
state: presentConfigurable Support Link
The global header now shows a configurable Support link. The default is https://access.redhat.com/support. Override it to point to your internal help desk:
# /etc/ansible-portal/config.yml
portal:
support_url: "https://helpdesk.corp.example.com/ansible"User-Facing Automation Output
Playbook authors can surface results directly to self-service users using ansible.builtin.debug. The portal displays debug messages in the template log output, making it a lightweight results channel:
- name: Provision web server
hosts: localhost
connection: local
tasks:
- name: Launch EC2 instance
amazon.aws.ec2_instance:
name: "{{ server_name }}"
instance_type: t3.medium
image_id: ami-0c55b159cbfafe1f0
register: ec2
- name: Show connection info to portal user
ansible.builtin.debug:
msg: |
Server provisioned successfully.
Hostname: {{ ec2.instances[0].public_dns_name }}
IP: {{ ec2.instances[0].public_ip_address }}
Connect: ssh ec2-user@{{ ec2.instances[0].public_ip_address }}The portal renders this debug output in the job log panel that users see after launching a template.
FAQ
Can the portal appliance connect to AAP 2.6?
The appliance is released as part of AAP 2.7. Red Hat supports it with AAP 2.7 instances. Compatibility with 2.6 is not guaranteed.
Does the appliance replace the containerized portal install?
No. The appliance is an additional deployment option for teams that prefer VM-based infrastructure over containerized deployments. The containerized and OCP operator install paths still exist and are the primary supported methods for full AAP deployments.
How do I scale the portal appliance?
The appliance is designed for single-VM deployment. For high-availability portal deployments, use the containerized installer or the OpenShift Helm chart, which support multiple replicas behind a load balancer.
What storage does the appliance need?
The base image requires approximately 10 GB. Plan for 20 GB to accommodate portal data, logs, and future upgrades. Persistent /etc/ansible-portal/ configuration survives bootc upgrades.
Related Articles
Category: installation