This guide walks you through setting up Morpheus 8 to provision virtual machines both on-prem (vSphere, KVM, Hyper-V) and in the cloud (AWS, Azure, etc.), and to automatically configure them using Ansible (Standalone mode) running from the Morpheus appliance.
Ensure your VM image (on-prem or cloud) includes:
- OS: Ubuntu, CentOS, RHEL, etc.
- User: A non-root user (e.g.
ubuntu
,morpheus
,centos
) - SSH Access:
- Public key added to
~/.ssh/authorized_keys
sshd
enabled
- Public key added to
- Sudo Access:
- Passwordless sudo configured:
echo "morpheus ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/morpheus
- Passwordless sudo configured:
Navigate to: Infrastructure > Clouds > + Add
- For on-prem:
- VMware vCenter
- KVM (libvirt)
- Hyper-V
- For cloud:
- AWS, Azure, GCP, etc.
- Provide access credentials, resource pools, networks
Navigate to: Infrastructure > Credentials > + Add
- Type: SSH Key or Username/Password
- Username: User in your base image
- Private Key: Paste SSH private key
- Save and assign to your Cloud or Instance Layout
Go to: Library > Instance Types > + Add
- Name:
Linux-Base
(example) - Create a Layout:
- Select Cloud, image/template, size
- Assign credential and provisioning method (Cloud-Init if supported)
Navigate to: Admin > Integrations > + Add
- Type: Ansible
- Mode: Standalone
- Executable Path:
/usr/bin/ansible-playbook
- Save the integration
Navigate to: Library > Templates > Scripts > + Add
- Name:
Configure Webserver
- Type: Ansible Playbook
- Upload a
.yml
file or ZIP withsite.yml
- Choose your Ansible integration
Navigate to: Admin > Integrations > Code Repositories > + Add
- Add your Git repo (public or private)
- Morpheus syncs your playbooks automatically
You can use a flat playbook or a role-based layout. Example below:
---
- name: Configure VM post-provision
hosts: all
become: yes
vars:
ansible_python_interpreter: /usr/bin/python3
roles:
- webserver
---
- name: Install NGINX
apt:
name: nginx
state: present
when: ansible_os_family == "Debian"
- name: Start NGINX
service:
name: nginx
state: started
enabled: yes
server {
listen 80;
server_name {{ inventory_hostname }};
root /var/www/html;
}
Go to: Library > Automation > Tasks > + Add
- Type: Ansible Playbook
- Select uploaded
.yml
or synced playbook - Choose the correct Ansible integration
Go to: Library > Automation > Workflows > + Add
- Type: Provisioning Workflow
- Add the Ansible Task you just created
Attach the workflow to:
- Instance Layout
- Blueprint
- Or manually during provisioning
Go to: Library > Instance Types > [Layout] > Automation Tab
Attach the Provisioning Workflow
Provision a new VM using your configured Instance Type. Then:
- Navigate to:
Instances > [Your VM] > History
- View the Automation Logs to confirm Ansible executed successfully
Create a Cloud-Init script to inject keys and users at build time:
#cloud-config
users:
- name: morpheus
sudo: ALL=(ALL) NOPASSWD:ALL
groups: sudo
shell: /bin/bash
ssh_authorized_keys:
- ssh-rsa AAAAB3Nza...your_key_here...
disable_root: true
ssh_pwauth: false
Upload at: Library > Templates > Scripts > + Add
Type: Cloud-Init
Attach to your Layoutβs Provisioning Scripts section
Step | Action |
---|---|
β | Prepare image with SSH, user, sudo |
β | Add Cloud (vSphere, AWS, etc.) |
β | Create and assign Credentials |
β | Set up Ansible Standalone Integration |
β | Upload or sync Ansible Playbooks |
β | Create Ansible Task & Workflow |
β | Attach Workflow to Layout or Blueprint |
β | Provision VM and confirm automation |
Add this task to print host info during provisioning:
- name: Debug host info
debug:
msg: "Hostname: {{ inventory_hostname }}, IP: {{ ansible_host }}, Cloud: {{ cloud_name | default('N/A') }}"