Terraform module for KVM/Libvirt Virtual Machine. This module will create a KVM Virtual Machine(s), configure it using Cloud Init and test the ssh connection. This module is using dmacvicar/libvirt Terraform provider.
- creates one or more VMs
- one NIC per domain, connected to the network using the bridge interface
- setup network interface using DHCP or static configuration
- cloud_init VM(s) configuration (Ubuntu+Netplan complient)
- optionally add multiple extra disks
- test the ssh connection
- Ubuntu 20.04 TLS Cloud Image
- Ubuntu 22.04 TLS Cloud Image
| Name | Version |
|---|---|
| terraform | >= 1.0 |
| libvirt | >= 0.7.0 |
No modules.
| Name | Type |
|---|---|
| libvirt_cloudinit_disk.commoninit | resource |
| libvirt_domain.virt-machine | resource |
| libvirt_volume.base-volume-qcow2 | resource |
| libvirt_volume.volume-qcow2 | resource |
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| additional_disk_ids | List of volume ids | list(string) | [] | no |
| autostart | Autostart the domain | bool | true | no |
| base_pool_name | Name of base OS image | string | null | no |
| base_volume_name | Name of base OS image | string | null | no |
| bridge | Bridge interface | string | "virbr0" | no |
| cpu_mode | CPU mode | string | "host-passthrough" | no |
| dhcp | Use DHCP or Static IP settings | bool | false | no |
| graphics | Graphics type (can be 'spice' or 'vnc') | string | spice | no |
| index_start | From where the indexig start | number | 1 | no |
| ip_address | List of IP addresses | list(string) | [ | no |
| ip_gateway | IP addresses of a gateway | string | "192.168.123.1" | no |
| ip_nameserver | IP addresses of a nameserver | string | "192.168.123.1" | no |
| local_admin | Admin user without ssh access | string | "" | no |
| local_admin_passwd | Local admin user password | string | "password_example" | no |
| memory | RAM in MB | string | "1024" | no |
| os_img_url | URL to the OS image | string | "https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img" | no |
| pool | Storage pool name | string | "default" | no |
| runcmd | Extra commands to be run with cloud init | list(string) | [ | no |
| share_filesystem | n/a | object({ | { | no |
| ssh_admin | Admin user with ssh access | string | "ssh-admin" | no |
| ssh_keys | List of public ssh keys | list(string) | [] | no |
| ssh_private_key | Private key for SSH connection test (either path to file or key content) | string | null | no |
| system_volume | System Volume size (GB) | number | 10 | no |
| time_zone | Time Zone | string | "UTC" | no |
| vcpu | Number of vCPUs | number | 1 | no |
| vm_count | Number of VMs | number | 1 | no |
| vm_hostname_prefix | VM hostname prefix | string | "vm" | no |
| xml_override | With these variables you can: Enable hugepages; Set USB controllers; Attach USB devices | object({ | { | no |
| bastion_host | ssh bastion host | string | null | no |
| bastion_user | ssh user on bastion host | string | null | no |
| bastion_ssh_private_key | ssh private key for bastion host (either path to file or key content) | string | null | no |
| Name | Description |
|---|---|
| ip_address | n/a |
| name | n/a |
Example with enable HugePages, Attached USB device, changed USB controller model... :
terraform { required_version = ">= 0.13" required_providers { libvirt = { source = "dmacvicar/libvirt" } } } resource "tls_private_key" "ecdsa-p384-bastion" { algorithm = "ECDSA" ecdsa_curve = "P384" } provider "libvirt" { uri = "qemu+ssh://hero@192.168.165.100/system" } module "vm" { source = "MonolithProjects/vm/libvirt" version = "1.8.0" vm_hostname_prefix = "server" vm_count = 3 memory = "2048" vcpu = 1 pool = "terra_pool" system_volume = 20 dhcp = true local_admin = "local-admin" ssh_admin = "ci-user" ssh_private_key = "~/.ssh/id_ed25519" local_admin_passwd = "$6$rounds=4096$xxxxxxxxHASHEDxxxPASSWORD" ssh_keys = [ "ssh-ed25519 AAAAxxxxxxxxxxxxSSHxxxKEY example", ] bastion_host = "10.0.0.1" bastion_user = "admin" bastion_ssh_private_key = tls_private_key.ecdsa-p384-bastion.private_key_pem time_zone = "CET" os_img_url = "file:///home/myuser/ubuntu-20.04-server-cloudimg-amd64.img" xml_override = { hugepages = true, usb_controllers = [ { model = "qemu-xhci" } ], usb_devices = [ { vendor = "0x0bc2", product = "0xab28" } ] pci_devices_passthrough = [ { src_domain = "0x0000", src_bus = "0xc1", src_slot = "0x00", src_func = "0x0", dst_domain = "0x0000", dst_bus = "0x00", dst_slot = "0x08" dst_func = "0x0" }, { src_domain = "0x0000", src_bus = "0xc1", src_slot = "0x00", src_func = "0x1", dst_domain = "0x0000", dst_bus = "0x00", dst_slot = "0x09" dst_func = "0x0" } ] } } output "ip_addresses" { value = module.nodes }Static IP settings... :
terraform { required_version = ">= 0.13" required_providers { libvirt = { source = "dmacvicar/libvirt" version = "0.6.3" } } } provider "libvirt" { uri = "qemu+ssh://hero@192.168.165.100/system" } module "vm" { source = "MonolithProjects/vm/libvirt" version = "1.8.0" vm_hostname_prefix = "server" vm_count = 3 memory = "2048" vcpu = 1 pool = "terra_pool" system_volume = 20 share_filesystem = { source = "/tmp" target = "tmp" readonly = false } dhcp = false ip_address = [ "192.168.165.151", "192.168.165.152", "192.168.165.153" ] ip_gateway = "192.168.165.254" ip_nameserver = "192.168.165.104" local_admin = "local-admin" ssh_admin = "ci-user" ssh_private_key = "~/.ssh/id_ed25519" local_admin_passwd = "$6$rounds=4096$xxxxxxxxHASHEDxxxPASSWORD" ssh_keys = [ "ssh-ed25519 AAAAxxxxxxxxxxxxSSHxxxKEY example", ] time_zone = "CET" os_img_url = "file:///home/myuser/ubuntu-20.04-server-cloudimg-amd64.img" } output "outputs" { value = module.nodes }The shared directory from the example can be mounted inside the VM with command
sudo mount -t 9p -o trans=virtio,version=9p2000.L,rw tmp /host/tmp
Create a VM with an extra disk
# Creates a 50GB extra-data-disk within vms pool resource "libvirt_volume" "data_volume" { pool = "vms" name = "extra-data-disk.qcow2" format = "qcow2" size = 1024*1024*1024*50 } module "vm" { source = "MonolithProjects/vm/libvirt" version = "1.8.0" vm_hostname_prefix = "data-server" base_volume_name = "debian-11-base.qcow2" base_pool_name = "linked-images" vm_count = 1 bridge = "bridge-dmz" memory = "4096" vcpu = 4 pool = "vms" system_volume = 25 additional_disk_ids = [ libvirt_volume.data_volume.id ] dhcp = true ssh_admin = "admin" ssh_keys = [ chomp(file("~/.ssh/id_rsa.pub")) ] time_zone = "America/Argentina/Buenos_Aires" } output "ip_addresses" { value = module.vm } output_data = { "ip_address" = [ "192.168.165.151", "192.168.165.152", "192.168.165.153", ] "name" = [ "server01", "server02", "server03", ] }MIT
Created in 2020 by Michal Muransky