How to Provision Bare Metal Servers with Packer: A Complete Guide with JSON Examples


2 views

While Packer is primarily known for creating machine images for cloud platforms and virtualization, its flexible architecture allows for bare metal provisioning when combined with the right tools. The key lies in using Packer's "null" builder alongside PXE boot and automation tools.

To make this work, you'll need:

  • A PXE boot server (like Cobbler or Foreman)
  • Network boot infrastructure (DHCP + TFTP)
  • Preseed/Kickstart or other unattended installation files
  • IPMI/iDRAC/iLO for remote power management

Here's a basic template to get started:

{
  "builders": [{
    "type": "null",
    "communicator": "ssh",
    "ssh_host": "{{user target_ip}}",
    "ssh_username": "root",
    "ssh_password": "{{user root_password}}",
    "ssh_timeout": "60m"
  }],
  "provisioners": [{
    "type": "shell",
    "inline": [
      "curl -s http://pxe-server/install.sh | bash",
      "reboot"
    ]
  }],
  "post-processors": [],
  "variables": {
    "target_ip": "",
    "root_password": ""
  }
}

The actual OS installation happens through PXE. Your PXE configuration should point to a Kickstart/Preseed file that performs these actions:

  1. Disk partitioning
  2. Base OS installation
  3. Packer SSH key injection
  4. Initial network configuration

For more complex scenarios, combine Packer with Ansible:

{
  "provisioners": [
    {
      "type": "shell",
      "inline": ["apt-get update && apt-get install -y python3"]
    },
    {
      "type": "ansible-local",
      "playbook_file": "playbooks/setup.yml",
      "inventory_groups": "baremetal"
    }
  ]
}

After the base OS is installed, Packer can:

  • Run configuration management tools
  • Install additional packages
  • Set up monitoring agents
  • Configure network services

Some considerations for production use:

  • Hardware detection may vary between servers
  • Driver compatibility issues
  • Longer provisioning times compared to virtual machines
  • Need for manual intervention in case of hardware failures

For large-scale deployments, consider these complementary tools:

  • MAAS (Metal-as-a-Service)
  • Foreman with Puppet
  • Ironic (OpenStack Bare Metal)

While Packer is primarily known for creating machine images for cloud platforms and virtualization systems, it can indeed be adapted for bare-metal provisioning through creative use of its components. The key lies in leveraging Packer's ability to:

  • Serve installation files via built-in HTTP server
  • Automate OS installation through preseed/kickstart
  • Execute post-install provisioning with Ansible/Chef/Puppet
  • Interact with PXE boot environments

The typical workflow involves:

1. PXE Boot → 2. Packer HTTP Server (OS Files) → 3. Auto-install Config → 4. Post-Provisioning

Here's a basic template for a bare-metal Ubuntu installation:

{
  "builders": [{
    "type": "null",
    "communicator": "none"
  }],
  "provisioners": [
    {
      "type": "shell-local",
      "inline": [
        "sudo systemctl start dnsmasq",
        "sudo systemctl start tftpd-hpa"
      ]
    },
    {
      "type": "file",
      "source": "preseed.cfg",
      "destination": "/var/www/html/preseed.cfg"
    }
  ],
  "post-processors": [{
    "type": "manifest",
    "output": "packer-manifest.json"
  }]
}

You'll need to configure your DHCP server to point to Packer's TFTP server:

# Example dnsmasq configuration
dhcp-boot=pxelinux.0
enable-tftp
tftp-root=/var/lib/tftpboot

After OS installation, extend provisioning with Ansible:

{
  "provisioners": [{
    "type": "ansible-local",
    "playbook_file": "site.yml",
    "extra_arguments": [
      "--extra-vars", "host_type=baremetal"
    ]
  }]
}

Use variables to manage different server roles:

{
  "variables": {
    "server_role": "web"
  },
  "provisioners": [{
    "type": "shell-local",
    "script": "scripts/{{user server_role}}-setup.sh"
  }]
}