This looks like a great way to learn Ansible too. Instead of learning alongside random examples, you can setup your server and see how it would look like in Ansible. Awesome stuff!
Show HN: Enroll, a tool to reverse-engineer servers into Ansible config mgmt
41–50 of 57 posts
Re: Show HN: Enroll, a tool to reverse-engineer servers into Ansible config mgmt
#42That's a really cute looking tool. I ran it without installing via: uv tool run enroll single-shot --harvest ./harvest --out ./ansible It generated almost a thousand roles, and at quick glance it identified many changes which I expected and some that I didn't.
Yup - it can be pretty overwhelming, it depends on what it detected on your system! The state.json will usually explain why it 'harvested' something (perhaps it was because it found a running systemd service, perhaps it was due to detecting a package having been manually installed, etc) There is the --exclude option which might help (also keep in mind you can define an enroll.ini file to manage the flags so it's less…
I had documented everything up to a point on this beatie and then things have got out of hand. I now have all the changes from after I went off piste.
What a great tool.
Thank you.
Re: Show HN: Enroll, a tool to reverse-engineer servers into Ansible config mgmt
#43I don't know if this touches networking or not but I've always deliberately avoided configuring (most) networking on Ansible after having shot myself in the foot too many times.
I like this in theory and will give it a shot but I'm wary of getting bled out by all the sharp corner cases...
Re: Show HN: Enroll, a tool to reverse-engineer servers into Ansible config mgmt
#44JinjaTurtle is just chef's kiss. Definitely taking both for a spin.
Re: Show HN: Enroll, a tool to reverse-engineer servers into Ansible config mgmt
#45Woah, very neat! I may have to add this to the examples in Ansible for DevOps. Great idea, looks like for many cases it will help move hand config into automation.
Appreciate it!
Re: Show HN: Enroll, a tool to reverse-engineer servers into Ansible config mgmt
#46Earlier quoted context omitted.
Yup - it can be pretty overwhelming, it depends on what it detected on your system! The state.json will usually explain why it 'harvested' something (perhaps it was because it found a running systemd service, perhaps it was due to detecting a package having been manually installed, etc) There is the --exclude option which might help (also keep in mind you can define an enroll.ini file to manage the flags so it's less…
Can you create a baseline system to create the ignores? What I mean is in some large companies you are given a host that already has lots of config changes, possibly by ansible. Then your team has to configure on top of those changes, maybe ansible again. I'd like to run on the baseline system given to create a baseline, then on a production host to see how it drifted. Sorry if this is in the docs, cool tool!
Treat that as your 'golden' harvest state. You could then run a 'harvest' on the production system. You'd then be able to run 'enroll diff --old baseline --new production' to compare the difference.
You could also first run the manifest of the baseline harvest against your production, to ensure it has (at least) all the same things as the baseline.
A 'harvest' of production after that, would probably then show just stuff that existed on production already that wasn't in the baseline.
I hope that makes sense!
Re: Show HN: Enroll, a tool to reverse-engineer servers into Ansible config mgmt
#47An incredible undertaking! How much testing have you done with regards to harvesting a manual configuration into Ansible, creating a new machine and then applying that to see whether the machine is a functional representation of the old machine? The reason I'm asking is because I'm interested in how much confidence could be lent to this tool with regards to more old and obscure machines that have been running for yea…
I run QubesOS as my workstation, so it's been really beneficial here, because Qubes is all VMs and templates. I've been 'harvesting' one Qube VM and then building another and running the manifest on the second machine. It's been working very well to align it with the first machine. Most of my testing has been visually watching the Ansible play install/configure things that I expect to see occur.
Where it falls down:
1) Systems that are so old, the packages that it detected as being installed, are no longer 'installable' on a new system (e.g the apt repositories no longer have those packages, they just did at the time of the original install)
2) Packages that were installed not via an apt repo but, say, dpkg -i (of a .deb file). Slack Desktop is a good example. Obviously the deb is not in the harvest, so it fails there.
So, there'll always be corner cases, but assuming everything that you have installed on the old/obscure machine is still something that can be installed via the usual methods, it should be okay. (If you are running a system that is so old, its packages are no longer available upstream, it's probably time to let it go! :) )
You'll want to use --exclude-path to ignore some server-specific stuff, perhaps, such as static network configuration etc. And of course, you can also comment out whatever roles are superfluous, in the playbook, before running it.
Always use --check with Ansible first just in case.
Re: Show HN: Enroll, a tool to reverse-engineer servers into Ansible config mgmt
#48I've been looking for something like this, awesome! Is it expected that it does not allocate a TTY for sudo password prompts when connecting to a remote machine via SSH? How would I use it otherwise?
I'm about to make a new release and I'll set `get_pty=True` for the paramiko calls that use sudo. I'm not 100% sure if it will fix it for all use cases, but hopefully it will.
Re: Show HN: Enroll, a tool to reverse-engineer servers into Ansible config mgmt
#49A question I didn't see answered on the Web site or in the comments... How does it determine what is "state"? Packages are easy, you just get a list of those with the package manager. I guess systemd lists services. But what about everything else? Is it just walking the whole file system and checking every file it finds to see if a package owns it? What about files and symlinks created by postinst scripts? Does it ha…
Let me break it down as to what harvest does:
1) Detects the OS and its package backend (e.g dpkg vs rpm etc)
2) Detects what packages are installed
3) For each package, it tries to detect files in /etc/ that have been modified from the default that get shipped with the package . It does't walk the whole filesystem, it looks straight in /etc for stuff here.
4) It detects running/enabled services and timers via systemd. For each of these, it looks for the unit files, any 'drop-in' files, environment variable files, etc, as well as what executable it executes, and tries to map those systemd services to the packages it's already learned about earlier (that way, those 'packages' or future Ansible roles, can also be associated with 'handlers' in Ansible, to handle restart of the services if/when the configs change)
5) Aside from known packages already learned, it optimistically tries to capture extra system configuration in /etc that is common for config management. This is stuff like crons, logrotate configs, networking settings (as you noted!), hosts files, etc.
6) It also looks for other snowflake stuff in /etc not associated with packages/services or other typical system config, and will put these into an etc_custom role
7) Likewise, it looks in /usr/local for stuff, on the assumption that this is an area that custom apps/configs might've been placed in. These go into a usr_local_custom role.
8) It captures non-system user accounts, their group memberships and their .ssh/authorized_keys
9) takes into account anything the user set with --exclude-path or --include-path . For anything extra that is included, it will put these into an 'extra_paths' role. The location could be anywhere e.g something in /opt, /srv/ whatever you want.
10) writes the state.json and captures the artifacts
So yes, you're right - it does capture stuff that many people might want to exclude if they are going to use the manifests to build other machines from that harvest (as opposed to just rebuild the same machine itself).
But you can use --exclude-path /etc/network and so on to skip the bits you don't want. You also can always comment out from the playbook.yml or delete certain roles it generates once you've run the 'enroll manifest'.
It doesn't have any knowledge of Ansible Galaxy roles/modules etc. It generates all the roles itself. I admit, many of the existing roles out there are a lot more pleasant/easier to read (especially Jeff Geerling's). I still use those myself day to day. A lot of configs out there are also good candidates for being Jinja templates with abstracted vars for separate hosts. Enroll does use my companion tool JinjaTurtle if it's installed, but JinjaTurtle only recognises certain types of files (.ini style, .json, .xml, .yaml, .toml, but not special ones like Nginx or Apache conf files which have their own special syntax).
I consider Enroll to be a good 'quick, grab it all, so I can sleep at night' method, perhaps best for DR purposes.
In terms of safety measures: it doesn't traverse symlinks, and it has an 'IgnorePolicy' that makes it ignore most binary files (except GPG binary keys used with apt) - though if you specify certain paths with --include-path and use --dangerous, it will skip its own policy. See https://git.mig5.net/mig5/enroll/src/branch/main/enroll/igno... .
It will skip files that are too large, and it also currently has a hardcoded cap of the number of files that it will harvest (4000 for /etc/ and /usr/local/etc and /usr/local/bin, and 500 per 'role'), to avoid 'bomb' situations.
I think your caution is very warranted and wise, and I highly recommend to always use --check with Ansible when/if you get to applying the playbook!
Thanks again.
Re: Show HN: Enroll, a tool to reverse-engineer servers into Ansible config mgmt
#50I've been looking for something like this, awesome! Is it expected that it does not allocate a TTY for sudo password prompts when connecting to a remote machine via SSH? How would I use it otherwise?
Ah, this is not a problem for me on my remote hosts. I'm guessing this comes down to a sudoers policy on certain distros (redhat-like ones perhaps). I'm about to make a new release and I'll set `get_pty=True` for the paramiko calls that use sudo. I'm not 100% sure if it will fix it for all use cases, but hopefully it will.