 Okay, I'm going to start with actually a very simple introduction to Ansible So I'm just going to assume that While people here might have experience with either sysadmin stuff or devops that they've pretty much never done You know dealt with Ansible itself before so we'll be covering the extreme basics not including installation because installation is It install Ansible. You're done Alternatively app get install Ansible Yum install Ansible or Pac-Man install Ansible, whatever. You know your own distros. That's how you install it Ansible currently does not support Windows as a controller. So Don't try and run it on Windows like 99.9% of things written in Python So Ansible itself Quite simple. It's basically Two things in one if you ever use chef and puppet for provisioning It does that if you use fabric for deployment. It does that too The difference between this and say fabric is fabric is very tell me what to do and I will do it So you tell it to copy a file it copies a file you tell it to create a file it creates a file with Ansible It's more decorative. You say I want a file to exist here. It makes sure that the file is there Similarly, you won't say install this package. You will say ensure that this package is installed Right and so that's a slight difference in thinking. It's quite similar to salt as well salt does the same thing So let's start with a few demos. Let's make sure that the machines that we're hitting are alive So Ansible the command simple Now the all comes from this. I have a host file here with For instances running on my laptop because I was bored This host file basically declares every single server that you have Be it a production server testing service staging server does not matter. You define everything here And then you put in the same groups in this case. I didn't have I don't have a distinction between say staging and production I just have a web server that is I NS zero a VPN server. That's the NS one of your IP server. That's a NS to and all four of these are under another group called arch Essentially servers themselves will be the first four and I put them into groups called well Whatever their name is mostly because I can't be arched to keep typing dot local everywhere Usually you will use this when you have multiple servers that always have the same config Let's say you have something shouted across two machines and will always be shouted They're rather replicated on the same two machines. You can always put them in the same group There is nothing stopping me from say doing an an S4 dot local down here both will now count as an S3 Children in the header just means that this group has Groups in it and not actually hosts One limitation is you cannot mix hosts and groups last I checked though. They have been to major point updates since then So I'm not sure but the last time I tried if I did this It didn't work. So we won't try it because and The other advantage of groups is you can have the same machine or the same Subgroups belong to other groups, which lets you do quite fun stuff. So you might wonder why I have a group here called arch Well, that's quite simple Because I now have a group variable a set of group variables Basically variables that any host in this group will inherit when I run anything with Ansible and I set the Python interpreter to Python 2 I have to do this on arch because arch is Python 3 by default and They don't like old things But the rest of the world does because we like stability and we are too lazy to update our packages apparently so These poor guys at the Ansible works had to support all the way back to Python 2.6. Thanks to our dear friends using CentOS And so that gives you group variables Other than group variables, you also have host variables So you could create a folder here and call it host underscore vars. You could do a lot of other fun stuff and it's just so basically, there's a Very interesting structure to this which might be easier if I just used Sublime text to show you guys So generally just pay attention to the left side. You'll notice our group variables playbooks Rolls and a bunch of YAML files, right? Yes You're not supposed to look at that text. It's okay. I'm only pointing out the left side, which I can't enlarge the size of Yeah, so you have those guys now active it so I can actually you guys can actually read, right? Let's work our way from the bottom up Very simple thing you can do with Ansible is like I did ran a ping command Which pings all the machines. It's not actually an ICMP echo ping What this does is it SSH is a file SCPs a file rather over and make sure that the correct file is there So there's check summing all kinds of fun stuff happening Basically, it's a simple sanity check to make sure that your actual stuff runs on your target machines So, you know, it makes sure that you have SSH installed you have Python 2 installed and You have the interpreter set correctly, which you don't have to do in most distros If you don't have any of these your ping will fail if you're hosted down your ping will also fail and So let's look at this command, right? It's go down to the basics All all is a sort of reserve keyword Wherein it basically is a master group containing every single host you defined in the host file Normally you would have to do something like dash I hosts To pass it like oh, this is my inventory file every single time Alternatively, if you're lazy and or sane you could just do export Ansible hosts equals Whatever of your host file is Let's not confuse people If you're using bash or dash or C shell or any other shell it would be that In my case, I'm not running any of those shells. So it's a bit different now back to this command again So dash M ping dash M in Ansible generally means module So here we're at using the ping module, which doesn't really have any options. So you could run it And it would ping all your machines. I have a dash F4 at the end I can't remember what F actually stands for there is, you know a long version of it But basically it's parallelism By setting it to four it runs on four machines at a time Doesn't make much difference when I'm pinging them makes a very big difference when I'm doing say a Pac-Man install or something Now obviously there are other modules this happy module called shell where you could tell it to Echo yay, and obviously it doesn't work because I'm supposed to Essentially when you run Ansible itself the command it will gather the STD out an STD error Whatever process you run, and it will print it out to you. Let me just confirm that it actually does print STD Yes, so it gives you both standard out and standard error And if something errors out it would be read because it failed So he wants us a happy field in a rather sad field in a happy Past you might not be able to see the field because red on black generally comes out terribly on Projectors that are small So let's try not to make fail too many things along the way Shell is basically a shell. There is actually a default module, which is called command Which is invoked if you don't pass a module It's kind of a lot like shell except now you need to do a user bin echo because there is no path This would work This would sometimes work and sometimes not depending on your default path Because it doesn't actually You know launch a shell Other fun modules include stuff like Pac-man, which I didn't give it anything to do Let's say I want to say name equals T-Mux State equals There you go There's the other beautiful thing about Ansible is that most commands that you run barring shell commands and stuff that You're telling it exactly what to do rather than what the outcome is Are I important? I could run this command a hundred times. It would make no difference They will just keep returning the same thing because well T-Mux is already installed. Why should I install it again? Same way you can add you can say I Can't remember whether it's uninstalled or is it absent or not present might be absent So there is one rather annoying thing I've found about Ansible it's that because the modules are written by different people in the community The syntax is not exactly the most consistent thing for a stuff like One example is that when you're using yum, it's not state equals installed. It's state equals present or something like that whereas when you're using Pac-man it's state equals installed and If you're trying to write this drag not stick stuff This can be very very infuriating because you will end up doing stuff like oh god. Why is this not working? Because you try you manage to write the code to automatically select the module based on the distro But you forgot that the second part is different too. So there's a lot of stuff that's distro specific, which is why I created group bars arch Everything arch will be here. So let's say I wanted to have something like Packager equals pack it's called Packager Pac-man and Installed state and start then later on I would be able to do fun stuff like So your stuff is written in the ginger to templating syntax, which I'll show you in a bit It's if you've done anything with Flask you will know it very well if you've done anything with Django It should be immediately familiar because it's quite similar in syntax with a few quirks here and there and That is it for that. So most of the config is done in YAML files dear little YAML files So you have in this case. I have common site via IP VPN and triple W Most of them would tell you exactly what they do site dot YAML is actually Part of Ansible best practices your mean file is supposed to be called site for some obscure reason So what this does is I just include the other four in so if I ran right now say Ansible Playbook Site dot YAML this would run every single thing. I'm not going to run this right now because it's extremely slow And there's a lot of things so this would basically be a short time to run everything Now if most of your stuff is done and you just want to set up say VPN you just to VPN dot YAML If most of the stuff is done and you need triple W. Well, you do that Common in my case is just a bunch of you know common config because there are certain things that you can't configure within a playbook Like the user it runs as for example, you can't have say I have a playbook I want one role to run as root one role to run as my user. Well, you can't do that so in this case everything is run as my user with pseudo and Ansible obviously being an automation tool does not like being asked for passwords. So make sure step one that you have SSH keys enabled Make sure number two that if you are running it as a user other than root that your pseudo does not require a Password because you will basically be wasting a lot of time and making our Ansible playbooks really really ugly if this means that you need to have like a 521 bit easy DSA key for your usage Just to make it secure. Go ahead. It's worth it and Well in common These are the two things that I want all my machines to have I want all of them to have the development role Which I'll go into in a bit and the SSH role Obviously you want to be able to SSH into a machine and therefore you want to be you want the SSH We configured the way you want it to be and The second thing I run is here. You'll notice I run this as my user without pseudo and The reason this is kind of important is because it will this is this environment role that you see at the bottom It sets up stuff like my dot files my VMRC And I don't want these files owned by root because it'll be really really annoying to set them up later So I run these as my user this is actually I Removed it from my playbook long long time ago. I put it back in so I could show you guys You can declare variables in here randomly so I could say have a bars and This is a standard YAML hash Something like that These will also you'll be able to access test as a variable anywhere in your playbook Variables have a global namespace. So do watch out for naming conflicts. Don't do lame-slash-fun-slash-stupid-things where In your roles themselves you use SSH as a variable and then here use SSH as a variable They will clobber and it will just it will start using random values in random places And you will hate yourself for ever having done that Vars prompt on the other hand what it does is when you run this playbook it will prompt you for a value if You set private to yes It will not echo it back to the terminal if you don't set anything or set it to no It will echo it back as per normal. I'm going to remove this because it's no longer used in my scripts Right, so that's common. There is also site.yaml which includes everything which I went through VoIP has one primary role that is murmur There is a vast prompt here again, which is actually still in use and it prompts me for a passphrase for my mumble server Mumble is a you know group VoIP thing that people use when they realize how bad Skype is Similarly, there's VPN which just sets up the VPN servers and there's RippleW which sets up multiple roles So it sets up Nginx. It sets up it transfers my SSL certs. It then sets up the Nginx sites themselves I keep these separate for a reason the idea is your Nginx is common config across all machines you ever admin mostly and The sites will configure the various you know site specific things which you might want to add remove whatever I also set up you whiskey in emperor mode and later on there are also playbooks around at least my repo for Deploying a particular app Okay, let's go down into playbooks because playbooks is quite simple This is not a role. This is a very very simple one file playbook and all it does Is actually generate you secure SSH keys Simple example, you give it a name You run out every single host by default. You can always limit this when you are running it I Wanted run as my user with pseudo as usual Tasks to do there are two main tasks here one is to delete the old SSH keys because most BPS services will either Generate it when the machine first boots up and has extremely low entropy, which is not exactly a good idea Or they might be like digital ocean on have an issue where the Debian thing just has the same SSH key for everyone Which is not fun So you just generate new SSH keys Both of these are shell commands because it's a very simple script Technically, I could use a file glob and say I want all these files to be state equals absent But an RM is just one line is quicker And you don't really care that it's that important because the files are going to be there when you're done with running this The next thing is to generate the SSH keys themselves again. You just use it from the shell now This thing is really interesting. So you see notify here What notify does is if you give it a string in this case restart SSH Which makes perfect sense if you do know exactly what it does by looking at it. It's not actually magic It looks underhandlers for something called restart SSH Because it's an exact string match. It runs this thing which then calls service A service is a really really smart module that they have an answer will unlike like 80% of the other modules It knows whether you're running something with in it D Where they are running something with upstart and therefore you can use service or whether you're running system D And so you can use system CTL Unfortunately, the system the implementation broke a while ago. I don't think anyone's fixed it So I've just gone back to using shell for it in this case Yeah, system D doesn't work anymore Yeah, you have to like shell system CTL restart SSHD But if things worked properly the way they should which definitely will happen once RGL 7 is out because that is You know actually moving things forward for once And so I'm looking for the service named SSHD state restarted So I want it restarted and I want it enabled on And you might wondering why it says restarted and not restart the reason for that is if you have ten separate guys Who all notify restart SSH? It will wait until all ten are done and then just restart SSH once It won't do stupid things like I have ten playbooks that want to restart SSH And then I run all ten tasks and it's restarts every time. No, it doesn't do that It will restart SSH after whatever you tell it to And there's also another task in here which is to fetch the new SSH host keys because how else do you know that you're SSHing into the correct machine you might be leaking information. So in this case, it's quite simple Don't really need pseudo. I fetch a file So fetch is another ansible module which pulls data from the server to you There's an obviously a module that pushes files over and you give it the desk You give it a source which is ETC SSH SSH host Item key. The reason there's item there is because I want both the RSA and the ECDS a key if you're not using Fedora or Arch you will probably only have the RSA key So it's fine, but the rest of us have things have to do things like this and destination I wanted in TMP new host keys slash ansible underscore host name This is one of those magic variables that appears out of nowhere anything prefixed with ansible underscore typically is like sort of They give it to you. So try not to name your variables ansible underscore something because you will probably conflict and Then we clean up which is to you know new stuff and Then we find the fingerprints stick it into a file so that I have something happily in my home directory Which has the fingerprints of every single server at which point I can then SSH Check if the key matches if it matches say yes and carry on with my day If it doesn't match say no and then find out who's trying to pull a man in the middle attack That was a very simple thing Now we go into roles Roles are basically meant for meant to be completely reusable. The idea is you could have You know roles that you have in say one repo in another repo in a third repo you can just stick it all together in one place and Then your various actual playbooks like the site that YAML the video IP. YAML would then Define these roles and this is exactly how you would set up Dependency I remember there's a question on the the Facebook group about dependencies and the thing is there is no strict Dependency orders or anything of that sort and ansible the concept simply does not exist The idea is you if you really need to do step a before step B You would then do something like what I did in This file where you make sure engine X is installed Here before installing the sites for engine X because otherwise, you know, you might be in for a bad day So your whole dependency thing is just purely in your order Obviously, if you have circular dependency somewhere in your system You can always set it up so that it install stuff does not start it It installs all the other stuff and then you have a notify somewhere in the way because I know all Notifies are patched and run at the end of the whole process Now we have seed a bunch of rules simple one would be development and This would be where we do this So there are a bunch of standard folders in ansible and this is by convention if you want to change it You'll probably have to patch ansible itself what it the two most common ones that you'll pretty much always need are tasks and variables tasks and Yes, you do have to name it main dot YAML. It's not that I'm bad at naming This just has a list of tasks you put your task in here and then you put your variable in bars main dot YAML and Yeah, so this is the list of packages that I have Let's say I want to install base devil Python to Python H top T mocks and tree because I can't live without these things So I just have a variable file with these variables and what the task itself does is it iterates over the items in the variable called packages Then uses the Pac-Man module Says here this package name for every package I want it installed and I want the latest version So if you're familiar with Pac-Man, this will be doing an s y Ssy yeah, it's actually an s y followed by an s s Yeah, that's why so it would update and then no because it doesn't install as well, right? So it's an s y followed by an s s. No s. Yeah, whatever. Yeah, that's why Basically, the idea is if you were using something like Ubuntu, it would be an app get update followed by an app get installed Or yum update followed by yum install, but yum update doesn't actually do that So it's yum something something which I can never remember and I have to look up Yeah, yum is horrible, but sometimes we have to live with it for reasons So yes, I would definitely like to use ansible as much as possible to make my life with yum better Anyway, so that settles the issue of this one. There's only tasks and bars So it's a very simple role and I mean it takes you about 10 minutes to write if you have the documentation speaking of documentation This page Learn to love this page. It's a listing of every single ansible module and Documentation for every single ansible module. I think it's a bit stupid to put it all on one page But at least you can like command f yum There you go. You have yum and with yum Okay, that might have been too big. Is that yum? No, that's you all right. We need to find yum again Okay, there you go So you can now manage your sentos packages or your RGL packages or your scientific linux packages if you're into that stuff and You can always do horrible things like disable GPG checking for example Which Pac-Man will simply never let you do and will yell at you unless you go and do it in the content file and of course everyone's favorite enabled repo because What packages that the base repo have again like four things other than this kernel? Yep, and so you you know here it would be state and you'll notice its state equals present and not installed Welcome to hell with Ansible, but you know it's Let's just say that the The whole ansible thing is designed to have a bunch of machines a bunch of minions under your control that are all the same If every single minion was different, it would be a nightmare to manage them You know especially automated management of them So if you're writing a bunch of services that you know if writing and ansible playbooks for a bunch of services that Run on sent us while you use young You don't introduce an arch machine into the middle of a sent us cluster That's probably not a good idea even if you don't use ansible. So they never actually cared about that case But yes, I would like to see this fixed it is very annoying Now back to fun stuff Let's see, which is a more complex rule over here Huh murmur murmur is the mumble Damon You will see I have handlers now and have templates. This is where the ginger to templating comes in So let's just look at the bars because they're simple. I Tell it the port. I tell it where I want my sequel at DB my bit rate maximum of users message of the day Whether to use a snake oil certificate and my actual certs and key Obviously these are put in there by the SSL playbook. So they will be somewhere else And now the two things you guys have not seen yet handlers are basically just the same things as handlers from earlier except you put it in a separate file and You have templates murmur. I and I there you go Unfortunately, it seems it's coming up in red. So you may not be able to see it No, that's worse, isn't it? Okay, basically You put stuff in a double curly brace and it subsets in variables That's all you need to know. It's very nice. It's very simple and you can also do ifs, which I think I have somewhere Actually, I do have it here. If not murmur dot SSL dot snake oil So basically if I'm not using the snake oil cert here is my real cert and my real key If not mumble by default will just generate a cert for you and like, yep, here's a snake oil cert If you're not familiar with the term snake oil cert It's a self-signed cert that is just completely useless in general unless you Don't really care about, you know security in that case other than this we have Open VPN SSL. Okay, SSL is fun There's also fun stuff that you can do with this with you also see files here, which is, you know, it contains Files like oh look my SSL keys Except the encrypted so it wouldn't really help you to steal this repo Now if you look at the tasks, this one's a rather complex one probably one of the more complex ones that Is part of my base package and not relating to application deployment because deployment is really really messy And there's no way around it. So you just write one really good answerable thing for it And you just leave it alone So I copy the SSL certs with the copy command name obvious Give it the source give it the destination both of which come from variables I want it owned by route and I don't want other people to be writing to it Now when it comes to keys, obviously you don't you want to source control your whole answerable library But you don't want your keys to be just sitting there for anyone to take because that is Probably the worst security practice in the existence of mankind So what I do here is I run a local action local action is another module Which runs something on the machine you're running answerable on So if I were to do if whatever happens here will actually run on my machine. So here. I'm telling you to use the shell module Open SSL decrypt blah blah blah blah blah all it does is decrypt my keys with this particular file glob Which is a variable and then we copy the SSL keys over because they have been decrypted Herp derp 0 6 zeros are because and then you clean up your local things again with a local action So at this point basically The only time there was ever an unencrypted key on your disc was for a few seconds If you're doing this on an untrusted machine, don't Because you should not be having your SSL keys on an untrusted machine in the first place, right? So assuming trusted machine and it's not on your disc for very long It is kind of safe. Obviously if there is an error during the copy stage, it will never actually get to the cleanup stage So you will have an SSL key on your machine, which is why I say don't do it on a machine You don't trust you don't walk into your friend's office and be like hey Can I use your machine to like ansible my machine well for one? How are you actually logging in SSL SSH keys? You know And the last step I do is I copy engine access SSL config over Some people like to put this just like oh my god. It's engine access config It should be with the SSL, but then you need to find a way to transfer Variables across playbooks which pretty much means you have to move up the hierarchy and put it in the outside Playbook which Has no business knowing where the SSL keys are So I do everything in here if it's SSL related it probably goes here You will you would notice that there's a small violation of that in the mumble thing, but never mind about that So here. Yes You ran first right and say yes, yes, and I presume it's kind of like Set option error exit batch, right? Okay Yep You can just run it again. I will run a couple of these things afterwards and show you how it goes There's a lot like files give it source destination. It just runs shit It's quite simple, and I think that is all the interesting playbooks. I have I mean there's a lot of other stuff here like a Sample you whiskey app which I guess we can look at because it's different from the others Yes, you ensure packages are installed you ensure the engine X config itself is in place you ensure the project repos up to date So there's a git module which This bit will basically cover most of your deployment needs You have git you give it repo. You give it destination folder. You give it revision So this version thing is a bit weird because I'm not sure why it's called version because it can be a branch It can be head it can be a commit obviously you don't want head because that's stupid You probably want it set to master or deploy or whatever your deployment branches Then you make sure the Python packages are installed because we're all Python developers. So we use pip Out here pip has a module as well and most importantly the you know, absolutely essential virtual and support So you can give it a version environment. You tell it the requirements file. It will install everything for you So it just looks in there and that's the usual things and the last step is I put a similar in-game place Which will basically ensure that Emperor mode picks up on this guy and runs it Now let's run a few of these things I Have not actually run these in a very long time So I'm not sure if any of them or I've not run these on these particular machines at hand recently. So things might break Worst case scenario, I will just demo against my own server Which I would prefer not to but Let's say we run Triple W The other thing about Ansible is that if you have cow say installed and if you're not familiar with what cow say is Cow say moon makes cow say move and If you have cow say installed or as I like to call it if you have made the mistake of having cows say installed Ansible will Use cow say for all its messages. You'll be seeing a lot of cows. You'll learn to love your cows and Before the obvious joke comes know the guy who wrote it is not Hindu So in this case I asked it to prompt me for the decryption password because well, it's decrypting it locally, isn't it? So I key in my password it decrypts it and You'll notice that a lot of text is in yellow because it is actually It's Yes, there's a lot of small little stuff Anyway, most of the text is I is yellow because this is being run against machines who have not had this done So the state has changed it managed to do this it managed to do that then it threw a giant warning at me somewhere down here because I Most of my playbooks were written back in the old syntax days where it was dollar open curly brace But now they've deprecated that it's double curly brace on both sides So a lot of my repos still in the process of transition. There's that stuff Then you have all the stuff that's transferred and then a giant error at the end which says that It could not create bar triple w is transit chances are the bar triple w folder doesn't actually exist That's why this is happening Because like a genius I forgot to put in the thing to say you should probably create this folder and So it didn't do it I'm not going to bother retrying this because we're just gonna get the same error But if I do retry it You will notice that a lot of the output will be green Because it will it will check that engine X is installed and engine X will be installed It will check that the SSL key has been transferred and the SSL key has been transferred in this case The key is always transferred again So most of these things didn't run again because I'd important accept this one step because the keys decrypted locally Which means the modification time always changes in the file create them always changes, which means it's always copied over But it's an SSL key. It's fine if this happens for most of the you know more expensive things like Installing packages and all that it doesn't do it multiple times. It will only do it once and it just says yep, okay This is new this is new this is done Let's try something else. Maybe this would work Laziness leads to simple passwords like hello It's going to try and install it in the meantime I ran this thing You'll notice that the hosts is not all the host says VoIP What that does is it looks inside here looks for VoIP Which is here and then installs it only on the machine that requires VoIP Which is this guy no one else has it which also means that given the way I've currently set up my things It will not actually work in the long run installing murmur takes a while because it's a giant package And in the meantime we can take a look at Open VPN for example again Same stuff in this case. I actually have two separate things because I have my machine runs to VPNs So there's two bits of config for it and you'll notice that here the notify is Restart which means that I would probably have fixed Main there you go So because the service module didn't work with system CTL I had to use the shell module and do it manually which is not fun at all but Such is the way of things If I get bored enough someday I will probably end up writing the module to handle system D because why the hell not Clearly hasn't been done yet for some reason but You will never know why people didn't do something until you attempt it and fail and that's the best way to learn Yes, it's taking very long to install murmur Well, they're all alive that's good news Yes, you can you can basically add up to five V's Which will then start printing out every single thing. You can see the exact command that it executes which is currently terrible Well, actually I know what to do. I was being stupid the simple way to for me to fix this would be Just give me one Yeah, my terminals better for presenting. There you go. It successfully did it and If you were bored enough you would notice that It's running a bunch of SSH commands With What is essentially a Python script that's being transferred over so the way this thing works and the reason that there are no Dependencies unlike salt and everything else is all it does is take libraries build Python script SSH Python script over execute Python script Which is why it has no dependencies, right? All you need is Python to an SSH because that's exactly all it uses anything else just bundles it into the file for you if we go up to If we go up to the bits where it's actually transferring files, you might notice scp sometimes But basically with this many V's you can see exactly what is happening and Also gives you like nice little information like oh it changed and the blank item changed and installed one package Brilliant Yeah, for example, you will see that it Added a file right obviously, which is actually the conflict file from earlier from somewhere What is going on here? Okay, and That is pretty much it for the basic introductions I mean, I will probably post a link to my GitHub repo once I clean up this stuff Where you can go and poke around with these files I will obviously remove the SSL set despite it being encrypted Because who knows where you know decryption thing goes like five days from now But yes, if you have any questions now would be the time It goes into TMPFS and then it likes to delete it so you would have to somehow kill the process before it manages to Build your over again and control Z it that way through and then just examine see what this thing is this thing like a whole like Polycrafted crass or is it something as small sweetened first library let's see it was an answerable to This is the Ansible Python module that it transferred over and there are 1243 lines in just the pipe the pac-band module This is not even the whole script So yes stuff is pretty big, but it generally likes to cache it so It's not quite that bad it's not as Efficient as salt would be But again salt also has a very strict master and sleeve Config whereas with Ansible you can either do push config like I've been doing all this time Or you can have the nodes pull or you can do something where like you push to one node and you have that node Push it to all the other nodes So you could have a cluster with say a controller and you just push the new config to the controller who pushes it out to all the little nodes that are Happy about it My Ansible version I need to switch to the next one for one any other questions People normally ask how it compares to other stuff, but I think I went through that briefly at the start. Yes Machines Yep, if I'm not wrong there is an IP tables module Not sure if there's a pf module They should be because they have been like really beefing up there be a support these days I personally this repo that of mine is all the Ansible scripts for just one VPS of mine So even though I don't use it to administer multiple machines It still has value because most people as Patrick likes to say are sticky to VPS providers Let's say you sign up on AWS you set up your instance after like two weeks you don't want to move because How your config is stuck then you need to copy everything in my case if you want me to Deploy a new instance like tomorrow in search VPS providers. Sure. I just run one command. It would be like Ansible Playbook Site. YAML enter And it would just set up my system exactly the way I want it from scratch Assuming my stitch key was there of course It's particularly useful if you have say a local cluster that you set up using KVM Zen Whatever you choose Because then you have full control over both the base image where you can ensure that you know public keys and everything in there And your Ansible config which? Customizes that machine to its role Can you get the output back in Jason? Yes, you can was there no reason to do that you can get the output back as Jason trivially for stuff that you run on the command line Okay, if you want it back as For like a playbook you cannot launch it from the command line. Obviously, you'll have to use their libraries So they have libraries for scripting this If you'd like to, you know, maybe brought a web interface someone to do it. Okay. Okay. So thanks