Skill

infrastructure-as-code

Use when the user asks about Terraform, Ansible, or infrastructure-as-code approaches for managing Unraid servers, VMs, or configuration. Examples: "terraform unraid", "ansible unraid", "infrastructure as code", "iac unraid", "terraform libvirt".

From unraid-assistant
Install
1
Run in your terminal
$
npx claudepluginhub jamesprial/prial-plugins --plugin unraid-assistant
Tool Access

This skill uses the workspace's default tool permissions.

Skill Content

Infrastructure as Code for Unraid

No first-class Unraid provider exists for Terraform or Ansible. All IaC uses generic tools (libvirt provider, raw SSH). This contrasts with Proxmox and ESXi which have dedicated providers.

Terraform with libvirt Provider

The dmacvicar/libvirt Terraform provider manages VMs on any libvirt/KVM host, including Unraid.

Provider Configuration

terraform {
  required_providers {
    libvirt = {
      source  = "dmacvicar/libvirt"
      version = "~> 0.8"
    }
  }
}

# Local connection (run Terraform on Unraid itself)
provider "libvirt" {
  uri = "qemu:///system"
}

# Remote connection over SSH
provider "libvirt" {
  uri = "qemu+ssh://root@192.168.1.100/system"
}

# Remote connection over TCP (requires libvirtd config)
provider "libvirt" {
  uri = "qemu+tcp://192.168.1.100/system"
}

Enable Remote libvirt TCP Access

Edit /etc/libvirt/libvirtd.conf on the Unraid host (set listen_tls = 0, listen_tcp = 1, auth_tcp = "none", tcp_port = "16509"), then restart with /etc/rc.d/rc.libvirt restart. IMPORTANT: TCP with auth_tcp = "none" has no authentication. Use SSH transport in production.

Resource Types

ResourcePurpose
libvirt_domainVM definition (CPU, memory, disk, network)
libvirt_volumeDisk image (qcow2, raw) in a storage pool
libvirt_networkVirtual network definition
libvirt_cloudinit_diskCloud-init NoCloud ISO generation
libvirt_poolStorage pool definition

Example: Provision a Linux VM

resource "libvirt_volume" "ubuntu_base" {
  name   = "ubuntu-base.qcow2"
  pool   = "domains"
  source = "/mnt/user/isos/jammy-server-cloudimg-amd64.img"
  format = "qcow2"
}

resource "libvirt_volume" "vm_disk" {
  name           = "myvm-disk.qcow2"
  pool           = "domains"
  base_volume_id = libvirt_volume.ubuntu_base.id
  size           = 42949672960  # 40 GiB in bytes
}

resource "libvirt_cloudinit_disk" "vm_cloudinit" {
  name      = "myvm-cloudinit.iso"
  pool      = "domains"
  user_data = <<-EOF
    #cloud-config
    hostname: myvm
    users:
      - name: admin
        sudo: ALL=(ALL) NOPASSWD:ALL
        ssh_authorized_keys:
          - ${var.ssh_public_key}
    packages:
      - qemu-guest-agent
    runcmd:
      - systemctl enable --now qemu-guest-agent
  EOF
}

resource "libvirt_domain" "myvm" {
  name   = "MyVM"
  memory = 4096
  vcpu   = 4

  cpu {
    mode = "host-passthrough"
  }

  disk {
    volume_id = libvirt_volume.vm_disk.id
    scsi      = true
  }

  cloudinit = libvirt_cloudinit_disk.vm_cloudinit.id

  network_interface {
    bridge = "br0"
  }

  graphics {
    type        = "vnc"
    listen_type = "address"
  }

  boot_device {
    dev = ["hd"]
  }

  firmware = "/usr/share/qemu/ovmf-x64/OVMF_CODE-pure-efi.fd"
}

output "vm_ip" {
  value = libvirt_domain.myvm.network_interface[0].addresses
}

The libvirt_cloudinit_disk resource auto-generates a NoCloud ISO. Combine with base_volume_id on libvirt_volume to create VMs from cloud images without manual ISO creation. VM provisioning typically completes in under 2 minutes. See mcreekmore/unraid-terraform on GitHub for a working reference.

Ansible over SSH

Prerequisites

  1. Python on Unraid: Install via the Nerd Scripts plugin (Community Applications)
  2. SSH key access: Copy your public key to /root/.ssh/authorized_keys on Unraid
  3. Persist SSH keys: Add key restoration to /boot/config/go since Unraid runs from RAM

Inventory

[unraid]
tower ansible_host=192.168.1.100 ansible_user=root ansible_python_interpreter=/usr/bin/python3

Example Playbook

---
- name: Configure Unraid server
  hosts: unraid
  gather_facts: false  # Unraid may lack standard fact paths

  tasks:
    - name: Ensure appdata directory exists
      file:
        path: /mnt/user/appdata/myapp
        state: directory
        mode: "0755"

    - name: Copy Docker template
      copy:
        src: templates/myapp.xml
        dest: /boot/config/plugins/dockerMan/templates-user/my-myapp.xml
        mode: "0644"

    - name: Start container via Docker CLI
      command: docker start myapp
      ignore_errors: true

    - name: Define VM from XML
      command: virsh define /tmp/myvm.xml

    - name: Copy user script
      copy:
        src: scripts/backup.sh
        dest: /boot/config/plugins/user.scripts/scripts/backup/script
        mode: "0755"

Community Projects

ProjectDescription
digilink/unraid-ansibleAnsible roles for Unraid configuration
zance1054/unraidAnsiblePlaybooks for common Unraid tasks

Ansible Limitations on Unraid

  • No Ansible Galaxy collection exists for Unraid
  • Many Ansible modules assume systemd, which Unraid does not use (Slackware-based)
  • Use command or raw modules for Unraid-specific CLI tools (mdcmd, emcmd, virsh)
  • Fact gathering may fail; use gather_facts: false and collect manually

Known Gaps

No dedicated Unraid Terraform provider or Ansible Galaxy collection exists. Proxmox and ESXi both have first-class IaC support. The libvirt provider covers VM provisioning, but Unraid-specific features (array, shares, Docker templates, plugins) have no IaC abstractions.

Similar Skills
cache-components

Expert guidance for Next.js Cache Components and Partial Prerendering (PPR). **PROACTIVE ACTIVATION**: Use this skill automatically when working in Next.js projects that have `cacheComponents: true` in their next.config.ts/next.config.js. When this config is detected, proactively apply Cache Components patterns and best practices to all React Server Component implementations. **DETECTION**: At the start of a session in a Next.js project, check for `cacheComponents: true` in next.config. If enabled, this skill's patterns should guide all component authoring, data fetching, and caching decisions. **USE CASES**: Implementing 'use cache' directive, configuring cache lifetimes with cacheLife(), tagging cached data with cacheTag(), invalidating caches with updateTag()/revalidateTag(), optimizing static vs dynamic content boundaries, debugging cache issues, and reviewing Cache Component implementations.

138.5k
Stats
Stars0
Forks0
Last CommitFeb 17, 2026