Skip to content

Commit ae2dd80

Browse files
authored
Add Tofu configuration for Ubuntu 24.04 VM on ARM64 for Apple Silicon
This Terraform configuration provisions an Ubuntu 24.04 LTS VM optimized for Apple Silicon with cloud-init support, automatic user configuration, and SSH port forwarding.
1 parent 48fb84c commit ae2dd80

1 file changed

Lines changed: 254 additions & 0 deletions

File tree

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
# Example: Single Ubuntu 24.04 LTS VM on Apple Silicon (ARM64)
2+
#
3+
# This example demonstrates provisioning an Ubuntu 24.04 VM with:
4+
# - ARM64 Architecture support optimized for Apple Silicon (hvf/aarch64)
5+
# - UEFI boot configuration using QEMU edk2 firmware
6+
# - Automatic user configuration (ubuntu:password) via cloud-init
7+
# - Copy-on-Write (CoW) storage using a base cloud image
8+
# - Post-provisioning SSH port forwarding (Host:2222 -> Guest:22)
9+
10+
terraform {
11+
required_providers {
12+
libvirt = {
13+
source = "dmacvicar/libvirt"
14+
version = "0.9.3"
15+
}
16+
}
17+
}
18+
19+
provider "libvirt" {
20+
uri = "qemu:///session?socket=${pathexpand("~/.cache/libvirt/libvirt-sock")}"
21+
}
22+
23+
# Download Ubuntu 24.04 (Noble) ARM64 cloud image
24+
# Ubuntu cloud images provide native cloud-init support for automated setup
25+
resource "libvirt_volume" "ubuntu_base" {
26+
name = "ubuntu-24.04-base.qcow2"
27+
pool = "default"
28+
29+
target = {
30+
format = {
31+
type = "qcow2"
32+
}
33+
}
34+
35+
create = {
36+
content = {
37+
url = "https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-arm64.img"
38+
}
39+
}
40+
}
41+
42+
# Create boot disk for the VM (uses base image as backing store)
43+
# This implements a Copy-on-Write (CoW) layer to save space and time
44+
resource "libvirt_volume" "ubuntu_disk" {
45+
name = "ubuntu-vm.qcow2"
46+
pool = "default"
47+
capacity = 10737418240
48+
49+
target = {
50+
format = {
51+
type = "qcow2"
52+
}
53+
}
54+
55+
backing_store = {
56+
path = libvirt_volume.ubuntu_base.path
57+
format = {
58+
type = "qcow2"
59+
}
60+
}
61+
}
62+
63+
# Cloud-init configuration for the Ubuntu VM
64+
# Defines user credentials, SSH server availability, and timezone
65+
resource "libvirt_cloudinit_disk" "ubuntu_seed" {
66+
name = "ubuntu-cloudinit"
67+
68+
user_data = <<-EOF
69+
#cloud-config
70+
chpasswd:
71+
list: |
72+
ubuntu:password
73+
expire: false
74+
ssh_pwauth: true
75+
packages:
76+
- openssh-server
77+
timezone: UTC
78+
EOF
79+
80+
meta_data = <<-EOF
81+
instance-id: ubuntu-001
82+
local-hostname: ubuntu-vm
83+
EOF
84+
85+
# Network config: Specific interface naming (enp1s0) for Virtio on KVM/Ubuntu
86+
network_config = <<-EOF
87+
version: 2
88+
ethernets:
89+
enp1s0:
90+
dhcp4: true
91+
EOF
92+
}
93+
94+
# Upload cloud-init ISO into the storage pool
95+
# This volume acts as the seed drive for the cloud-init process
96+
resource "libvirt_volume" "ubuntu_seed_volume" {
97+
name = "ubuntu-cloudinit.iso"
98+
pool = "default"
99+
100+
create = {
101+
content = {
102+
url = libvirt_cloudinit_disk.ubuntu_seed.path
103+
}
104+
}
105+
}
106+
107+
# Virtual Machine Definition (Apple Silicon / ARM64 optimized)
108+
# Configures CPU passthrough, UEFI firmware paths, and virtual hardware
109+
resource "libvirt_domain" "ubuntu_vm" {
110+
name = "ubuntu-vm"
111+
memory = 4096
112+
memory_unit = "MiB"
113+
vcpu = 2
114+
type = "hvf" # Hardware acceleration for macOS
115+
running = true
116+
117+
# Boot and Architecture configuration
118+
os = {
119+
type = "hvm"
120+
type_arch = "aarch64"
121+
type_machine = "virt"
122+
123+
# UEFI Loader is required for ARM64 boot on Apple Silicon
124+
loader = "/opt/homebrew/Cellar/qemu/10.2.1/share/qemu/edk2-aarch64-code.fd"
125+
loader_type = "pflash"
126+
127+
# NVRAM setup to persist EFI variables
128+
nv_ram = {
129+
nv_ram = "${abspath(path.module)}/ubuntu-vm_VARS.fd"
130+
template = "/opt/homebrew/Cellar/qemu/10.2.1/share/qemu/edk2-arm-vars.fd"
131+
}
132+
133+
features = {
134+
acpi = true
135+
}
136+
137+
cpu = {
138+
mode = "host-passthrough"
139+
}
140+
}
141+
142+
# Attached devices: Disks, Network, and Consoles
143+
devices = {
144+
disks = [
145+
# Main System Disk
146+
{
147+
source = {
148+
volume = {
149+
pool = libvirt_volume.ubuntu_disk.pool
150+
volume = libvirt_volume.ubuntu_disk.name
151+
}
152+
}
153+
target = {
154+
dev = "vda"
155+
bus = "virtio"
156+
}
157+
driver = {
158+
type = "qcow2"
159+
}
160+
},
161+
# Cloud-init Seed Disk
162+
{
163+
source = {
164+
volume = {
165+
pool = libvirt_volume.ubuntu_seed_volume.pool
166+
volume = libvirt_volume.ubuntu_seed_volume.name
167+
}
168+
}
169+
target = {
170+
dev = "vdb"
171+
bus = "virtio"
172+
}
173+
}
174+
]
175+
176+
# User-mode networking (SLIRP)
177+
interfaces = [
178+
{
179+
type = "user"
180+
model = {
181+
type = "virtio"
182+
}
183+
}
184+
]
185+
186+
# VNC Graphics Configuration
187+
graphics = [
188+
{
189+
vnc = {
190+
auto_port = true
191+
listen = "127.0.0.1"
192+
}
193+
}
194+
]
195+
196+
video = [
197+
{
198+
model = {
199+
type = "virtio"
200+
}
201+
}
202+
]
203+
204+
# Serial and Console access for debugging
205+
serials = [
206+
{
207+
type = "pty"
208+
target = {
209+
type = "system-serial"
210+
port = "0"
211+
model = {
212+
name = "pl011"
213+
}
214+
}
215+
}
216+
]
217+
218+
consoles = [
219+
{
220+
type = "pty"
221+
target = {
222+
type = "serial"
223+
port = "0"
224+
}
225+
}
226+
]
227+
228+
inputs = [
229+
{ type = "tablet", bus = "virtio" },
230+
{ type = "keyboard", bus = "virtio" }
231+
]
232+
}
233+
}
234+
235+
# Post-provisioning: Automatic SSH Port Forwarding
236+
# Maps host port 2222 to guest port 22 via QEMU monitor command (HMP)
237+
resource "null_resource" "auto_ssh_port" {
238+
# Ensure the VM is created before attempting port mapping
239+
depends_on = [libvirt_domain.ubuntu_vm]
240+
241+
# Force execution on every 'apply' to maintain the mapping
242+
triggers = {
243+
always_run = timestamp()
244+
}
245+
246+
provisioner "local-exec" {
247+
command = <<-EOT
248+
echo "Waiting for VM to initialize..."
249+
sleep 10
250+
virsh -c qemu:///session qemu-monitor-command ubuntu-vm --hmp "hostfwd_add hostnet0 tcp::2222-:22"
251+
echo "SSH access available at: ssh ubuntu@localhost -p 2222"
252+
EOT
253+
}
254+
}

0 commit comments

Comments
 (0)