Python for Entrepreneurs Transcripts
Chapter: Deploying to the cloud
Lecture: The deployment playbook

Login or purchase this course to watch this video and the rest of the course contents.
0:01 We just wrote a whole bunch of code in the last video
0:04 to create our initial configuration for Digital Ocean droplet.
0:07 You may want to take a little break, but as soon as you ready,
0:10 we're going to dive right back into creating our second playbook,
0:13 we are just going to form the foundation
0:16 for us to deploy our application to our server,
0:19 not only once, but every single time we make changes.
0:21 Let's switch back over to the command line.
0:23 We've already got some of our files set up, from writing the initial configuration.
0:26 Modify the hosts file, and we're going to create a new configuration.
0:30 I'll just call this one common, and again,
0:34 specify the IP address to your Digital Ocean droplet.
0:37 We're also going to specify the Ansible Python interpreter as Python 3, save that.
0:43 Next up, create a file named deploy.yml, write out a quick comment here,
0:49 now just like we had our init_config.yml, we are just going to write a few lines here,
0:52 we'll apply this to a common host and this time
0:56 and this is the really important part, that the user is going to be deployer.
1:00 Now, this user should be whatever name that you've named in your group vars file
1:04 for your non-root user, and the roles we're going to apply
1:06 just common, so common will be the name
1:10 that we use under roles for this playbook.
1:14 Save that file and quit out, now head under roles,
1:17 and instead of init_config, we're going to create a new folder named common,
1:23 move under common, and we're going create
1:26 three directories here: templates, handlers and tasks.
1:31 Now templates are going to be files like our configuration files for supervisor;
1:35 handlers are used for services, for example if we need to restart nginx
1:39 after many different tasks that we do, we can just call
1:43 a handler to do a common operation over and over again.
1:46 And then task, we've already been introduced to, that will form the backbone
1:48 of all the instructions we want for applying our configuration to the server.
1:52 Head into tasks, and this is where we'll start things off
1:55 create a file, name main.yml, start out with little comment
1:58 and now we're going to take advantage of the include statement,
2:01 so rather than just writing every single task in here,
2:03 like we did in the previous playbook, for initial configuration
2:06 we're going to essentially import other yaml files that Ansible will use
2:11 as instructions for setting up our server.
2:13 First one we'll call Ubuntu,
2:16 now throughout the remainder of the videos in this chapter,
2:19 we're going t be creating several other yaml files,
2:21 in this video we're just going to flesh out a Ubuntu,
2:24 but let's go ahead and add the other includes just as comments,
2:27 so that we can see how this entire deployment will come together.
2:30 The next one we'll call letsencrypt, and this is going to be
2:33 setting up our SSL certificates for our web server
2:36 after that, we'll set up the web server itself, which will be nginx,
2:40 we'll be configuring that with https;
2:43 the next one will be our source code, which will happen and git
2:45 and these should all be yaml, not html.
2:48 Next up, we'll handle application dependencies,
2:50 then we'll handle running as a wsgi application
2:53 and finally, we'll just create a notification process,
2:57 because as you build out your deployments, sometimes these deployments
3:00 can take up to 5, 10, 15 minutes to complete
3:04 so it's nice when you can walk away from your computer
3:06 and get a text message when it's finished or something like that,
3:10 or get an email or post to a Slack channel.
3:12 Notifications are really simple modules,
3:14 but they let you take your attention away
3:17 from what's happening with the playbook and go work on other things.
3:20 Alright, save this file, and now we'll create ubuntu.yml.
3:23 In this playbook, we're really just going to do a couple things,
3:26 we're going to install some basic Python packages,
3:29 system packages through Ubuntu, and we're going to set up the firewall,
3:33 we really only want to have two ports open in our case
3:36 the first one is just going to be port 22 for ssh,
3:39 and the second one is going to be 443 for https connections.
3:42 And then, port 80 it for http connections, even though we're not going to
3:45 respond over http, we will redirect to the https version of our application.
3:49 Alright, the first task we're going to write,
3:52 ensure Python packages are installed, again use that apt module,
3:56 and we're going to use a slightly different syntax here,
3:59 we're going to use a variable, but we're not going to declare this variable
4:02 in or group vars file, we will say update_cache before we install each of these items
4:05 and here we're going to specify become is true
4:10 what this does is use a sudo in order to escalate privileges
4:14 so we can install the system packages, without using sudo
4:17 deployer is not going to have the appropriate permissions
4:20 in order to install these packages and our deployment would fail;
4:23 when we write become true, we can become any user,
4:26 we can use this to become a postgress user for using a postgress database
4:31 but if we don't specify who else to become, it'll just use the sudo mode.
4:35 Alright, now we're going to use with_items
4:38 and this is how we can avoid creating multiple tasks
4:41 when we need to install multiple packages,
4:44 in our case, we only need to install a couple of packages
4:47 the first one will be python-virtualenv, the second one will be python3-dev.
4:52 What happens here is that with_items
4:55 think about it like it's plugged into the variable item
4:58 for the apt module, pretty much just a for loop
5:01 and this is the list of items that we're going to use
5:04 and it's going to run this task with each of these items.
5:07 Put that out of the way, let's enable our firewall, we can use the ufw module
5:13 we'll say allow port 22, and again we need to use become true
5:17 and now we can copy this a few times, this time http port 80
5:21 copy it again, https 443, and one more bit we need to write
5:27 is to actually enable the firewall, ufw module
5:34 and we're going to specify state enabled and become true.
5:37 There is something slightly different about the way that I wrote these tasks
5:40 compared to the ones we've seen so far.
5:43 What you'll see here is in this module this ufw,
5:45 the only thing we needed to specify here
5:47 is that our state should be enabled, here we only had a couple things
5:50 we need to specify, so instead of writing them on their own lines,
5:54 what we could do is we could say rule out and port 443,
5:59 this would work just fine, but if you're writing a bunch of tasks at once,
6:02 it's often easier just specify it all on a single line
6:05 and this is the format we would use, we would use
6:08 a key and equal sign and then the value,
6:10 rather than a key and then s colon and then the value.
6:14 So it's just another way that you can specify with Ansible in a more compact fashion
6:19 and we'll use them interchangeably throughout,
6:22 we don't need to edit the group vars all file, we probably should create a shell strip
6:26 just to make it easier for us to kick off this file, just like we did with init.sh.
6:30 So copy init.sh, or create a new file, and I just typically call it prod_deploy
6:36 so a production deployment, we'll modify prod_deploy,
6:40 and instead of initial_config, this will be deploy.yml,
6:43 we will use the same private key,
6:46 but the root will be deployer, as opposed to root.
6:49 Save that, let's give it a try, see if it works.
6:53 So we kick this off, looking good so far,
7:03 ok so we did run into an error here, so what seems to be the issue?
7:07 Well, the connection timed out, couldn't connect, that's kind of odd.
7:10 But if we go into hosts, one of the things is that I mistyped an IP address
7:16 and this happens frequently, take care if you are modifying files by hand
7:21 especially when you're typing out certain digits, this was 234 and it should be 243
7:27 little things like this can trip you up, so if it doesn't seem
7:30 like you're able to connect at all with Ansible,
7:33 double check the IP address or the host name,
7:36 make sure that your private key exists and that you are pointing to the correct one
7:40 and make sure that you're specifying the appropriate user name like deployer
7:43 if you have already locked down root.
7:45 Those are things that have often tripped me up as I am using Ansible.
7:48 Let's try this again.
7:50 Alright, now this time it looks like it was able to connect successfully.
7:53 Alright, looking good, now let's just make sure that we can connect to our server
7:56 because we did change the firewall rules, so again we'll just manually connect
8:00 to make sure everything looks good-
8:09 and it looks like we're still able to connect
8:12 even though we've got the firewall rules in place, awesome.
8:15 So now we have the start of our new deployment playbook,
8:18 and we can add new tasks, new files to it, build it up over the next few videos,
8:22 until we've got our completed deployment and our application is up and running.