[{"data":1,"prerenderedAt":387},["ShallowReactive",2],{"project-46449852":3},{"id":4,"name":5,"line":6,"line_source":7,"title":8,"url":9,"domain":10,"maker":11,"posted_at":12,"year":13,"points":14,"comments":15,"rank_in_year":16,"shown_in_year":17,"top":18,"tier":19,"category":20,"subcategory":21,"format":22,"keywords":23,"reception":28,"sentiment":29,"stance_mix":30,"scored_comments":35,"aspects":36,"strip":42,"post_text":44,"what":45,"said":87,"maker_in_thread":192,"shape":205,"grid":209,"attempts":349,"same_week":350,"maker_shows":34,"maker_hidden":379,"reader_version":380,"card":381},"46449852","Enroll","A tool to reverse-engineer servers into Ansible config mgmt","title","Show HN: Enroll, a tool to reverse-engineer servers into Ansible config mgmt","https:\u002F\u002Fenroll.sh","enroll.sh","_mig5",1767227034,2026,265,56,176,4366,5,"legend","dev_tools","configuration management","cli",[24,21,25,26,27],"ansible","drift detection","server provisioning","sbom","loved",0.422,{"positive":31,"neutral":32,"mixed":33,"critical":34},16,14,2,1,33,{"idea":37,"docs":40,"execution":41},{"positive":38,"critical":39},11,0,{"positive":39,"critical":39},{"positive":39,"critical":34},[18,39,18,39,43,43,39,43,18,43,39,39,43,43,43,39,18,18,39,43,18,39,18,18,18,39,34,18,18,43,43,18,18,39,43,43,39,18,39,43],3,"Happy new year folks!\n\nThis tool was born out of a situation where I had 'inherited' a bunch of servers that were not under any form of config management. Oh, the horror...\n\nEnroll 'harvests' system information such as what packages are installed, what services are running, what files have 'differed' from their out-of-the-box defaults, and what other custom snowflake data might exist.\n\nThe harvest state data can be kept as its own sort of SBOM, but also can be converted in a mere second or two into fully-functional Ansible roles\u002Fplaybooks\u002Finventory.\n\nIt can be run remotely over SSH or locally ",{"problem":46,"audience":52,"pricing":61,"motivation":62,"time_to_build":61,"stack":66,"openness":84,"stage":85,"team_size":86},{"value":47,"source":48,"evidence":49},"Servers built by hand are not under config management and drift from their intended state.","maker",[50],{"id":51},"post",{"value":53,"source":54,"evidence":55},"Sysadmins and engineers who inherit or manage servers not under config management.","inferred",[56,57],{"id":51},{"id":58,"by":59,"text":60},"46460412","barbazoo","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.",null,{"value":63,"source":48,"evidence":64},"Inherited servers with no config management; wanted a catch-all DR tool.",[65],{"id":51},[67,76,80],{"value":68,"source":54,"evidence":69},"Python",[70,73],{"id":71,"by":11,"text":72},"46461488","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…",{"id":74,"by":11,"text":75},"46471304","Thanks for the comment and questions! Very wise. 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…",{"value":77,"source":48,"evidence":78},"Ansible",[79],{"id":51},{"value":81,"source":48,"evidence":82},"systemd",[83],{"id":74,"by":11,"text":75},"open_source","launched","unknown",{"praise":88,"objections":108,"requests":123,"questions":142,"alternatives":161},[89,101],{"value":90,"source":91,"evidence":92},"Useful for learning Ansible and seeing server state as code.","commenter",[93,97],{"id":94,"by":95,"text":96},"46460223","bcye","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!",{"id":98,"by":99,"text":100},"46465056","geerlingguy","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.",{"value":102,"source":91,"evidence":103},"Captures forgotten manual changes on long-lived servers.",[104,105],{"id":58,"by":59,"text":60},{"id":106,"by":11,"text":107},"46460645","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…",[109,113],{"value":110,"source":48,"evidence":111},"Generated Ansible code is harder to read than hand-written roles.",[112],{"id":74,"by":11,"text":75},{"value":114,"source":91,"evidence":115},"Can produce overwhelming output with many roles.",[116,120],{"id":117,"by":118,"text":119},"46463086","stevekemp","That's a really cute looking tool. I ran it without installing via: ``` uv tool run enroll single-shot --harvest .\u002Fharvest --out .\u002Fansible ``` It generated almost a thousand…",{"id":121,"by":11,"text":122},"46463132","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…",[124,134],{"value":125,"source":91,"evidence":126},"Support for sudo password prompts over SSH.",[127,131],{"id":128,"by":129,"text":130},"46464684","slhck","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…",{"id":132,"by":11,"text":133},"46471010","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…",{"value":135,"source":91,"evidence":136},"Detect SELinux labels and file ACLs.",[137,141],{"id":138,"by":139,"text":140},"46461437","westurner","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…",{"id":71,"by":11,"text":72},[143,151],{"value":144,"source":91,"evidence":145},"How does it determine what counts as state beyond packages and services?",[146,150],{"id":147,"by":148,"text":149},"46467165","bityard","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…",{"id":74,"by":11,"text":75},{"value":152,"source":91,"evidence":153},"Does it handle one-off custom applications?",[154,158],{"id":155,"by":156,"text":157},"46462456","indigodaddy","Does the playbook generation have support for some totally custom\u002Fone-off application? (Eg, not just system\u002Fwell-known stuff). If so, that would be insane!",{"id":159,"by":11,"text":160},"46462586","It does! There are several sort of 'catch-alls' in place: 1) stuff in \u002Fetc that doesn't belong to any obvious package, ends up in an 'etc_custom' role 2) stuff in \u002Fusr\u002Flocal ends…",[162,169,175,186],{"value":163,"source":91,"evidence":164},"Machinery (SUSE)",[165],{"id":166,"by":167,"text":168},"46459971","nightshift1","This makes me think of the now defunct https:\u002F\u002Fgithub.com\u002FSUSE\u002Fmachinery",{"value":170,"source":48,"evidence":171},"blueprint (DevStructure)",[172],{"id":173,"by":11,"text":174},"46460634","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)…",{"value":176,"source":91,"evidence":177},"Nix \u002F NixOS",[178,182],{"id":179,"by":180,"text":181},"46460859","novoreorx","I wonder if Nix has similar tools, as it is famous for declarative system management, which is quite suitable for server provisioning.",{"id":183,"by":184,"text":185},"46461180","xyst","poor man’s nixOS",{"value":187,"source":91,"evidence":188},"cloud-init",[189],{"id":190,"by":11,"text":191},"46460620","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…",{"comments":193,"answered":194,"key":195},20,8,[196,199,202],{"id":197,"text":198},"46470746","Thank you, Jeff! What an honour! Let me say that nothing compares to your catalogue of Ansible roles that I have benefited from for many years, which are far better written than…",{"id":200,"text":201},"46460713","Here's a video of JinjaTurtle, the companion tool that converts configs to Jinja2 templates and Ansible vars: https:\u002F\u002Fasciinema.org\u002Fa\u002F765293 Enroll will automatically make use of…",{"id":203,"text":204},"46561301","Hi everyone! I'm pleased to report I'm releasing Enroll 0.4.0 today. It has some cool new features: --ignore-package-versions for 'enroll diff' ,so you don't get alerted to just…",{"commenters":35,"max_depth":206,"maker_replies":193,"first_comment_mins":207,"lifespan_hours":208},4,1431,216,[210,212,214,215,218,220,224,225,229,232,234,235,238,240,244,247,249,254,255,257,258,261,263,267,270,275,277,281,283,284,285,289,291,294,298,300,301,304,306,310,313,315,316,318,322,326,328,329,331,335,337,338,340,342,344,346],[98,39,18,211,99,39],"project\u002Fpositive\u002Fidea",[197,39,39,213,11,34],"commenter\u002Fneutral\u002Fnone",[94,34,18,211,95,39],[216,34,18,211,217,39],"46466234","stego-tech",[200,33,39,219,11,34],"project\u002Fneutral\u002Fnone",[221,43,43,222,223,39],"46459992","project\u002Fneutral\u002Fidea","smoyer",[203,206,39,219,11,34],[226,18,43,227,228,39],"46461036","project\u002Fmixed\u002Fdocs","Quarrel",[230,18,39,231,11,34],"46461069","project\u002Fneutral\u002Fdocs",[166,233,43,222,167,39],6,[173,233,39,222,11,34],[236,233,18,211,237,39],"46460785","heliostatic",[179,239,43,222,180,39],7,[241,239,39,242,243,39],"46462486","other\u002Fneutral\u002Fnone","ptman",[245,239,39,242,246,39],"46464589","c0balt",[248,194,39,219,11,34],"46486759",[250,251,43,252,253,39],"46459762",9,"project\u002Fneutral\u002Fexecution","Imustaskforhelp",[190,251,39,222,11,34],[117,256,43,252,118,39],10,[121,256,39,252,11,34],[259,256,43,222,260,39],"46463891","mlrtime",[262,256,39,222,11,34],"46470776",[264,256,18,265,266,39],"46466468","project\u002Fpositive\u002Fnone","gerdesj",[268,38,18,211,269,39],"46460125","proxysna",[271,272,43,273,274,39],"46461053",12,"project\u002Fmixed\u002Fexecution","neilv",[276,272,39,252,11,34],"46461076",[278,279,43,252,280,39],"46463877",13,"usrme",[282,279,39,252,11,34],"46470812",[58,32,18,211,59,39],[106,32,39,265,11,34],[286,287,18,211,288,39],"46460581",15,"yowlingcat",[290,287,39,222,11,34],"46460663",[292,31,18,265,293,39],"46462530","krelas",[295,296,18,265,297,39],"46464831",17,"skywhopper",[128,299,43,252,129,39],18,[132,299,39,252,11,34],[302,299,34,303,129,39],"46473287","project\u002Fcritical\u002Fexecution",[305,299,39,252,11,34],"46473422",[307,308,18,265,309,39],"46460819",19,"olekspin",[311,193,18,211,312,39],"46470190","kriskaminski",[138,314,43,219,139,39],21,[71,314,39,252,11,34],[317,314,43,219,139,39],"46464662",[319,320,18,265,321,39],"46496948",22,"dweller42",[323,324,18,211,325,39],"46460959",23,"tecoholic",[147,327,43,252,148,39],24,[74,327,39,252,11,34],[330,327,39,231,11,34],"46492878",[332,333,43,219,334,39],"46462943",25,"poemxo",[155,336,43,222,156,39],26,[159,336,39,219,11,34],[339,336,18,211,156,39],"46462627",[341,336,18,211,156,39],"46490972",[343,336,39,265,11,34],"46492863",[183,345,43,222,184,39],27,[347,345,39,242,348,39],"46462554","yjftsjthsd-h",[],[351,356,360,364,369,374],{"id":352,"name":353,"points":354,"category":355},"46454693","OpenWorkers",500,"infrastructure",{"id":357,"name":358,"points":359,"category":20},"46491749","taws",390,{"id":361,"name":362,"points":363,"category":20},"46511469","Prism.Tools",380,{"id":365,"name":366,"points":367,"category":368},"46499646","DoNotNotify",347,"productivity",{"id":370,"name":371,"points":372,"category":373},"46488654","how browsers work",302,"learning_science",{"id":375,"name":376,"points":377,"category":378},"46501137","Tailsnitch",280,"security_privacy",false,"v2",{"id":382,"name":5,"line":6,"ai":379,"cat":20,"year":13,"points":14,"comments":15,"rec":28,"s":383,"top":18,"kw":384,"maker":11,"domain":10,"tier":19,"attempts":39,"strip":385,"url":9,"mix":386,"praise":90,"objection":110,"sub":21},46449852,0.42,[24,21,25,26,27],"5050330353003330550350555015533550330503",[31,32,33,34],1793991137932]