This article is currently an experimental machine translation and may contain errors. If anything is unclear, please refer to the original Chinese version. I am continuously working to improve the translation.
Introduction
I’ve previously used Ansible to manage a series of VPS instances, but until now I hadn’t applied it to my HomeLab setup.
Recently, my HomeLab underwent some hardware changes and upgrades. However, since I found some of my earlier blog posts overly verbose and dull, I’ve decided to consolidate minor updates into a dedicated HomeLab Changelog. As such, I won’t go into detail here about the hardware changes over the past year.
TL;DR: Replaced SSDs from SN640 7.68T to Dongting N2 1.92T, upgraded CPU from 10100 to 10900 ES (significant performance boost), and removed an externally attached 120G SATA SSD.
Taking advantage of the need to reinstall PVE due to disk and filesystem changes, I decided it was time to start managing my PVE host configuration with Ansible.
Infrastructure-as-Code (IaC)
Ansible vs NixOps
I’ve used Ansible before—despite the fair share of criticism about its false claims to reproducibility and declarative programming, it’s just really convenient to write with. I now treat Ansible more like a scripting language enriched with many idempotent templates (e.g., creating files, starting services, installing packages, etc.).
One major downside of Ansible is its slowness. I’ve already noticed this when deploying multiple VPS instances, and one can only imagine how painful it would be to manage hundreds of servers this way.
Another issue is its “fake” reproducibility. Even if a playbook follows best practices perfectly, the final result still depends heavily on the initial system state—Ansible doesn’t actually manage system state. For example, running the same playbook on Debian 11 vs Debian 12 might yield different outcomes due to differences in default software versions and configurations. This also means there’s no built-in rollback mechanism—you either write a new playbook to revert changes or manually SSH in to fix things.
That said, in the context of a HomeLab, both drawbacks are acceptable: there’s only one server, so speed isn’t critical; and the PVE host runs minimal software, making the environment relatively simple and predictable. Ansible still helps me manage most configurations far better than doing everything manually.
Bottom line: just treat Ansible as a fancy shell script.
Before settling on Ansible, I also considered the trendy cult of recent years NixOS.
NixOS, by contrast, is much more radical and comprehensive. The entire system is managed through a single configuration file, and Nix takes full control of the system state, achieving a high degree of reproducibility.
Official NixOS documentation is often outdated, but there are several well-written third-party Chinese guides available online, such as [1] [2] [3]. These resources are already quite polished and detailed, so I won’t dive deeper into NixOS here.
I ultimately didn’t go with NixOS because I couldn’t find a mature, stable hypervisor solution for it. For now, I’m sticking with the Ansible + Proxmox combo. That said, I’ve still done some NixOS exploration—maybe I’ll gradually migrate parts of my setup to NixOS in the future.
After dealing with ancient dumpster fires like CentOS 7 or Ubuntu 16.04 for too long, NixOS feels like cyber utopia—pure bliss. It’s not that regular Linux distros or container solutions can’t solve problems—it’s that NixOS perfectly satisfies the unique brand of obsessive-compulsive tendencies common among tech nerds.
Random thought: here’s a piece generated by ChatGPT 4o mini (prompt: write a prose poem praising the virtues of NixOS):
Ode to NixOS
In the vast and chaotic digital cosmos,
NixOS shines as a solitary, brilliant star—
unyielding to convention, untouched by the tides of time.
It is the embodiment of order, a harmony of logic and elegance.Each line of configuration flows like a clear river,
bearing no impurities, no sediment.
Software packages exist as independent entities,
free from tangled dependencies and obsolete baggage.
They run in their own realms,
yet within this carefully woven web,
they collaborate in silence, never interfering.NixOS builds everything through declarative language,
whispering: every action, every deployment,
is a reflection of your intent—
no noise, no surprises.
It strips away the hidden pitfalls buried in layers of systems,
and with every rebuild,
it offers pure rebirth and clarity.Reproducible builds—
four simple words, carrying an eternal promise:
whether yesterday’s version or tomorrow’s form,
every return begins from the same source,
unchanged, fresh, and unregretful.NixOS is more than an operating system—
it’s a new way of thinking, a new philosophy.
Rationality flows in its code; art ascends in its builds.
In this ever-changing world,
it offers us a constant sanctuary—
like a lighthouse on the sea that never sinks,
guiding us into the unknown, yet never losing direction.
“Reproducible builds, four simple words(?)”… 🤣 Classic GPT.
Show me the code
I’ve bundled all my HomeLab / VPS playbooks, along with experimental Nix configurations, into my infra repository: https://github.com/lyc8503/infra
The benefits of IaC go beyond just easily deploying predefined systems—I can now track every change via git commits, reuse my own or others’ code, and occasionally pad my GitHub contribution graph while tinkering with servers.
Here are some services on my PVE host currently managed by Ansible (subject to change, of course):
- Smartd: monitors disk health and sends alert emails
- Zed: sends email notifications for ZFS pool events
- Netdata: monitors and stores system metrics (though Netdata v2.0 introduced several user-hostile changes, not recommended at all; actively looking to migrate away)
- Promtail: forwards local syslog to Grafana Cloud for long-term storage
- Zrepl: automates snapshots of VM disks (still WIP as of this post)
- hdidle: enables automatic HDD spin-down
Ansible also tweaks various PVE defaults to match my preferences—like properly configuring Postfix email settings, and adjusting vim and bash configurations.
I’ve also documented hardware-specific or Ansible-incompatible settings in the repo. This way, future me will thank present me when it’s time to redeploy. (x)
During my most recent migration, I got the entire PVE system—including all containers and VMs—up and running in just about an hour, most of which was just waiting for backups to extract and import.
This article is licensed under the CC BY-NC-SA 4.0 license.
Author: lyc8503, Article link: https://blog.lyc8503.net/en/post/18-ansible-in-aio/
If this article was helpful or interesting to you, consider buy me a coffee¬_¬
Feel free to comment in English below o/