URI: 
        _______               __                   _______
       |   |   |.---.-..----.|  |--..-----..----. |    |  |.-----..--.--.--..-----.
       |       ||  _  ||  __||    < |  -__||   _| |       ||  -__||  |  |  ||__ --|
       |___|___||___._||____||__|__||_____||__|   |__|____||_____||________||_____|
                                                             on Gopher (inofficial)
  HTML Visit Hacker News on the Web
       
       
       COMMENT PAGE FOR:
  HTML   Show HN: Enroll, a tool to reverse-engineer servers into Ansible config mgmt
       
       
        bityard wrote 2 hours 27 min ago:
        A 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
        have special "knowledge" about certain services like Apache which have
        their own Ansible modules?
        
        I 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...
       
        geerlingguy wrote 5 hours 31 min ago:
        Woah, 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.
       
        skywhopper wrote 5 hours 55 min ago:
        Really cool! I’m in a similar situation and I’m going to try this
        tool out right away to see if it can speed up Ansible onboarding for
        some particularly crusty old servers. Thanks for sharing!
       
        slhck wrote 6 hours 14 min ago:
        I'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?
       
        usrme wrote 8 hours 9 min ago:
        An 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 years.
       
        stevekemp wrote 10 hours 27 min ago:
        That'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.
       
          _mig5 wrote 10 hours 18 min ago:
          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
          cumbersome). Otherwise, you can always prune the roles from the
          ansible dir/playbook.
          
          I'm going to continue to work on easy options to skip stuff. In
          particular I do think many of the 'lib' packages could be omitted if
          they are just dependencies of other packages already detected as part
          of the harvest. (Need to basically build a dependency graph)
          
          Thanks for trying it out!
       
            gerdesj wrote 3 hours 25 min ago:
            I've just run it against my desktop PC.
            
            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.
       
            mlrtime wrote 8 hours 6 min ago:
            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!
       
        poemxo wrote 10 hours 46 min ago:
        Can it do Oracle? That would be a gamechanger.
       
        krelas wrote 11 hours 55 min ago:
        I’ve been looking for something exactly like this, thank you!
        Now I just need to find the same thing for Windows and macOS…
       
        indigodaddy wrote 12 hours 8 min ago:
        Does the playbook generation have support for some totally
        custom/one-off application? (Eg, not just system/well-known stuff). If
        so, that would be insane!
       
          _mig5 wrote 11 hours 45 min ago:
          It does! There are several sort of 'catch-alls' in place:
          
          1) stuff in /etc that doesn't belong to any obvious package, ends up
          in an 'etc_custom' role
          
          2) stuff in /usr/local ends up in a 'usr_local_custom' role
          
          3) Anything you include with --include will end up in a special
          'extra_paths' role.
          
          Here's a demo (which is good, helped me spot a small bug, the role is
          included twice in the playbook :) I'll get that fixed!) [1] Thanks
          for your interest!
          
  HTML    [1]: https://asciinema.org/a/765385
       
            indigodaddy wrote 11 hours 37 min ago:
            Nuts, I'm going to have to try this out.  Pretty sure nothing like
            this exists, at least not for Ansible (?).  This would certainly
            help converting chef cookbooks (we have a ton of custom
            applications along with system stuff of course) to Ansible (I guess
            it's not really converting in this scenario, just scanning the
            host(s), super neat!).    We are still using chef, and use Ansible
            for one-off jobs/playbooks/remediations etc, but would like to
            pivot to Ansible for config mgmt of everything for deployments at
            some point.  This definitely looks useful in that effort.
       
        westurner wrote 15 hours 28 min ago:
        Could it also detect changed package files; if there are
        per-package-file checksums like with `debsums` and `rpm -V`?
        
        Does it check extended filesystem labels with e.g. getfacl for SELinux
        support?
        
        I've also done this more than a few times and not written a tool.
        
        At least once I've scripted better then regex to convert a
        configuration file to a Jinja2 templated configuration file (from the
        current package's default commented config file with the latest
        options). And then the need is to diff: non-executable and executable
        guidelines, the package default config (on each platform), and our
        config.
        
        Sometimes it's better not to re-specify a default config param and
        value, but only if the defaults are sane on every platform. Cipher
        lists for example.
        
        P2V (physical to virtual) workflows don't result in auditable system
        policy like this.
        
        Most of the OS and Userspace packages backed up in full system images
        (as with typical P2V workflows) are exploitably out of date in weeks or
        months.
        
        To do immutable upgrades with rollback, 
        Rpm-ostree distros install the RPM packages atop the latest signed
        immutable rootfs image, and then layer /etc on top (and mounts in /var
        which hosts flatpaks and /var/home). It keeps a list of packages to
        reinstall and it does a smart merge of /etc. Unfortunately etckeeper
        (which auto-git-commits /etc before and after package upgrades) doesn't
        yet work with rpm-ostree distros.
        
        Ansible does not yet work with rpm-ostree distros. IIRC the primary
        challenge is that ansible wants to run each `dnf install` individually
        and that takes forever with rpm-ostree. It is or is not the same to
        install one long list of packages or to install multiple groups of
        packages in the same sequence. It should be equivalent if the package
        install and post-install scripts are idempotent, but is not equivalent
        if e.g. `useradd` is called multiply without an explicit UID in package
        scripts which run as root  too.
        
        I wrote a PR to get structured output (JSON) from `dnf history`, but it
        was for dnf4.
        
        From [1] :
        
        > upgrading the layered firefox RPM without a reboot requires
        -A/--apply-live (which runs twice) and upgrading the firefox flatpak
        doesn't require a reboot, but SELinux policies don't apply to flatpaks
        which run unconfined FWIU.
        
        Does it log a list of running processes and their contexts; with `ps
        -Z`?
        
        There are also VM-level diff'ing utilities for forensic-level
        differencing.
        
  HTML  [1]: https://news.ycombinator.com/item?id=43617363
       
          _mig5 wrote 15 hours 18 min ago:
          Hi westurner!
          
          > Could it also detect changed package files; if there are
          per-package-file checksums like with debsums and `rpm -V`?
          
          Yes, that's exactly what it does. See [1] and [2] It also tries to
          ignore packages that came with the distro automatically, e.g focusing
          on stuff that was explicitly installed (based on 'apt-mark
          showmanual' for Debian, and 'dnf -q repoquery --userinstalled' (and
          related commands, like dnf -q history userinstalled) for RH-like)
          
          > Does it check extended filesystem labels with e.g. getfacl for
          SELinux support?
          
          Not yet, but that's interesting, I'll look into it.
          
          > At least once I've scripted better then regex to convert a
          configuration file to a Jinja2 templated configuration file (from the
          current package's default commented config file with the latest
          options).
          
          Yep, that was the inspiration for my companion tool [3] (which enroll
          will automatically try and use if it finds it on the $PATH - if it
          can't find it, it will just use 'copy' mode for Ansible tasks, and
          the original files).
          
          Note that running the `enroll manifest` command against multiple
          separate 'harvests' (e.g harvested from separate machines) but
          storing it in the same common manifest location, will 'merge' the
          Ansible manifests. Thereby 'growing' the Ansible manifest as needed.
          But each host 'feature flips' on/off which files/templates should be
          deployed on it, based on what was 'harvested' from that host.
          
          > Does it log a list of running processes and their contexts; with
          `ps -Z`?
          
          It doesn't use ps, but it examines systemctl to get a list of running
          services and also timers. Have a look at [4] Thanks for the other
          ideas! I'll look into them.
          
  HTML    [1]: https://git.mig5.net/mig5/enroll/src/branch/main/enroll/plat...
  HTML    [2]: https://git.mig5.net/mig5/enroll/src/branch/main/enroll/rpm....
  HTML    [3]: https://git.mig5.net/mig5/jinjaturtle
  HTML    [4]: https://git.mig5.net/mig5/enroll/src/branch/main/enroll/syst...
       
            westurner wrote 6 hours 16 min ago:
            Thanks for your reply. As well; otoh:
            
            Does it already indirectly diff the output of `systemd-analyze
            security`?
            
            Would there be value to it knowing the precedence order of systemd
            config files? (`man systemd.unit`)
            
            How to transform the generated playbooks to - instead of ansible
            builtins - use a role from ansible-galaxy to create users for
            example?
            
            How to generate tests or stub tests (or a HEALTHCHECK
            command/script, or k8s Liveness/Readiness/Startup probes, and/or a
            Nagios or a Prometheus monitoring config,) given ansible inventory
            and/or just enroll?
            
            Ansible Molecule used to default to pytest-testinfra for the verify
            step but the docs now mention an ansible-native way that works with
            normal inventory that can presumably still run testinfra tests as a
            verify step. [1] MacOS: honebrew_tap_module, homebrew_module,
            homebrew_cask_module, osx_defaults_module
            
            Conda (Win/Mac/Lin, AMD64, ARM64, PPC64, RISC-V 64 (*), WASM)
            
            CycloneDX/cyclonedx-python generates SBOMs from venv, conda, pip
            requirements.txt, pipenv, poetry, pdm, uv: [2] Container config:
            /var, $DOCKER_HOST,  Podman, Docker, $KUBECONFIG defaults to
            ~/.kube/config    (kube config view), Podman rootless containers
            
            Re: vm live migration, memory forensics, and diff'ing whole
            servers:
            
            Live migration and replication solutions already have tested
            bit-level ~diffing that would also be useful to compare total
            machine state between 2 or more instances. At >2 nodes, what's
            anomalous? And how and why do the costs of convergence-based
            configuration management differ from golden image -based
            configuration management?
            
            E.g. vmdiff diffs VMs. The README says it only diffs RAM on
            Windows. E.g. AVML and linpmem and volatility3 work with Linux.
            
            /? volatility avml inurl:awesome
            
  HTML      [1]: https://docs.ansible.com/projects/molecule/configuration/?...
  HTML      [2]: https://github.com/CycloneDX/cyclonedx-python
  HTML      [3]: https://www.google.com/search?q=volatiloty+avml+inurl%3Aaw...
       
        xyst wrote 16 hours 15 min ago:
        poor man’s nixOS
       
          yjftsjthsd-h wrote 11 hours 50 min ago:
          If NixOS was this easy to onboard, we'd have an easier time of it.
          
          - Sent from my NixOS daily-driver, which only cost me a small number
          of grey hairs
       
        neilv wrote 16 hours 38 min ago:
        This is a great idea. I have done this manually, and it was a lot of
        work.
        
        Even with a tool, people will still have to understand the output,
        enough that they can spot situations like "this part doesn't make sense
        at all", "that bit isn't static", "holy crud, there's an unsecured
        secret", "this part suggests a dependency on this other server we
        didn't know was involved, and which the tool doesn't investigate".
       
          _mig5 wrote 16 hours 33 min ago:
          I agree! It's always a 'best effort' tool. There's going to be corner
          cases where something that might end up in the 'logrotate' role could
          arguably be better placed in a more specific app's role.
          
          It does an okay job at this sort of thing, but definitely human eyes
          are needed :)
       
        Quarrel wrote 16 hours 42 min ago:
        Very cool.
        
        I just saved the state of my WSL2 instance, pushed it to github.
        Amazingly simple.
        
        FWIW, I was required to add the --harvest, which your quick start seems
        to be missing?
        
        ie I used:
        
        uvx enroll single-shot --harvest ./harvest --out ./ansible
       
          _mig5 wrote 16 hours 35 min ago:
          Whoops, thanks, I'll adjust that example!
          
          Indeed when using single-shot, unless you're using the --remote modes
          (in which case, the harvest is pulled down to a machine-generated
          path locally), indeed you need to supply the path to the harvest so
          that the 'manifest' part under the hood, knows what to use.
          
          (By contrast, if you are using just the 'enroll harvest' command by
          itself, and omit the --out option, it will by default store the
          harvest in a random directory in ~/.cache/enroll/harvest/xxxxxxx)
          
          Thanks for trying it out!
       
        tecoholic wrote 16 hours 53 min ago:
        Very cool idea and kudos for building and making the idea into a
        reality.
       
        novoreorx wrote 17 hours 9 min ago:
        I wonder if Nix has similar tools, as it is famous for declarative
        system management, which is quite suitable for server provisioning.
       
          c0balt wrote 6 hours 24 min ago:
          The other comment already answers part of it, there is no real need
          for it for a NixOS system as you usually either can consult the store
          on the machine (and recursively build a graph of a all transitive
          dependencies of a generation), have a system that stores the config
          along with the generation (option `system.copySystemConfiguration` or
          a flake-based system will store the config in the store itself).
          
          A system that has neither a store nor the config (container image)
          not easily reconstructable as you miss too much metadata.
       
          ptman wrote 12 hours 3 min ago:
          It's hard with nix to end up with a system without first having a
          config for that system
       
        olekspin wrote 17 hours 15 min ago:
        Wonderful! I wish that tool was existed a few years ago, when I had no
        experience with Ansible. Anyway, will try it and compare outcome of
        Enroll with my current playbooks
       
        _mig5 wrote 17 hours 32 min ago:
        Here's a video of JinjaTurtle, the companion tool that converts configs
        to Jinja2 templates and Ansible vars: [1] Enroll will automatically
        make use of jinjaturtle if it's on the $PATH, to generate templates.
        
  HTML  [1]: https://asciinema.org/a/765293
       
        yowlingcat wrote 17 hours 53 min ago:
        Very cool! Managing ones boxes as cattle and not pets almost always
        seems like a better idea in retrospect but historically it is easier
        said than done. Moreover, I like the idea of being able to diff a box's
        actual state from a current Ansible system to verify that it actually
        is as configured for further parity between deployed/planned.
       
          _mig5 wrote 17 hours 40 min ago:
          Definitely! It's all too easy to make a direct change and later
          forget to 'fold it in' to Ansible and run a playbook. My hope is that
          `enroll diff` serves as a good reminder if nothing else.
          
          I'm pondering adding some sort of `--enforce` argument to make it
          re-apply a 'golden' harvest state if you really want to be strictly
          against drift. For now, it's notifications only though.
       
        barbazoo wrote 18 hours 21 min ago:
        This is a fantastic idea. I can imagine using this to pull in any
        manual changes I might have made to the server because I’m not the
        most disciplined person.
       
          _mig5 wrote 17 hours 42 min ago:
          Haha, same! I ran it on a server I've been shepherding along since
          2008 and wow, it was insightful, there were even cron jobs it found
          that I had forgotten about :)
          
          If you are using a Debian-like or Fedora-like workstation, it's also
          really useful to 'ansibilize' your desktop OS in case you need to
          reinstall :)
       
        bcye wrote 18 hours 50 min ago:
        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!
       
          stego-tech wrote 3 hours 46 min ago:
          My thoughts exactly. As someone who has generally learned better and
          faster through labs or real world work, this is exactly how I intend
          to teach myself Ansible while also migrating some stuff to
          containers: throw at my current VMs, identify configs, and then
          migrate or enroll accordingly.
       
        proxysna wrote 19 hours 3 min ago:
        Genuenly the thing i've been dreaming about for a while. Nice work.
       
        smoyer wrote 19 hours 19 min ago:
        I have quite a few machines that were constructed using Ansible ...
        When I get a chance, I'll reverse then and compare the results to the
        IaC that created them
       
        nightshift1 wrote 19 hours 21 min ago:
        This makes me think of the now defunct
        
  HTML  [1]: https://github.com/SUSE/machinery
       
          _mig5 wrote 17 hours 44 min ago:
          Indeed! I'm showing my age, but I do remember using this with Puppet
          and it was one of my inspirations :D (no commits in nearly 13 years,
          ouch)
          
  HTML    [1]: https://github.com/devstructure/blueprint
       
            heliostatic wrote 17 hours 22 min ago:
            Yes! I always thought that was a very clever project, and was sad
            when it ceased development. Very excited to try this out, and glad
            to have stayed on Debian all these years.
       
        Imustaskforhelp wrote 19 hours 45 min ago:
        Bravo, I will play with it. I haven't played with ansible till now but
        I know that its related to automation.
        
        If something can make ansible easier for me to try out like this tool
        while being pragmatic, I will give this a try someday thank you!
        
        How accurate does this tool end up becoming though? Like can I just run
        some bunch of commands to setup a server and then use this with
        ansible?
        
        Would this end up being a good use for it or would I just re-invent
        something similar to cloud-init on wrong abstraction. (On all fairness,
        one thing troubling me about cloud-init is that I would need to
        probably have a list of all commands that I want to run and all changes
        which sometimes if history command might have some issues or you do end
        up writing files etc. ends up being a little messy)
        
        I haven't played that much with both cloud-init and ansible either but
        I am super interested to know more about enroll and others as well as I
        found it really cool!
       
          _mig5 wrote 17 hours 46 min ago:
          Great questions! OP here, let me answer them below:
          
          > How accurate does this tool end up becoming though? Like can I just
          run some bunch of commands to setup a server and then use this with
          ansible?
          
          Yes, exactly: let's say you provision a VPS and then install some
          stuff on it, configure some configs, create a crontab, create a user
          account. Running 'enroll harvest' on it will detect all of that, and
          'enroll manifest' will then convert that 'harvest' into Ansible
          roles/playbooks.
          
          > Would this end up being a good use for it or would I just re-invent
          something similar to cloud-init on wrong abstraction. (On all
          fairness, one thing troubling me about cloud-init is that I would
          need to probably have a list of all commands that I want to run and
          all changes which sometimes if history command might have some issues
          or you do end up writing files etc. ends up being a little messy)
          
          Yeah, your instinct is right on the latter point. Ansible and
          Cloud-init are similar in that they are both 'declarative' systems to
          say what should exist on the machine. Ansible has some advantages in
          that it compares with the current setup to see if it needs to change
          anything. Cloud-init (in my experience) is a bit more crude: 'just
          run this stuff the first time the machine is booted'.
          
          I'm sure there are different ways of using it, but in my experience,
          cloud-init is really designed to 'run once' (first time setup). For
          example, if you provision a machine with Terraform or OpenTofu, and
          you pass in cloud-init, then later if you change the cloud-init data,
          it wants to destroy the machine and rebuild it (unless you configure
          it explicitly not to do that, by which you have to tell it to
          'ignore' changes to the cloud-init).
          
          Whereas with Ansible, you're at least equipped with a solid
          foundation that you can extend over time - you'll no doubt eventually
          need to make changes to your server post the initial setup.
          
          If you're new to Ansible, Enroll will be a quick way to get up and
          running with working Ansible configuration and you can adapt it from
          there as you learn it.
          
          Admittedly, to satisfy a lot of corner cases (or support different
          Linux distros), the Ansible code that Enroll generates is a bit
          complex to read compared to a 'bespoke' home-grown playbook, on the
          other hand, it's perfectly correct code and you'd be immediately
          exposed to good practice syntax.
          
          Let me know if you get to try it!
       
       
   DIR <- back to front page