add vmware-linux template (#527)

## Description

Add Vmware template to coder

## Type of Change

- [ ] New module
- [x] New template
- [ ] Bug fix
- [ ] Feature/enhancement
- [ ] Documentation
- [ ] Other


## Template Information

<!-- Delete this section if not applicable -->

**Path:** `registry/anis/templates/vmware-linux`

## Testing & Validation

- [x] Tests pass (`bun test`)
- [x] Code formatted (`bun fmt`)
- [x] Changes tested locally


https://github.com/user-attachments/assets/ffc787a8-4335-4602-a405-c475f0cad62b


## Related Issues
Closes #211 
/claim #211 
<!-- Link related issues or write "None" if not applicable -->

---------

Signed-off-by: Anis KHALFALLAH <khalfallah.anis@hotmail.com>
Co-authored-by: DevCats <christofer@coder.com>
This commit is contained in:
Anis
2026-01-08 16:04:42 +01:00
committed by GitHub
parent e8e3a4e642
commit 82a76de3fc
6 changed files with 408 additions and 0 deletions
+14
View File
@@ -0,0 +1,14 @@
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" width="128px" height="128px">
<path fill="#00C1D5" d="M60.3,2.3H20.2c0,0-15.8,0.8-18,18v86.3c0,0,1.1,17.3,19.1,19.1h35.1l5.3-5.3H21.9c0,0-12.6-1.6-14.2-14.2
V21.4c0,0-0.5-12.8,14-14h33.9L60.3,2.3z" />
<path fill="#78BD20" d="M67.7,125.7h40.1c0,0,15.8-0.8,18-18V21.4c0,0-1.1-17.3-19.1-19.1H71.7l-5.3,5.3h39.7c0,0,12.6,1.6,14.2,14.2
v84.8c0,0,0.5,12.8-14,14H72.5L67.7,125.7z" />
<g fill="#0091DA">
<path d="M100.1,109.9C100.1,109.9,100,109.9,100.1,109.9H47.6c-6.5,0-8.8-5.8-9.1-8.9l0-0.2V46.8
c0-7.3,6.3-9.5,9.6-9.6l0.1,0l52.7,0.2c6.6,0,9,6,9.3,9.1l0,0.2v53c0,3-0.9,5.5-2.8,7.3C104.6,109.8,100.7,109.9,100.1,109.9z
M42.5,100.6c0.1,0.8,0.9,5.3,5.1,5.3h52.5c0.1,0,2.8,0,4.6-1.7c1-1,1.5-2.5,1.5-4.4V46.9c-0.1-0.9-1-5.5-5.4-5.5l-52.6-0.2
c-0.7,0-5.7,0.5-5.7,5.6V100.6z" />
<path d="M33.2,85.4h-7c-3.9,0-4.6-4.1-4.8-4.9V26.7c0-4.8,4.5-5.2,5.3-5.3l52.7,0.2h0c4,0,4.8,4.3,5,5.1v5.5h4.8v-5.6
l0-0.3c-0.4-3.3-2.9-9.5-9.7-9.5l-52.8-0.2c-3.4,0.1-9.9,2.4-9.9,10v53.9l0,0.3c0.3,3.2,2.8,9.3,9.5,9.3l7,0V85.4z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

+12
View File
@@ -0,0 +1,12 @@
---
display_name: "Anis Khalfallah"
bio: "DevOps Engineer"
github: "aniskhalfallah"
avatar: "./.images/avatar.png"
linkedin: "https://www.linkedin.com/in/khalfallah-anis/"
status: "community"
---
# Anis KHALFALLAH
DevOps Engineer
@@ -0,0 +1,81 @@
---
display_name: VMware vSphere VM (Linux)
description: Provision VMware vSphere virtual machines as Coder workspaces
icon: ../../../../.icons/vsphere.svg
verified: false
tags: [vm, linux, vmware, vsphere]
---
# Summary
Provision VMware vSphere virtual machines as [Coder workspaces](https://coder.com/docs/workspaces) using this Terraform template.
## Prerequisites
To deploy Coder workspaces on VMware vSphere, you'll need the following:
### vSphere Resources
Before deploying, ensure your vSphere environment has:
- A **vSphere Datacenter** already created
- A **Compute Cluster** within that datacenter
- A **Datastore** with sufficient storage capacity
- A **Network** (port group) accessible by VMs
- A **VM Template** with Ubuntu and cloud-init configured
### VM Template Requirements
Your VM template must have
- **cloud-init** installed and configured for VMware datasource
### vSphere Authentication
You'll need the following credentials:
- **vSphere Server** (hostname or IP)
- **Username**
- **Password**
- **Datacenter Name**
- **Cluster Name**
- **Datastore Name**
- **Network Name**
- **VM Template Name**
[VMware Provider Documentation](https://registry.terraform.io/providers/hashicorp/vsphere/latest/docs)
---
## Example `.tfvars` File
```hcl
vsphere_server = "vcenter.example.com"
vsphere_username = "administrator@vsphere.local"
vsphere_password = "YourSecurePassword123!"
vsphere_datacenter = "DC01"
cluster_name = "Cluster01"
vsphere_datastore = "datastore1"
vsphere_network = "VM Network"
vm_template = "ubuntu-22.04-cloud-init-template"
```
---
## Architecture
This template creates:
- A **vSphere Virtual Machine** per workspace
- **Dynamic resource allocation** (CPU, memory configurable by users)
- **Two disks**: root disk (from template) and separate home volume
- **Coder agent** installed via cloud-init
- **code-server** for browser-based VS Code access
## Workspace Parameters
Users can customize their workspace with:
- **VCPUs**: 1, 2, 4, or 8 virtual CPUs
- **Memory**: 1, 2, 4, 8, 16, or 32 GB RAM
- **Home Volume Size**: 10-1024 GB (default: 20 GB)
@@ -0,0 +1,56 @@
#cloud-config
hostname: ${hostname}
users:
- name: ${username}
sudo: ["ALL=(ALL) NOPASSWD:ALL"]
groups: sudo
shell: /bin/bash
packages:
- git
- curl
- wget
- unzip
disk_setup:
/dev/sdb:
table_type: "gpt"
layout: true
overwrite: false
fs_setup:
- label: ${home_volume_label}
filesystem: ext4
device: /dev/sdb
partition: auto
mounts:
- ["/dev/sdb", "/home/${username}", "ext4", "defaults", "0", "2"]
write_files:
- path: /opt/coder/init
permissions: "0755"
encoding: b64
content: ${init_script}
- path: /etc/systemd/system/coder-agent.service
permissions: "0644"
content: |
[Unit]
Description=Coder Agent
After=network-online.target
Wants=network-online.target
[Service]
User=${username}
ExecStart=/opt/coder/init
Environment=CODER_AGENT_TOKEN=${coder_agent_token}
Restart=always
RestartSec=10
TimeoutStopSec=90
KillMode=process
OOMScoreAdjust=-1000
SyslogIdentifier=coder-agent
[Install]
WantedBy=multi-user.target
runcmd:
- mkdir -p /home/${username}
- chown ${username}:${username} /home/${username}
- systemctl enable coder-agent
- systemctl start coder-agent
@@ -0,0 +1,245 @@
terraform {
required_providers {
coder = {
source = "coder/coder"
}
vsphere = {
source = "vmware/vsphere"
}
}
}
provider "vsphere" {
user = var.vsphere_username
password = var.vsphere_password
vsphere_server = var.vsphere_server
allow_unverified_ssl = var.unverified_ssl
}
variable "vsphere_username" {
type = string
default = ""
}
variable "vsphere_password" {
type = string
default = ""
sensitive = true
}
variable "vsphere_server" {
type = string
default = ""
}
variable "datacenter_name" {
type = string
default = ""
}
variable "cluster_name" {
type = string
default = ""
}
variable "datastore_name" {
type = string
default = ""
sensitive = true
}
variable "network_name" {
type = string
default = ""
}
variable "vm_template" {
type = string
default = ""
}
variable "unverified_ssl" {
type = bool
default = true
}
locals {
vm_name = "coder-${lower(data.coder_workspace_owner.me.name)}-${lower(data.coder_workspace.me.name)}"
root_disk_label = substr("${local.vm_name}-root", 0, 32)
home_volume_label = substr("${local.vm_name}-home", 0, 32)
}
data "coder_parameter" "instance_vcpus" {
name = "instance_vcpus"
display_name = "vCPUs"
description = "Number of vCPUs "
type = "number"
default = 1
mutable = true
option {
name = "1 vCPU"
value = 1
}
option {
name = "2 vCPUs"
value = 2
}
option {
name = "4 vCPUs"
value = 4
}
option {
name = "8 vCPUs"
value = 8
}
}
data "coder_parameter" "instance_memory" {
name = "instance_memory"
display_name = "Memory (GB)"
description = "Amount of RAM"
type = "number"
default = 2048
mutable = true
option {
name = "1 GB"
value = 1024
}
option {
name = "2 GB"
value = 2048
}
option {
name = "4 GB"
value = 4096
}
option {
name = "8 GB"
value = 8192
}
option {
name = "16 GB"
value = 16384
}
option {
name = "32 GB"
value = 32768
}
}
data "coder_parameter" "home_volume_size" {
name = "home_volume_size"
display_name = "Home Volume Size (GB)"
description = "How large would you like your home volume to be (in GB)?"
type = "number"
default = 20
mutable = true
validation {
min = 10
max = 1024
monotonic = "increasing"
}
}
data "coder_workspace" "me" {}
data "coder_workspace_owner" "me" {}
resource "coder_agent" "main" {
os = "linux"
arch = "amd64"
metadata {
key = "cpu"
display_name = "CPU Usage"
interval = 5
timeout = 5
script = "coder stat cpu"
}
metadata {
key = "memory"
display_name = "Memory Usage"
interval = 5
timeout = 5
script = "coder stat mem"
}
metadata {
key = "home"
display_name = "Home Usage"
interval = 600 # every 10 minutes
timeout = 30 # df can take a while on large filesystems
script = "coder stat disk --path /home/${lower(data.coder_workspace_owner.me.name)}"
}
}
data "vsphere_datacenter" "dc" {
name = var.datacenter_name
}
data "vsphere_datastore" "datastore" {
name = var.datastore_name
datacenter_id = data.vsphere_datacenter.dc.id
}
data "vsphere_compute_cluster" "cluster" {
name = var.cluster_name
datacenter_id = data.vsphere_datacenter.dc.id
}
data "vsphere_network" "network" {
name = var.network_name
datacenter_id = data.vsphere_datacenter.dc.id
}
data "vsphere_virtual_machine" "template" {
name = var.vm_template
datacenter_id = data.vsphere_datacenter.dc.id
}
locals {
cloud_init_config = templatefile("cloud-init/cloud-config.yaml.tftpl", {
hostname = local.vm_name
username = lower(data.coder_workspace_owner.me.name)
home_volume_label = local.home_volume_label
init_script = base64encode(coder_agent.main.init_script)
coder_agent_token = coder_agent.main.token
})
}
resource "vsphere_virtual_machine" "workspace" {
name = local.vm_name
firmware = data.vsphere_virtual_machine.template.firmware
resource_pool_id = data.vsphere_compute_cluster.cluster.resource_pool_id
datastore_id = data.vsphere_datastore.datastore.id
num_cpus = data.coder_parameter.instance_vcpus.value
memory = data.coder_parameter.instance_memory.value
guest_id = data.vsphere_virtual_machine.template.guest_id
scsi_type = data.vsphere_virtual_machine.template.scsi_type
network_interface {
network_id = data.vsphere_network.network.id
adapter_type = data.vsphere_virtual_machine.template.network_interface_types[0]
}
disk {
label = "disk0"
size = data.vsphere_virtual_machine.template.disks.0.size
}
disk {
label = local.home_volume_label
size = data.coder_parameter.home_volume_size.value
unit_number = 1
}
extra_config = {
"guestinfo.userdata" = base64encode(local.cloud_init_config)
"guestinfo.userdata.encoding" = "base64"
}
clone {
template_uuid = data.vsphere_virtual_machine.template.id
}
}
module "code-server" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/code-server/coder"
version = "~> 1.0"
agent_id = coder_agent.main.id
order = 1
}