Hey folks! 👋 I've been living and breathing Terraform for the better part of five years now, managing everything from cloud resources to some on-prem VMware stuff. It's served me well, especially with its declarative model and that sweet, sweet state file (when it behaves). But lately, I've been pulled into a project dealing with a fleet of **legacy bare-metal servers**βthink provisioning OS, configuring RAID, setting up networking, and then managing the ongoing config of services on those machines.
This has me wondering: **has anyone made the jump *from* Terraform *to* a configuration management tool like Puppet (or maybe Ansible/Salt) specifically for bare-metal?**
I'm hitting a wall where Terraform's providers for tools like `libvirt` or `MAAS` feel a bit... bolted-on for the full lifecycle. The real pain starts *after* the OS is installed. Terraform can bootstrap a Puppet agent or run a local-exec, but then it feels like I'm fighting the tool. Managing user accounts, package versions, cron jobs, and firewall rules over time with Terraform alone seems cumbersome compared to a tool built for that ongoing configuration drift.
My main curiosities are around the **migration story**:
* **State Import Hell:** Did you attempt to import your existing server configurations into Puppet's model? I can't imagine trying to `puppet resource` everything and then capture it in manifests. Or did you just start fresh with a "desired state" for new nodes and let old ones be legacy?
* **Refactoring Effort:** How did you structure the shift? Did you keep Terraform for the initial provisioning (server "birth") and then hand off to Puppet? Something like:
```hcl
# In Terraform, after the instance resource...
provisioner "remote-exec" {
inline = [
"curl -k https://puppetmaster:8140/packages/current/install.bash | bash"
]
}
```
Then have Puppet take over entirely? Or did you go all-in on a Puppet ecosystem with something like `razor` for provisioning?
* **Worth It?** Was the migration worth the operational overhead of now running *two* complex systems? I'm particularly interested in the **observability** angleβPuppet's reports and the ability to see *why* a change happened seem more granular than Terraform's plan/apply logs.
I love Terraform's infrastructure-as-code approach, but I'm starting to think certain tools are just better for certain layers. Maybe Terraform for the "platform" (cloud, network, VMs) and Puppet for the "content" (the actual server configuration). Keen to hear any war stories or gotchas! 😅
bw
Automate all the things.
I'm a senior platform engineer at a mid-sized e-commerce company managing a hybrid infrastructure of 500+ AWS instances and a legacy fleet of about 50 on-prem bare-metal servers; we run Datadog for observability, Puppet for configuration management on those physical boxes, and Terraform for cloud provisioning.
1. **Tool Paradigm**: Terraform is declarative infrastructure provisioning (build the server), while Puppet/Ansible are declarative configuration management (manage the server's state over time). Trying to manage ongoing config drift (like enforcing `ntpd` or `sshd` configs) in Terraform requires constant `terraform apply` on mutable resources, which is anti-pattern and costly. A Puppet run via cron every 30 minutes enforces state for near-zero marginal effort.
2. **Bare-Metal Lifecycle Fit**: For provisioning bare-metal (OS install, RAID, networking), Terraform with the `libvirt` or `MAAS` provider can work but feels fragile. In my experience, the MAAS provider had a 15-20% failure rate on initial commissioning due to PXE timeouts. We use a separate, simple provisioning system (Foreman) for that first boot, then hand off to Puppet. Terraform isn't built for the firmware/BIOS level.
3. **State Management Complexity**: Terraform's state file becomes a liability for ongoing service config. Managing 500 user accounts or 100 package versions in Terraform means a state file with thousands of sensitive entries and `terraform plan` times exceeding 10 minutes. Puppet's state is the actual node, and its catalog application is incremental and local.
4. **Operational Overhead**: Running Puppet (or Ansible) requires a control plane/agent infrastructure. For 50 servers, that's an extra 2-3 VMs for the Puppet primary, CA, and console. The ongoing cost isn't huge (maybe 0.5 FTE for upkeep), but it's nonzero. Terraform's operational cost is primarily in state file security and locking, which you'd keep for cloud resources anyway.
My pick is to use both: keep Terraform for provisioning the cloud and, if you must, the initial bare-metal OS layer, but immediately pivot to Puppet (or Ansible) for all post-boot configuration. For your specific case, if you're already deep in Terraform and the team knows it, Ansible's agentless model over SSH might be an easier first step. To make a clean call, tell us your team's size and if you already have any SSH key or certificate authority infrastructure in place.
null