Python for Entrepreneurs Transcripts
Chapter: Deploying to the cloud
Lecture: Let's encrypt

Login or purchase this course to watch this video and the rest of the course contents.
0:01 When our application is deployed and running we're going to want to make sure it's secure using an https connection;
0:07 that way our users can pass us information and we know it's going to be encrypted
0:11 from the time they entered into the browser, until it reaches our server. This is not only important, but mandatory
0:16 when you're using services such as Stripe, you don't want your users' credit card information to be leaked because of the insecure http protocol.
0:25 Now it used to be much more difficult to deploy secure applications because ssl certificate is more expensive.
0:32 If you'd go to a company like Digicert, and oftentimes pay a few hundred dollars a year to get an ssl certificate that was certified by a brand name,
0:41 that's all changed with a service called Let's Encrypt. As it says right on its home page, at,
0:48 Let's Encrypt is a free automated and open certificate authority a certificate authority grants the ssl certificates
0:56 that are used to create https connections if you self sign a certificate, and you don't use a certificate authority,
1:02 than a user in a web browser like Chrome is going to get a warning that the certificate was not issued by a certificate authority.
1:08 The certificate authority provides an additional stamp of approval that is accepted by all major browsers, as secure and generated via their process.
1:19 One of the great parts about Let's Encrypt other than the fact that it's free is the ability to automate obtaining certificates.
1:26 We're going to add this now to our Ansible playbook, switch back over to the command line where you've got your deployment scripts.
1:33 We're going to need a few new variables added to our group vars file. Go into group vars and edit the all file, the first thing we're going to need
1:41 is to specify or fully qualified domain name, now in my case, this is going to be
1:51 but you're going to put in your domain name that you registered and just set up in the last video, into the fully qualified domain name.
1:58 Second, we're going to need to specify the directory in which our web server is going to serve up static files like HTML and JavaScript, css;
2:07 we're going to use the default one that nginx is going to serve files from on Ubuntu "var/www/HTML"
2:15 and then one more bit we're going to use our email address that will be added to the certificate, so when we request the certificate
2:22 we're going to pass Let's Encrypt our email first off so that they have a contact, but second of all,
2:29 that is going to be added to a part of the certificate and we're going to call this ssl_cert_email in my case that'll be
2:39 Those are the three new variables we need for this chapter. Save the file, and then we're going to go back up
2:46 into our roles directory common, go under tasks and now we're going to write a new file, this one is going to be letsencrypt.yml
2:59 As always, we'll just add a simple comment up top, now we've got a few new tasks here.
3:06 The first one is going to be familiar to us, and that's going to be the apt module so use apt and the name here is going to be item,
3:15 because we're going to install more than one yes we want to update to the latest cache, we're going to become Super User when we do this
3:24 and we're going to install two packages, the first one will be letsencrypt, and the second one will be nginx.
3:31 The letsencrypt package has some command line utilities to make it really easy for us to in an automated way go and grab that certificate
3:40 and nginx is going to be the web server, which will serve up all of our static files and serve as what is known as a reverse proxy,
3:47 it's going to be a pass through where any requests that are supposed to go to your application nginx is going to pass them on
3:54 so pyramid can respond to those requests. Alright, the next module we're going to have is a new one and that's going to be the stat module,
4:04 think about the stat module as a check on something, as storing the state that we can use in conditional statements
4:11 throughout our Ansible playbook, and execute tasks or not execute tasks based on the results that come back from the state.
4:18 So we only want to grab the certificate, the first time that we need it
4:24 we don't want to get a new certificate every single time that we do our deployment we're only going to do it if the certificate does not exist.
4:31 The way we're going to check for that is we're going to check the letsencrypt directory when it's created
4:37 and it's going to put it under our fully qualified domain name and if that path exists, and we'll check for it later in the next few tasks
4:44 then we're not going to go ahead and get a new certificate, we're going to skip those steps. Again, we're going to use become true,
4:52 so this check as soon as we have finished installing, the first task with the letsencrypt and nginx packages,
4:59 we're then going to check if we already have the certificates based on the directory that was already set up for this application.
5:06 Alright, next up, were going to stop nginx because we can't use letsencrypt unless nginx has stopped.
5:16 And we'll give this the name of nginix for the service and the state should be stopped. We are going to need sudo privileges for this one,
5:28 and we're only going to stop nginx if the directory is not defined and it is not a directory, so the when condition here says
5:42 if the certificate directory that letsencrypt creates when it runs is not a directory, it's just not defined, and it's not a directory,
5:49 then we'll go ahead and run this step; otherwise, skip it, we've already got our certificate.
5:55 Next up, we're going to create the certificate with the Let's Encrypt command if we're going to use the shell module,
6:06 the shell module allows us to execute commands on the command line now we're going to pass a bunch of parameters in here
6:12 we're going to pass in our fully qualified domain name we're going to pass in the directory in which we want to serve files from
6:22 we're going to pass in our e mail address so these are all the variables that we just define in our group vars all file,
6:30 agree to the terms of service for Let's Encrypt and we'll renew the certificate by default when it expires. We will need to have sudo privileges here,
6:42 and we only want to do this again same thing as above we can actually just copy this and paste it if we don't already have the certificate.
6:54 Okay, so we use the shell command, so we drop down into bash and we just executed this command straightup on the shell
7:02 and the one thing to note is that there is actually a Let's Encrypt module as part of Ansible,
7:08 but it's in a very early state, and it's in a preview mode so it's likely that that module is going to change significantly over time
7:16 I just thought it was much easier to use the shell command and execute a single command rather than trying to use the Let's Encrypt module.
7:23 This is a trade-off you're sometimes going to make in your Ansible playbooks, sometimes it's just easier to do things with a shell command
7:28 now that's not going to necessarily be as maintainable as if you have a really clean module that's already been written
7:33 but occasionally this stuff can come up when there's a new module that's been added and it can change over time.
7:38 We just need to do two more things here, the first is, so now when we get our certificate we're going to generate a strong parameter for our ssl file
7:47 that is going to be used during the key exchange when a web browser contacts our web server, this is something we're only going to want to perform once
7:55 and it will actually take several minutes, even on the latest hardware in order to generate a file that will be used in the key exchange.
8:00 But this makes our handshake in https protocol more secure. Again I am going to drop down into the shell, use the open ssl command
8:09 and again we're only going to perform this when it's not already been done. One last command we need to boot nginx back up,
8:19 we can use the service module, save the file, now one more step, we need to go into main yml,
8:32 do the comment that is prepended to the line to include letsencrypt.yml, now we'll try to run this;
8:48 we've hit a snag as we wrote our files, so let's go back in and see unsupported parameters for the stat module-
8:57 go back in and check out what we just wrote. Now the issue here is that the indentation that I used is incorrect
9:06 this springs up a really good point about Ansible which is very sensitive to indentation, because the playbooks are based on yaml,
9:13 what we've said here incorrectly and the reason why Ansible ceased to run is because register and become are not arguments
9:22 that are passed to the stat module they need to be one level up, the first thing is we're registering
9:28 a state known as certs, and we need sudo privileges, because only sudo can access the directory that we're looking for,
9:37 so these are two arguments that are run with the stat module not arguments that are passed into the stat module,
9:45 we'll save that, and then move up a few directories, and we'll kick it off again. Once again, we ran into an issue, but we got past the previous one
9:57 that was causing us some trouble. We'll go back in, modify letsencrypt, so what we actually want to do here is,
10:05 we want to make sure we only run this when a directory does not exist so the way we can do that is with not certs.stat.exists
10:13 so sometimes we need to fiddle around a little bit with some of these conditions, just as we are more doing our programming
10:19 and make sure that it maps up to exactly what we would expect. So we can delete the rest of these, and just replace them with not certs.stat.exists.
10:32 Let's give this a try one more time.
10:49 This time it looks like everything ran fine, but the real test comes in when we take a look at our url.
10:58 Now the thing is that this is not actually configured for the url to work just yet, nginx is going to answer when something
11:06 contacts on port 80 directly through its IP address we have not set up nginx to handle our domain name just yet,
11:14 we'll do that in the next video, for now we can see that we can contact nginx through the IP address, so it is up and running
11:21 just by installing a package, but we need to tweak the configuration files now so that it will serve up via the domain name.

Talk Python's Mastodon Michael Kennedy's Mastodon