Skip to main content

πŸ“œ Templates

Templates are the basis of every VM deployed by Ludus. Unlike other solutions, Ludus templates are built from scratch (ISO), and by design don't contain any customization. This allows users to modify base templates into arbitrary VMs during a deploy without having to maintain a library of stale, customized VMs. This focus on infrastructure as code allows Ludus users to create fresh, up to date VMs every deployment.

Ludus supports highly customized templates if that is your preferred option, but all the builtin and included templates deploy the bare minimum to allow Ansible to work (python3/powershell and SSH/WinRM) and a user to connect (RDP, SSH, KasmVNC).

Builtin Templates​

Ludus comes with 5 builtin templates:

  • debian11
  • debian12
  • kali
  • win11-22h2-x64-enterprise
  • win2022-server-x64

Users can add their own templates to the Ludus server with the Ludus CLI. Additional templates are provided in the templates directory in the root of the git project as examples and have been tested to work with Ludus. These templates include:

  • debian10
  • rocky-9-x64-server
  • ubuntu-20.04-x64-server
  • ubuntu-22.04-x64-server
  • win10-21h1-x64-enterprise
  • win11-23h2-x64-enterprise
  • win2012r2-server-x64
  • win2016-server-x64
  • win2019-server-x64
  • commando-vm
  • flare-vm
  • remnux

Adding Templates to Ludus​

To add a template to Ludus, use the Ludus CLI to upload the template directory to the server with ludus templates add -d <template directory>.

local:~$ git clone https://gitlab.com/badsectorlabs/ludus
local:~$ cd templates
local:~$ ls -1
debian10
manual-setup-required
rocky-9-x64-server
ubuntu-22.04-x64-server
win10-21h1-x64-enterprise
win11-23h2-x64-enterprise
win2012r2-server-x64
win2022-server-x64
local:~$ ludus templates add -d debian10
[INFO] Successfully added template
local:~$ ludus templates list
+----------------------------------------+-------+
| TEMPLATE | BUILT |
+----------------------------------------+-------+
| debian-11-x64-server-template | TRUE |
| debian-12-x64-server-template | TRUE |
| kali-x64-desktop-template | TRUE |
| win11-22h2-x64-enterprise-template | TRUE |
| win2016-server-x64-template | TRUE |
| win2019-server-x64-template | TRUE |
| debian-10-x64-server-template | FALSE |
| debian-12-x64-server-ludus-ci-template | TRUE |
+----------------------------------------+-------+
local:~$ ludus templates build -n debian-10-x64-server-template
[INFO] Template building started
local:~$ ludus templates logs -f
2024/01/17 18:19:11 [INFO] Packer version: 1.9.4 [go1.20.7 linux amd64]
2024/01/17 18:19:11 [TRACE] discovering plugins in /opt/ludus/resources/packer/plugins
2024/01/17 18:19:11 [INFO] Discovered potential plugin: ansible = /opt/ludus/resources/packer/plugins/github.com/hashicorp/ansible/packer-plugin-ansible_v1.1.1_x5.0_linux_amd64
...

Creating Your Own Templates for Ludus​

Templates in Ludus must contain certain variables to function correctly. To create a new template, copy an existing working template and modify it as necessary. Templates for different Linux flavors and Windows are provided. While macOS VMs are supported by Ludus, their automated templating is not (see Non-Automated OS Template Builds).

Every Ludus template is a packer file (.pkr.hcl and .pkr.json supported, but .pkr.hcl preferred), and any supporting files (resources, scripts, etc.). The template file MUST include the .pkr. portion of the file name to be recognized as valid by Ludus.

Ludus template packer files must include the following variables, which are set dynamically by Ludus during build time:

# This block has to be in each file or packer won't be able to use the variables
variable "proxmox_url" {
type = string
}
variable "proxmox_host" {
type = string
}
variable "proxmox_username" {
type = string
}
variable "proxmox_password" {
type = string
sensitive = true
}
variable "proxmox_storage_pool" {
type = string
}
variable "proxmox_storage_format" {
type = string
}
variable "proxmox_skip_tls_verify" {
type = bool
}
variable "proxmox_pool" {
type = string
}
variable "iso_storage_pool" {
type = string
}
variable "ansible_home" {
type = string
}
variable "ludus_nat_interface" {
type = string
}
####

These variables are to be used in the packer configuration to ensure that the template is built correctly depending on how the Ludus server is configured (i.e. with a custom ZFS storage pool).

The template name displayed by Ludus is extracted with the following regex: (?m)[^"]*?-template. Therefore, be sure to have a string in your packer file that includes -template that will be used as the template name. Typically this is the vm_name variable.

It is the Ludus convention to use localuser:password as the user account for templates unless there is a reason not to (i.e. kali).

Performance Options​

Disk​

For best performance of VMs in Proxmox, it is recommended to set the following options:

  scsi_controller = "virtio-scsi-single" # Allows the use of io_thread for the disk
disks {
disk_size = "${var.vm_disk_size}"
format = "${var.proxmox_storage_format}"
storage_pool = "${var.proxmox_storage_pool}"
type = "virtio"
discard = true # allows Proxmox to reclaim space when files are deleted
io_thread = true
}

IOThreads deliver performance gains exceeding 15% at low queue depth. The performance benefits of an IOThread (for a single storage device) appear to diminish with increasing queue depth. However, in most cases, the benefits outweigh any potential consequences.

Source

Network​

For network hardware, virtio is recommended if the guest supports it (see any Windows template provided with Ludus for how to automatically install the virtio drivers during install):

  network_adapters {
bridge = "${var.ludus_nat_interface}"
model = "virtio"
}

While the e1000 adaptor is an emulated Intel network card, the virtio adaptor is paravirtualized and much faster.

CPU​

Setting cpu_type = "host" in your template will essentially "pass through" the CPU without any compatibility to migrate between hosts with different CPUs.

If you don’t care about live migration or have a homogeneous cluster where all nodes have the same CPU and same microcode version, set the CPU type to host, as in theory this will give your guests maximum performance.

Source

Non-Automated OS Template Builds​

To manually upload ISO files, click the datastore, then ISO Images, then Upload.

&#39;The Ludus Network&#39;

Windows 7​

If you wish to use VirtIO devices during install, follow this guide.

  1. Download the Windows 7 ISO (md5: 1d0d239a252cb53e466d39e752b17c28)
  2. Create a VM with your desired hardware options
  3. Boot the VM and install Windows 7
  4. Install an old version of the virtio drivers manually
  5. Install Service Pack 1 from here
  6. Install .NET 4.5 from here
  7. Install Windows Management Framework 5.1 from here and reboot
  8. Copy the setup-for-ansible.ps1 script to the host and run powershell -exec bypass .\setup-for-ansible.ps1
  9. Convert to template

Windows 2008 R2 x64​

  1. Download the Windows 2008 R2 x64 ISO (sha1: a548d6743129f2a02c907d2758773a1f6bb1bcd7)
  2. Create a VM with your desired hardware options
  3. Boot the VM and install Windows 2008 R2
  4. Install an old version of the virtio drivers manually
  5. Install Firefox because IE8 (yes 8) can't load Microsoft sites
  6. Install SP1 from here
  7. Install KB2677070-x64.msu from here
  8. Download and install the MicrosoftRootCertificateAuthority2011.cer into Trusted Root Certification Authorities (guide) from here
  9. Set the date to 2013-10-10
  10. Download and install the .Net 4.5.2 offline installer from here
  11. Reset the date to current date
  12. Install Windows Management Framework 5.1 from here and reboot
  13. Copy the setup-for-ansible.ps1 script to the host and run powershell -exec bypass .\setup-for-ansible.ps1
  14. Convert to template

macOS​

  1. Follow this
  2. Run python3 in a terminal in the VM to install python3
  3. Optionally, install Xcode or other tools
  4. Convert to template
warning

The VM name MUST include the string macos to be properly identified as macOS by the dynamic inventory script since macOS doesn't have QEMU agent support.