 Good morning, my name is Solomon Gifford and I work with a company BlackMesh. We are a managed hosting company and I've been there for a little over a year now working on a product called Cascade and I will give a little demo and an announcement about that at the very end of the presentation. But to give you a little bit of a background of where I got started in DevOps, I used to work for a large nonprofit in DC that had a large Drupal site and originally it was just a HTML silo but we converted it to Drupal 5 way back in the good old days and over time it was needed to be upgraded to Drupal 7 and so I led that effort but when I first got there literally all of the devs were doing their development on a single box, it was a shared server, hot fixes were done on production. We had a developer who was testing joins out on the production database and I kid you not the database was going down weekly, sometimes daily and a number of these issues were leading to other problems and as I was promoted to the director which was more like Drupal lead, we made some changes, we moved to Git so that we could track our changes better, we moved to scheduling our deployment so that we're not deploying at just any time of the day. We created an environment for every developer so that developers weren't stepping on each other's work and we had a true load balance staging environment and by the time I was done our database has had over two years of uptime. We had many fewer errors in terms of taking things to production and of course increased availability to the user which was the most important thing. This is a high performance website of over 100 million members, I'm sorry 1 million members so you can kind of get a little bit of a picture of the size and the scope of what I was dealing with. So again this led me at the end of that process to working for BlackMesh hosting company because I had just essentially gone through doing this for a single customer and they brought me on to essentially set up a system to give our customers and we'll talk about some of that at the very end again. So today's presentation is on the idea of local versus remote development and to give you a little bit of a preview of where we're going in the presentation. We do local development, we can do remote development, but there's the advantages of each and we're going to try to talk about how to use some tools mainly Jenkins but also talk about vagrant and HA proxy. Use these tools to essentially keep these environments in sync and if you are already a vagrant expert, if you are already a Jenkins expert, if you already know a little bit about HA proxy then this presentation may not be for you, but hopefully everybody can get something out of this. So I guess I just said this, but yeah vagrant, HA proxy, Jenkins and of course at the very end we'll talk about something called Cascade. So I guess the question that I would ask, how many of you do your development on a laptop or a desktop? So majority of you, how many of you do it remotely by SSHing into a server? Smaller number, how many of you do both? Most of us are already doing both and I would guess that there are reasons that you're doing it in both locations. So let's talk about local development for a second. So when you're talking about local development, you have low network dependence, right? So you don't have to worry about if the internet's out or if you're on a train, you're on a plane, you can do your development anywhere. You can also use your local IDEs, your tools, each developer has their own workspace. Of course you can do that remotely as well, but this is your workspace, you can muck it up all you want. And then of course there's the concept of security, right? So if you work for the government sometimes it could take a week or even months to get access. As the director of technology for the previous organization that I was a part of, there was a guy that I did not want to have access even to dev. This guy just screwed everything up all the time. How many of you have one of those in your organization? How many of you are that guy? No, just kidding. So hopefully you're seeing that there's maybe reasons that you have to do local development or many times want to do local development. On the other side of the coin we have the concept of remote development. One of the biggest challenges with local development is demos, right? You have to actually bring your computer to someone and say, hey, you see what I'm doing? Or of course you can use join me or some other conferencing system. But it's not like you can just send someone a link and say, hey, go check out what I've been working on. Where obviously with remote development you can pass somebody a URL. How many of you work with really large databases? All right, so a number of you. I assume that you don't want to bring those databases down to your local environment. It's just not feasible. Or even large file sets. Also when you're talking about integrating with APIs or solar or remcache, et cetera, when you start integrating with some of those, you might not want to set those all up on your local machine. Maybe you don't know how. Now, I'm sure that some of you know how and you can do it very easily. But there's a lot of developers who they've never touched those layers of caching. And so they just let somebody else take care of that. And so the point being that if it's remote, if you log into a website, I'm sorry, log into a server that's already been set up, you can just jump into development right away. And then this last point I think is important as well. So if you have a guy on your team that's your support guy, he's the guy who sets up your new environments or sets up the new projects on that remote environment, then you lean on him to take care of that. And so, or maybe you are that guy and the guys around you lean on you. But the point is that one or two people know how to set up all different caching layers and have the permissions to set everything up. So the point is that you can offload this to a single person or to a number of people. There was a shop that I recently spoke to and there was, again, one guy who did all the setup for their organization and he essentially wasn't developing anymore. He spent his entire life just supporting the other developers and he was the Drupal lead. And so essentially he was the guy who should have been doing the most in terms of Drupal development. Instead he would spend all of his time doing other things. So the point is that there's advantages to both remote and local development. And we're going to try to see by the end of the presentation what can we do to do both. So the challenge that we're going to try to solve is how do we keep our remote and our local environments in sync. Now when I say in sync, some of you probably immediately thought, okay, this is a cron. This is something that's automatically happening at some kind of frequency. Or maybe you're thinking automatically every time I do a get commit or maybe you're thinking on demand every time I push a button or initiate some process. And I would say all of those are yes. I'm not going to, I'm going to talk about some of the different ways that you can do it, maybe a combination of this. I don't think anybody wants their databases automatically on a cron overriding their work. But yes it can be done. So we're going to talk about Jenkins. So Jenkins is a continuous integration server. How many of you have played with Jenkins? Okay, a number of you. So I'm going to assume that before you knew what Jenkins was and you read the definition that it was a continuous integration server, you were like what's a continuous integration server and then someone said, well, it's something like Jenkins. And you get yourself into this loop. And I like to just say well when stuff happens, Jenkins does stuff. And that's my simple explanation. So Jenkins can submit, sync code on commit, it can sync databases on demand, it can sync files on demand and those are the things that we kind of want to do with the website when we talk about keeping a remote and a local environment in sync. So when we think about where is Jenkins installed, I'm going to go through two scenarios today. The two scenarios are first, Jenkins is installed locally. You're actually going to install Jenkins on your machine. I'm not going to actually watch, you know, do a demo of it being installed but we're going to talk about some of the issues. And then the second is in a remote environment. So some of you have a dev environment or a machine that your company will allow you to install Jenkins on. And that's another solution. But with both of these solutions, there are some issues that we'll talk about. So for example, if you're going to commit to a Git repo and your Jenkins is on your local machine and you want your code to automatically check out every time you do a commit, well somewhere on the web where that Git is hosted needs to have a ping back to your local machine to run that Jenkins job. And unless you're going to set up dynamic DNS or something like that, it's hard to happen, hard to be done. There's lots of solutions I'm sure you could figure out, but the point is it's not as simple. And I'm trying to solve this as simply as possible. And in a remote environment, well again, that remote environment, if Jenkins is in a remote environment and needs to have access to your machine, and so we're going to talk about setting this up with some reverse SSH tunnels. So there's some challenges and we'll talk about those as we go through. So again, there's two scenarios, we'll talk about one, then we'll talk about the other. So the first one we want to talk about is running Jenkins locally in a vagrant environment. How many of you use vagrant? A lot of you, great. So how many of you have used vagrant with a multi-machine setup? All right. So that's what I thought. So I came into this presentation assuming that most of you had played with vagrant, or at least knew it was, but when we talk about using vagrant in a multi-machine environment, there's limited documentation out there. I mean, it's out there, but there's less information out there on using vagrant in a multi-box setup. So we're going to talk about that. And we're going to set up or show you a vagrant file where one of the two boxes is for Jenkins and then the other box is for your development. And in this scenario, you could essentially have multiple other boxes for different projects if you wanted it to be done that way as well. So we're not just talking about two, we're talking about n plus one. All right. So over here, I have a vagrant file. And how many of you have edited your vagrant file? All right. So about a third of you. Okay. We're a little less than a third. So for those of you that have edited your vagrant file, it's a Ruby file, and you really don't have to know Ruby. You just have to figure out where to copy and paste, right? So with a multi-box vagrant setup, each one of these config.vm.define regions is a box. And so I'm going to scroll up and down in this file so that you can see the very top, we have some initialization of scope at the very end. We have an end statement. But between that, we have these two boxes that are in a config.vm.define. There's one at the bottom there, and you've already seen this one here at the top. And so I'll go through very briefly what this file is doing, so you can kind of see how this is working. But the first one here, we're giving it a name Jenkins, and we're giving it a scope of the Jenkins server, and we're giving it a host name of Jenkins.blackmesh.com. You could name that anything. I chose blackmesh.com simply because I work for Blackmesh. And then I give it a box URL or a box name. If the box is already downloaded on your computer with vagrant, then you can just give it a box name that's local where you can give it a vagrant name from Hashicorp's vagrant boxes, and it will automatically download. You could also give it a URL. There's another setting, Jenkinsserver.vm.url. You could actually give it an alternate URL so that the boxes are downloading from some other location. And the point is there's a lot of boxes out there. If you do a Google search for vagrant box, you'll see a pile of them. So in this example, I have a Jenkins demo box that I've created, but if you're creating a box, maybe you just want to grab a SenOS or a Ubuntu or a Debian box and start from there. Again, if you Google the web, you can find a bunch. Be careful, obviously, from a security perspective. You don't want to just be downloading anything, so kind of trust the people that you're downloading from. I like Puppet Labs. They have some good SenOS boxes. So my second box here you'll see is a SenOS 6 Puppet Labs box. All right, so then you have a region. We call it the provider. So most people working with vagrant use virtual box. You can use VMware as well. And you can give it a number of CPUs and a amount of memory here. For Jenkins, I'm going to go ahead and give it two, but it could have been one just as easily for the RAM. And the final three lines set up the network. And this is really where I'm going with this. We need to set up a network between these two boxes. So we have our vagrant box, we're going to have our local development box. They need to connect to each other. They need to talk to each other. And so we want to put them into the same network. And so we're going to create a private network. Now, we could have set this up as a public network. We could have done bridging. We could have done other things. It's a little bit more complicated. And I'm a guy that likes simplicity so that I can redo this over and over and over again. So my model, private network. So here's the IP address. I'm assigning it this IP address. I decided what numbers to give it. And you'll notice for the second box, I gave it a different number. So I'm not giving it the same IP address. And I need to forward the ports. So here's another, for those of you who've played with vagrant, you know that whenever you run something in vagrant, it's not, when you're sitting out on the host machine, you type in the URL of something that's running on the vagrant box. It's not the same port number, right? So if you are, you know, web runs on port 80, port 80 on the vagrant box, isn't port 80 outside of the vagrant box. Which means every time you type in a URL, you're typing colon and then a port number. And we'll talk about how to get rid of that in a minute. But the point is that this port 80, internally to the box is getting mapped to an external port. And you can determine, you can decide what you want that to be. In this scenario, I chose 8111 for no real reason. And I'm also going to allow this to connect securely over port 443, which is being mapped outside to 18 and 443. The last thing I'll show on this Jenkins server is that there's the concept of a provisioning script. And this is a number of commands that you want to run. And this box is created. And there's a bunch of provisioners out there. There's puppet and chef, enhanceable provisioners. Or there's the shell, which means you can just write some commands. And when vagrant spins up this box, it just runs, runs those commands. So I'm doing it in line. It's just going to do a service Jenkins restart. Every time this start, every time this box comes up. Now, I don't have to restart Jenkins. I'm only doing this for purposes of demo. But whatever you wanted to be installed or run when this box comes up, you could have done this. And in this scenario, I've put the run always, meaning do this every time the box comes up. Not necessarily just when it comes up the first time, which is what would happen if I didn't do run always. All right, so hopefully you're seeing that this vagrant is allowing us to spin up a box. It's using virtual box. It's spinning up a box called Jenkins. And Jenkins isn't necessarily installed on it yet. For my purposes of the demo, I went ahead and installed it on here already. But if you're spinning up a brand new box, yes, you are going to have to install Jenkins on this. And then I have a second machine that I'm spinning up. And it's a SenOS 6.6 box. I've grabbed it off of Puppet Labs. And I'm not going to go through all the other pieces of this, since it's very similar to the previous. But I will show you this one thing called the synced folder. For those of you who've already used vagrant, you know that you can sync from within your vagrant to, within your vagrant box, you can mount that outside so that your code is kept in sync. And so my var www.localdev inside my vagrant box is mapped to this on my Mac. All right, so now you're an expert at vagrant multi-box setups. And so you can create your vagrant box. All right, so back to the slides. Once I've done that, I need to do something like vagrant up local dev, vagrant up Jenkins. This is what actually starts up those vagrant boxes. And if I want to log in to them, vagrant SSH local dev. So for those of you who've already played with vagrant, you know some of these pieces already. Vagrant halt will kill a machine, or it will shut down a machine. Vagrant destroyer will kill a machine while you restart it all over. But back to the original scenario, we're trying to set up one box for Jenkins and one box for development. Now if you're like me, you don't like all these ports. So hopefully you'll get, for those of you who use vagrant, hopefully you'll get something out of this next little piece of the presentation. When we talk about all these port mappings, if you're using Jenkins especially, Jenkins will redirect often to port 80. So if you're running Jenkins within a vagrant box and it redirects to port 80, and of course you're trying to run this on port 8111, then you're gonna constantly get errors in your webpage. So we've gotta find a way to map the ports without us having to type them in every time. So how many of you have played with HAProxy? One, well, so you all came here today for the HAProxy, okay. So HAProxy is a really nifty piece of software. Unfortunately it doesn't work on Windows, but essentially it'll allow us to map different ports and different URLs into vagrant. You can kind of think about it as similar in a way to varnish, not from the caching perspective but from the other things that it has. So essentially to start HAProxy, we're gonna obviously we need to install it on our machine, but to start it and stop it, there's not a start and stop command except for you're gonna run it from the terminal, HAProxy-f meaning I'm gonna pass it a configuration file, and I'll show you an example of a configuration file. And to shut it off, again there's not a stop command, but we can always do a pseudo-pkill HAProxy to kill it and that will shut it off. Or of course just restart your machine. Pkill's a little bit easier. So I'll show you an example config file here. Okay, so an HAProxy configuration file has a couple sections at the top, a global section and a default section. I'm not gonna go into what each of the lines mean, you can Google them, but essentially the important thing here is we're running this as the staff user on the staff group, which is my default group on my Mac here. And we're running this as a daemon and it's also supporting SSL. It's globally logging, et cetera, et cetera. Here's some timeouts. The important parts are down here at the bottom. So I set up two front ends. You see front end here and here. And I'm gonna name them arbitrarily, HTTPS front end and HTTP front end. Sorry. So I'm creating two front ends and that's essentially saying I'm going to listen on some port, use some rules and then redirect those calls to somewhere else. That's a big picture of what HAProxy's doing. So bind 443 obviously is HTTPS. So our front end for the HTTPS is listening on port 443 and then the rule that I've given it is essentially if I see Jenkins.blackmesh.com in the URL, then it's going to do something with this. So this is a listener on port 443 for the URL Jenkins.blackmesh.com. And when it sees that, it's gonna use the back end of Jenkins servers. I got to define Jenkins server somewhere later in my file, but I've set up my listener. I'm also gonna set up a second listener to listen on port 80. So I'll call this the HTTP front end, bind port 80. And I'm listening again to Jenkins.blackmesh.com. And if I see that, I'm gonna use the back end of Jenkins server. And then finally, in this front end, I'm still listening on port 80. I'm also gonna add two more listeners. One for d8.example.com and then another one for localdev.blackmesh.com. So think about the websites that you're setting up within Vagrant on your development box. You obviously want those to map as well. And so here the host, the HDR underscore end is essentially saying if your URL ends with d8.example.com, then I'm gonna use my development server. All right, so big picture. I have two front ends, both listening on different ports. And if I see Jenkins.blackmesh.com on both of them, I'm going to redirect the traffic to the Jenkins server back end. If I see these two URLs, d8.example.com or localdev.blackmesh.com, it's gonna use the development server back end. And I have those back ends defined down here. So back end Jenkins server is essentially saying if I see it coming in as non HTTPS or non secure, redirect it to secure and then take the traffic, send it to localhost on port 18443. My back end for my development server is saying if it's coming in as HTTPS, redirect to HTTP and use the back end development server, which is localhost port 7082. So once I run this, it's gonna be listening for Jenkins.blackmesh.com, it's gonna be listening for d8.example.com and it's gonna be listening to localdev.blackmesh.com and it's gonna redirect those traffic to the right port on my vagrant boxes. So that's what we have been able to set up. All right, don't forget to add those domains to your localhost and Etsy hosts as well. Okay, all right, so that scenario, I gave you all the stuff about vagrant, I gave you all the stuff about HA Proxley just to set up that scenario that vagrant was installed locally. But I said at the beginning that we could have vagrant either installed locally or it could have been installed remotely. So in the other scenario that vagrant, I'm sorry, that Jenkins is installed remotely, well, we've gotta have some way for Jenkins to reach back onto your local machine. Again, the first scenario, Jenkins was installed locally on a vagrant box. Now Jenkins is gonna be installed remotely. Well, in this scenario, all we have to do once we have our single vagrant box set up, that's gonna be our development environment, we've just gotta use auto SSH or some other mechanism to set up an SSH tunnel. And in this one liner here, we are mounting, or I'm saying binding, port 101.00 on that remote box, wherever Jenkins is installed, making that port essentially port 22.00 on my local box, meaning that I can SSH to local host and that port on the remote box and it will have access to my local machine. So I'm creating a path down to my local machine. Again, I'm trying to keep these environments in sync, I've gotta create the connections, I've gotta create the paths. I'm not a network guy, so I can't explain the rest of this. Well, I can try, but let's not do that. All right, so once I've installed Jenkins, once I've set up my, I've decided whether it's gonna be local or remote, there I have my front page for Jenkins. And again, Jenkins, I'm not gonna go through and install Jenkins, it takes a little bit of time. You gotta set up Java, which is probably the hardest thing you'll encounter, which isn't too hard, but obviously you do it. And then you can create these jobs. So in this page you see I have four different jobs or five different jobs. And I'll talk about these a little bit briefly in a little bit. Okay, so let's go ahead and set up Jenkins and we're gonna have to set up first a plugin in Jenkins, the GitLab hook plugin, and I'll show you why in a minute. Then we're gonna add a web hook to Git or to GitLab or to BitBucket or whatever your Git happens to be. And then we're gonna add a node, I'll talk about that term in a minute in Jenkins, and then add a job in Jenkins. So I'm gonna go ahead and do a little bit of a demo here, and of course demos are always a little bit scary. We'll see if we can successfully do this. So I have Jenkins running on this machine. And if you wanna know where to add plugins, here's the managed plugins. And I've already installed it, but essentially what I would have done is typed in Git, what was it, Git? Well, I'll just say, if you type in the word Git, you'll see all the different available ones or the installed ones or whatever. I'm typing too many things here. So you can install plugins, but the one you're looking for is the Git hook plugin. That's already been installed. Once you've done that, we need to do two things. So Jenkins has this concept of a node. A node is a machine that it has access to. So I've already set up three nodes here. One comes by default. When you first log into Jenkins, it has access to the machine that it's already sitting on. That's always called the master. But we want it to have access to two more machines. One is our local environment, one is our remote environment. So I've already set up two nodes and I'll go through the configs here of local dev and remote dev. And so these, again, these nodes are just machines that it has access to. So I will go ahead and look at the configurations for local dev. So I'm going to name it local dev. And it has to have a directory that it starts in, a home directory, if you will. And because I'm using the vagrant user, I'm going to use home vagrant. If you have another user you've set up on the machine, then you can use that as the home directory as well. The concept of a label, most of you will be familiar with because we're all in the Drupal world, but a label is simply like a taxonomy tag. And I can then later tag jobs with that same taxonomy tag. And that means that that job runs on this node. And so it's just a way to connect and associate a job to a node. So I'm going to go ahead and label this local dev. I could have named this anything. It does not have to be the same as the name of the node, but for simplicity I went ahead and did that. I set the only build jobs with label restrictions matching this node. I don't want other jobs just randomly running on my local machine. I only want ones that have been explicitly said to run on my machine, to run on my machine. The launch method here is the default to SSHN. And now I have to give it where to log in. So in this version, remember I was talking about Jenkins can be installed remotely or locally. In this version, Jenkins has been installed remotely. And so I need to connect to that SSH tunnel. And so 127.01, and if I actually open up the extra advanced information here, you'll notice port 101.00. If you had been on your remote, if this had been on a local machine, on a vagrant machine, then you'd have used the IP address from that vagrant file that we showed earlier. Point is wherever your location is for your local dev, that's the IP address and important number that you're going to put in. The rest of this information isn't necessary. The hardest part about setting up a node, I'll be honest with you, is making sure that Java is installed on the remote machine and setting up credentials. Now if you do it right the first time, great and you'll never have to worry about it again. But make sure that you set up a user and credentials so that Jenkins can log in as that user. Or have a user that you don't mind putting in the credentials into Jenkins. You can set up credentials with usernames and passwords, with keys and usernames. But the point simply is that credentials sometimes give people a little bit of a difficulty setting up. So I've done that for the first node. I'm not going to make any changes here. I'm also going to add that for the remote dev. Configure. I don't have to show really anything unique except for I'm labeling this something different and it obviously has a different host. So this happens to be the URL of my remote machine. Now that I have my nodes, these are the places that Jenkins can log into. Now I need to create a job. Now you can ignore these bottom five jobs. They're part of Cascade, which I'll show at the very, very end. But this job I created earlier this morning, actually. And I will show you some of the configurations. So I give it a name. I restrict the project to only run on local dev remember this was that tag that I tagged on the node. It's a Git project. I give it the repo URL for my Git and also give it credentials so that it can know how to log in and access Git. Obviously this is accessing Git, not accessing the machine, this is accessing Git. So if you're using an SSH key to log into Git then that's what you'll give here. And you can create special credentials just for Jenkins if you'd like. Not a whole lot else to do except for run commands in a shell. Now there's a couple ways to set up Jenkins in terms of what you want it to do. In fact there's lots of plugins. I'm just gonna show one way. Essentially I'm just gonna run two commands. I want it to CD to a directory and I want it to do a Git pull on the origin to be meshed up. If you want to add other commands or the checks to see if there's files that need to be checked in first if you want to modify this to send you an email if certain conditions exist, feel free, go ahead. I'm just going to assume everything's okay and do a Git pull in my little example here. And so what this should have set up is Jenkins is now ready anytime I commit to that branch that I just associated with that job. It should take those two commands that I gave at the end of that job and run them on the node that I associated with that job. So that's what should happen. One final piece that I need to set up and that is that over in my Git lab or BitBucket or wherever I have my Git repository I need to set up a webhook. And this webhook is going to be the URL of my Jenkins forward slash Git lab build now. And what this does is anytime a commit is done to this branch, then Git or my Git lab in this, which is like GitHub by the way, it's just installed locally so that I could do this for a demo. But GitHub will fire off this hook and tell Jenkins, hey, he just committed something. Go do your thing. And remember Jenkins I said at the very beginning when Jenkins is essentially something happened, I need to do something. Well, that something happened is that this hook was fired, this hook was fired because you committed something. So I should, again, demos are always scary. Here's my local dev. I have a nice Drupal image here. And on my remote dev I have a similar image or the same image. And I'm going to see if I can't copy a different image. All right, so that should be the right one. So cat ascii2.html into ascii.html. Now right before this presentation I found that my hook for some reason was not firing and it's a Git lab issue. So I'm going to manually test this hook. What you'll see as soon as I did that commit Jenkins should start to run. Unfortunately I can't show you it running because it has already run. It ran and here it is. And here's the output of it running. The point simply is is that it took this file which we had changed to this file and copied it to my local environment successfully. So essentially what we saw is I committed from my remote environment and it checked that out immediately on my local environment. And so now I've kept my code in sync on a commit. Now I'm not going to show you how to do a database or syncing files. I hope you can think through that essentially a database. Let's think about the steps. We're going to export the database on the remote. We're going to copy that file to our local. We're going to then import that from our local into the new location. We might want to first back up the local so that we have a backup of it. Obviously when we're talking about file and disk space you got to be careful. Let's think about files for example. We can do an R sync from the remote to the local or vice versa. And so in this job here, instead of the commands being to get pull, origin, B mesh, it could be those list of commands that I just mentioned. So either dumping a database, R syncing the file over and then doing an import or in the case of files just doing an R sync. I know it's a little bit of hand waving but there's a lot to show. Okay. All right so the last thing I'm going to show for the last few minutes here. For the last year I've been working on a product called Cascade at Black Mesh. And here's the cool announcement. We're going to be open sourcing this within the next six months or so. And hopefully others in the room would get involved in the project. But essentially what it is is a workflow tool. So we all know that CommerceGuys has platform.sh. The Pantheon has their platform. Acquire has their platform. We are creating, it's probably not, it doesn't have as many features yet. But we are creating a similar type product. And we're open sourcing it. And yes, in the end it's just glue around Jenkins and around Cascade. I'm sorry Jenkins and GitLab. And we hope to have it support not just GitLab but GitHub and Bitbucket and other Git repos at some point in the future. And maybe even other continuous integration servers besides Jenkins at some point. But our model is to essentially create a set of scripts and a set of command line options that allow us to set up all the things that we just talked about today, not just for local to remote, but also from local to remote to staging to production. A full suite of a tool. We currently have some customers that are using this. So it is a product that we do have at BlackMesh. But our big drive now is to open source this. And we're working on that. And I'm not gonna go through all the different pictures of how this works, but essentially Jenkins is using Ansible. Which I'm not sure if you're familiar with Ansible but it essentially allows you to log into a machine and do stuff. And Jenkins obviously does stuff. So between the fact that Jenkins can do stuff and Ansible can do stuff on a remote machine, it's a nice marriage. And we can use that to deploy things from development to staging to production. It can obviously do more than just dev staging and production. It can do a local development, for example. We can have multiple web heads for staging, multiple web heads for production. We can group our sites. It also supports non-standard sites. And what I mean by that is it's not just Drupal, it's also WordPress or Node.js or any other application. Essentially if it's in Git, has files, connects to a database, we can do it. So on this machine I actually have seven VMs running in my Vagrant file. It's a Jenkins machine. It's a remote dev, a local dev, staging, productions one and two, and an installer which I just use. So I'll show you a quick little demo of Cascade and then I will answer some questions if there are any. So here's the dashboard for Cascade. And there is a Cascade CLI, a command line version, which also helps with setup, so to add a new site or to add a new environment or add a new machine. I'm not gonna demo that if you're interested in that, you can see me afterwards. But we have the concept of a group. So we have multiple sites and the multiple sites. Multiple sites can be in a group and so this just allows us to group our sites. The, on the right-hand side here, we have different machines. You can restart a machine, so I'll restart a service on a machine I should say. And this is all permission-based, so every single button that I click is essentially a permission on the back end. So you can, if you're working on a team, some people have access to certain deployment paths, others have other permissions. It may be that you never want anybody to take a local database and push it to production, hint, hint. So in that scenario, you would remove that permission from everybody. But I do have a Drupal 8 site, so that was the groups, here's the site, and I have four environments. So remember at the beginning of the presentation or this whole presentation is about keeping our local and our development environments in sync. Well, here's a local environment. This is actually connected to this laptop. The development production and staging machines are, yes they're in vagrant boxes, but I've removed the network access between them and local dev. So it's simulating, these are out there on the web, hosted somewhere else. And if you click on the different previews, you can see what that site looks like. So this is a demo, this is just a basic Drupal 8 install, which I happen to change the permissions on so that I can execute things without logging in. And so there's a dev, and there's my local dev. And so we're going to change, use the database here. We're gonna add some content to the dev. All right, so this is the remote dev. I'm gonna add an article, test demo, test demo. Again, demos are always scary, we'll see if this works. So I've added this piece of content to my development. And this, I'm gonna demonstrate, hopefully if this works, I'm gonna demonstrate taking that database from development and copying it down to my local machine. So this was the local machine, as you can see. I'm refreshing the page here, there's no content. And I'm going to deploy the database from development to that local machine. And the way this works, is this is using Jenkins in the background. This is just glue and interface around Jenkins. So Jenkins gives a man of time that it is estimating that it's gonna take. So this is estimating it's gonna take about 40 seconds. And the steps are the ones that I outlined earlier. The first thing we're gonna do is we're gonna take a dump of the development database. We're also gonna do a dump of the local database. We're gonna copy the file from our development machine to our local machine. That's the R-sync here. And once I've done that, I start an import. And you'll notice that this job is already completed. That database has been moved from my development machine down to my local machine. And this was the development machine. This was the local machine. If I refresh this, if everything worked as I intended, then I should see content here. I should see that test content. So I've refreshed and there the test demo that worked. All right, I appreciate it. All right, so I will end with questions. I think there's a mic over here. If anybody has any questions, I'll be interested in answering. Go right ahead. Hi there. We do lots of different applications, not just Drupal. So, for example, Symphony and e-commerce and PHP-based. But one of the challenges we have is config, i.e., we have a Symphony application and the production configuration is different from the development, is different from the staging. Pretty much every single, well, not every, but it happens quite often that the config files get lost, aren't in Git or shouldn't be in Git or should be. So config is something, I wonder what's your view on handling config files? So we have one customer that has a similar scenario. What we've done for that customer is we've installed something called GitWatch and what essentially it's just watching for iNode changes on the server. And so anytime a file changes in the config directory, it doesn't get commit and check in and automatically checks it in. And that, of course, with Git Ignore, you can exclude certain configs, so you might not want, for example, your homepage settings to be changed. But essentially, it automatically commits those in and then the next time changes go live from staging or dev to the next environment, those changes then do go live. So GitWatch is the name of that. That's not something we manage, but it's out there. Any other questions? Yes, sir. In your scary example, did you demo? Did you Git push something or did the Jenkins fire it up using your platform? So in the second demo, I was just a database push. I didn't show a code push. In the first example, I showed a code push which didn't use Cascade. So in that, when I did a Git commit, it committed to Git. When I pushed it, it pushed it up to GitLab. GitLab was supposed to fire a hook and that failed and I pushed the hook manually, but I'm not sure, right before the demo, it failed to hit the hook, but that's a GitLab issue, not part of the demo. But the point is that when that hook fires, it fired to Jenkins and Jenkins would have, and it did, check out the code. Cascade does the same exact thing. Again, Cascade is glue and it's a wrapper around GitLab and Jenkins and it also does the same thing. In fact, any time you commit anywhere to those branches, it will check out that branch to the right environment. So we have customers, for example, that do a change to production. They pull out the production branch, do a change to production, do a commit and it immediately checks out on production, on all the production web heads. I don't recommend obviously going straight to production. I'm just giving that as an example. Okay, thanks. Yep, any other questions? All right, well thank you for coming and of course there's opportunity for feedback, so appreciate it. And I'll stand around up here and answer any questions you have. Thanks a lot.