One place for hosting & domains

      Acquire

      How To Acquire a Let’s Encrypt Certificate Using DNS Validation with acme-dns-certbot on Ubuntu 18.04


      The author selected the COVID-19 Relief Fund to receive a donation as part of the Write for DOnations program.

      Introduction

      The majority of Let’s Encrypt certificates are issued using HTTP validation, which allows for the easy installation of certificates on a single server. However, HTTP validation is not always suitable for issuing certificates for use on load-balanced websites, nor can it be used to issue wildcard certificates.

      DNS validation allows for certificate issuance requests to be verified using DNS records, rather than by serving content over HTTP. This means that certificates can be issued simultaneously for a cluster of web servers running behind a load balancer, or for a system that isn’t directly accessible over the internet. Wildcard certificates are also supported using DNS validation.

      The acme-dns-certbot tool is used to connect Certbot to a third-party DNS server where the certificate validation records can be set automatically via an API when you request a certificate. The advantage of this is that you don’t need to integrate Certbot directly with your DNS provider account, nor do you need to grant it unrestricted access to your full DNS configuration, which is beneficial to security.

      Delegated DNS zones are used in order to redirect lookups for the certificate verification records to the third-party DNS service, so once the initial setup has been completed, you can request as many certificates as you want without having to perform any manual validation.

      Another key benefit of acme-dns-certbot is that it can be used to issue certificates for individual servers that may be running behind a load balancer, or are otherwise not directly accessible over HTTP. Traditional HTTP certificate validation cannot be used in these cases, unless you set the validation files on each and every server. The acme-dns-certbot tool is also useful if you want to issue a certificate for a server that isn’t accessible over the internet, such as an internal system or staging environment.

      In this tutorial, you will use the acme-dns-certbot hook for Certbot to issue a Let’s Encrypt certificate using DNS validation.

      Prerequisites

      To complete this tutorial, you will need:

      • An Ubuntu 18.04 server set up by following the Initial Server Setup with Ubuntu 18.04, including a sudo non-root user.

      • A domain name for which you can acquire a TLS certificate, including the ability to add DNS records. In this particular example, we will use your-domain and subdomain.your-domain, as well as *.your-domain for a wildcard certificate. However this can be adjusted for other domain, subdomains, or wildcards if required.

      Once you have these ready, log in to your server as your non-root user to begin.

      Step 1 — Installing Certbot

      In this step, you will install Certbot, which is a program used to issue and manage Let’s Encrypt certificates.

      Certbot is available within the official Ubuntu Apt repositories, however, it is instead recommended to use the repository maintained by the Certbot developers, as this always has the most up-to-date version of the software.

      Begin by adding the Certbot repository:

      • sudo apt-add-repository ppa:certbot/certbot

      You’ll need to press ENTER to accept the prompt and add the new repository to your system.

      Next, install the Certbot package:

      Once the installation has completed, you can check that Certbot has been successfully installed:

      This will output something similar to the following:

      Output

      certbot 0.31.0

      In this step you installed Certbot. Next, you will download and install the acme-dns-certbot hook.

      Step 2 — Installing acme-dns-certbot

      Now that the base Certbot program has been installed, you can download and install acme-dns-certbot, which will allow Certbot to operate in DNS validation mode.

      Begin by downloading a copy of the script:

      • wget https://github.com/joohoi/acme-dns-certbot-joohoi/raw/master/acme-dns-auth.py

      Once the download has completed, mark the script as executable:

      • chmod +x acme-dns-auth.py

      Then, edit the file using your favorite text editor and adjust the first line in order to force it to use Python 3:

      Add a 3 to the end of the first line:

      acme-dns-certbot.py

      #!/usr/bin/env python3
      . . .
      

      This is required in order to ensure that the script uses the latest supported version of Python 3, rather than the legacy Python version 2.

      Once complete, save and close the file.

      Finally, move the script into the Certbot Let’s Encrypt directory so that Certbot can load it:

      • sudo mv acme-dns-auth.py /etc/letsencrypt/

      In this step, you downloaded and installed the acme-dns-certbot hook. Next, you can begin the setup process and work toward issuing your first certificate.

      Step 3 — Setting Up acme-dns-certbot

      In order to begin using acme-dns-certbot, you’ll need to complete an initial setup process and issue at least one certificate.

      Start by running Certbot to force it to issue a certificate using DNS validation. This will run the acme-dns-certbot script and trigger the initial setup process:

      • sudo certbot certonly --manual --manual-auth-hook /etc/letsencrypt/acme-dns-auth.py --preferred-challenges dns --debug-challenges -d *.your-domain -d your-domain

      You use the --manual argument to disable all of the automated integration features of Certbot. In this case you’re just issuing a raw certificate, rather than automatically installing it on a service as well.

      You configure Certbot to use the acme-dns-certbot hook via the --manual-auth-hook argument. You run the --preferred-challenges argument so that Certbot will give preference to DNS validation.

      You must also tell Certbot to pause before attempting to validate the certificate, which you do with the --debug-challenges argument. This is to allow you to set the DNS CNAME record(s) required by acme-dns-certbot, which is covered later in this step. Without the --debug-challenges argument, Certbot wouldn’t pause, so you wouldn’t have time to make the required DNS change.

      Remember to substitute each of the domain names that you wish to use using -d arguments. If you want to issue a wildcard certificate, make sure to escape the asterisk (*) with a backslash ().

      After following the standard Certbot steps, you’ll eventually be prompted with a message similar to the following:

      Output

      ... Output from acme-dns-auth.py: Please add the following CNAME record to your main DNS zone: _acme-challenge.your-domain CNAME a15ce5b2-f170-4c91-97bf-09a5764a88f6.auth.acme-dns.io. Waiting for verification... ...

      You’ll need to add the required DNS CNAME record to the DNS configuration for your domain. This will delegate control of the _acme-challenge subdomain to the ACME DNS service, which will allow acme-dns-certbot to set the required DNS records to validate the certificate request.

      If you’re using DigitalOcean as your DNS provider, you can set the DNS record within your control panel:

      A screenshot of the DigitalOcean DNS control panel, showing an example of a CNAME record for ACME DNS

      It is recommended to set the TTL (time-to-live) to around 300 seconds in order to help ensure that any changes to the record are propagated quickly.

      Once you have configured the DNS record, return to Certbot and press ENTER to validate the certificate request and complete the issuance process.

      This will take a few seconds, and you’ll then see a message confirming that the certificate has been issued:

      Output

      ... Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/your-domain/fullchain.pem Your key file has been saved at: /etc/letsencrypt/live/your-domain/privkey.pem ...

      You’ve run acme-dns-certbot for the first time, set up the required DNS records, and successfully issued a certificate. Next you’ll set up automatic renewals of your certificate.

      Step 4 — Using acme-dns-certbot

      In this final step, you will use acme-dns-certbot to issue more certificates and renew existing ones.

      Firstly, now that you’ve successfully issued at least one certificate using acme-dns-certbot, you can continue to issue certificates for the same DNS names without having to add another DNS CNAME record. However, if you wish to acquire a certificate for a different subdomain or entirely new domain name, you will be prompted to add another CNAME record.

      For example, you could issue another standalone wildcard certificate without having to perform the verification again:

      • sudo certbot certonly --manual --manual-auth-hook /etc/letsencrypt/acme-dns-auth.py --preferred-challenges dns --debug-challenges -d *.your-domain

      However, if you were to attempt to issue a certificate for a subdomain, you would be prompted to add a CNAME record for the subdomain:

      • sudo certbot certonly --manual --manual-auth-hook /etc/letsencrypt/acme-dns-auth.py --preferred-challenges dns --debug-challenges -d subdomain.your-domain

      This will show an output similar to the initial setup that you carried out in Step 3:

      Output

      ... Please add the following CNAME record to your main DNS zone: _acme-challenge.subdomain.your-domain CNAME 8450fb54-8e01-4bfe-961a-424befd05088.auth.acme-dns.io. Waiting for verification... ...

      Now that you’re able to use acme-dns-certbot to issue certificates, it’s worth considering the renewal process as well.

      Once your certificates are nearing expiry, Certbot can automatically renew them for you:

      The renewal process can run start-to-finish without user interaction, and will remember all of the configuration options that you specified during the initial setup.

      To test that this is working without having to wait until nearer the expiry date, you can trigger a dry run. This will simulate the renewal process without making any actual changes to your configuration.

      You can trigger a dry run using the standard renew command, but with the --dry-run argument:

      • sudo certbot renew --dry-run

      This will output something similar to the following, which will provide assurance that the renewal process is functioning correctly:

      Output

      ... Cert not due for renewal, but simulating renewal for dry run Plugins selected: Authenticator manual, Installer None Renewing an existing certificate Performing the following challenges: dns-01 challenge for your-domain dns-01 challenge for your-domain Waiting for verification... Cleaning up challenges ...

      In this final step, you issued another certificate and then tested the automatic renewal process within Certbot.

      Conclusion

      In this article you set up Certbot with acme-dns-certbot in order to issue certificates using DNS validation. This unlocks the possibility of using wildcard certificates as well as managing a large estate of distinct web servers that may be sitting behind a load balancer.

      Make sure to keep an eye on the acme-dns-certbot repository for any updates to the script, as it’s always recommended to run the latest supported version.

      If you’re interested in learning more about acme-dns-certbot, you may wish to review the documentation for the acme-dns project, which is the server-side element of acme-dns-certbot:

      The acme-dns software can also be self-hosted, which may be beneficial if you’re operating in high-security or complex environments.

      Alternatively, you could dig into the technical details of ACME DNS validation by reviewing the relevant section of the official RFC document which outlines how the process works:



      Source link

      How To Acquire a Let’s Encrypt Certificate Using Ansible on Ubuntu 18.04


      The author selected the Electronic Frontier Foundation to receive a donation as part of the Write for DOnations program.

      Introduction

      Modern infrastructure management is best done using automated processes and tools. Acquiring a Let’s Encrypt certificate using the standard Certbot client is quick and easy, but is generally a task that has to be done manually when commissioning servers. This is manageable for an individual server setup, but can become tedious when deploying a larger fleet.

      Using a configuration management tool such as Ansible to acquire a certificate makes this task completely automatic and reproducible. If you ever have to rebuild or update your server, you can just run your Ansible playbook, rather than having to manually carry out the steps again.

      In this tutorial, you’ll write an Ansible playbook to acquire a Let’s Encrypt certificate automatically for an Ansible host machine.

      Prerequisites

      To complete this tutorial, you will need:

      The first server will be used as your Ansible server, which we will call Ansible server throughout this tutorial. This is where Ansible will run to send the commands to the host machine. Alternatively, you can use your local machine or any other machine that has your Ansible inventory configured as your Ansible server.

      On your Ansible server, you’ll need:

      The second server will be used as your Ansible host, which we will call the host machine throughout this tutorial. This is the machine that you wish to configure and issue certificates on. This machine will also run a web server to serve the certificate issuance validation files.

      On your host machine, you’ll need:

      • A domain name that you are eligible to acquire a TLS certificate for, with the required DNS records configured to point to your Ansible host machine. In this particular example, the playbook will acquire a certificate valid for your-domain and www.your-domain, however it can be adjusted for other domains or subdomains if required.

      • A web server that is accessible from the internet over port 80 (HTTP), for example by following steps 1, 2, and 3 of How To Install the Apache Web Server on Ubuntu 18.04. This could also be an Nginx server, or any other suitable web server software.

      Once you have these ready, log in to your Ansible server as your non-root user to begin.

      Step 1 — Configuring the Settings for the Let’s Encrypt Ansible Module

      Ansible has a built-in module named letsencrypt, which allows you to acquire valid TLS certificates using the ACME (Automated Certificate Management Environment) protocol.

      In this first step, you will add a host variables configuration file to define the configuration variables that are required to use the module.

      Note: The letsencrypt module has been renamed to acme_certificate as of Ansible 2.6. The letsencrypt name is now an alias of acme_certificate, so will still work, but you way wish to use acme_certificate instead, to ensure future-proofness of your playbooks. You can check your Ansible version using ansible --version. As of the writing of this tutorial, the Ubuntu 18.04 Apt repositories don’t support acme_certificate yet.

      Firstly, create the host_vars Ansible directory on your Ansible server:

      • sudo mkdir /etc/ansible/host_vars

      Next, create a new file in the /etc/ansible/host_vars directory with the name of your Ansible host machine. In this example, you’ll use host1 as the name of the host:

      • sudo nano /etc/ansible/host_vars/host1

      The following sample configuration includes everything you need to get started, including: the validation method and server address, an email address to receive certificate expiry reminders to, and the directories where your Let’s Encrypt keys and certificates will be saved.

      Copy the sample configuration into the file:

      /etc/ansible/host_vars/host1

      ---
      acme_challenge_type: http-01
      acme_directory: https://acme-v02.api.letsencrypt.org/directory
      acme_version: 2
      acme_email: certificate-reminders@your-domain
      letsencrypt_dir: /etc/letsencrypt
      letsencrypt_keys_dir: /etc/letsencrypt/keys
      letsencrypt_csrs_dir: /etc/letsencrypt/csrs
      letsencrypt_certs_dir: /etc/letsencrypt/certs
      letsencrypt_account_key: /etc/letsencrypt/account/account.key
      domain_name: your-domain
      

      Save and close the file when you’ve finished.

      Adjust the domain name and email address as required. You can use any email address—it doesn’t have to be the one on your-domain.

      Some of the directory/file paths defined may not actually exist on your server yet. This is OK; the first part of the playbook will be to create these directories and assign the relevant permissions.

      You’ve added the required configuration variables to your Ansible inventory file. Next, you will begin writing the playbook to acquire a certificate.

      Step 2 — Creating the Let’s Encrypt Directories and Account Key

      In this step, you’ll write the Ansible tasks that you’ll use to create the required Let’s Encrypt directories, assign the correct permissions, and generate a Let’s Encrypt account key.

      Firstly, create a new playbook named letsencrypt-issue.yml on your Ansible server in a new directory of your choice, for example /home/user/ansible-playbooks:

      • cd ~
      • mkdir ansible-playbooks
      • cd ansible-playbooks
      • nano letsencrypt-issue.yml

      Before you can start writing Ansible tasks, you’ll need to specify the hosts and associated settings. Adjust the following according to how you referred to your hosts in the prerequisite tutorial. Then add the following to the top of the file:

      letsencrypt-issue.yml

      ---
      - hosts: "host1"
        tasks:
      

      Now you can begin writing the required tasks, the first of which is to create the file system directories required to store the Let’s Encrypt files. Add the following Ansible task to the file after the previous content:

      letsencrypt-issue.yml

      ...
        - name: "Create required directories in /etc/letsencrypt"
          file:
            path: "/etc/letsencrypt/{{ item }}"
            state: directory
            owner: root
            group: root
            mode: u=rwx,g=x,o=x
          with_items:
          - account
          - certs
          - csrs
          - keys
      

      This Ansible task will create the account, certs, csrs, and keys directories in /etc/letsencrypt, which is where the files required for acquiring certificates will be stored.

      You set the owner of the directories to root and apply the permissions u=rwx,g=x,o=x so that only root has read and write access to them. This is recommended as the directories will contain private keys, certificate signing requests (CSRs), and signed certificates, which should be kept confidential.

      Next, the Let’s Encrypt account key needs to be created. You’ll use this to identify yourself to the Let’s Encrypt service.

      Add the following task to your playbook:

      letsencrypt-issue.yml

      ...
        - name: "Generate a Let's Encrypt account key"
          shell: "if [ ! -f {{ letsencrypt_account_key }} ]; then openssl genrsa 4096 | sudo tee {{ letsencrypt_account_key }}; fi"
      

      The account key doesn’t need to be re-created every time you renew the certificates, so you also add a check for an existing key if [ ! -f {{ letsencrypt_account_key }} ];, to make sure that it isn’t overwritten.

      You’ll continue to work in letsencrypt-issue.yml in the next step, so don’t close this file yet.

      You’ve created your playbook and set up the initial configuration and tasks in order to prepare for acquiring your Let’s Encrypt certificate. Next, you will add further tasks for the private key and CSR generation.

      Step 3 — Generating Your Private Key and Certificate Signing Request

      In this step, you’ll write the playbook tasks to generate the required private key and certificate signing request.

      The first task in this section will generate the required private key for your certificate. Add the following to the end of your playbook that you started writing in Step 2:

      letsencrypt-issue.yml

      ...
        - name: "Generate Let's Encrypt private key"
          shell: "openssl genrsa 4096 | sudo tee /etc/letsencrypt/keys/{{ domain_name }}.key"
      

      Subdomains on the same domain will all be added to the same certificate through the use of Subject Alternate Names (SANs), so you only need to generate one private key for now.

      You’ll use the next task to generate a Certificate Signing Request (CSR) for the certificate that you want to acquire. This is submitted to Let’s Encrypt in order for them to validate and issue each certificate.

      Add the following to the end of the playbook:

      letsencrypt-issue.yml

      ...
        - name: "Generate Let's Encrypt CSR"
          shell: "openssl req -new -sha256 -key /etc/letsencrypt/keys/{{ domain_name }}.key -subj "/CN={{ domain_name }}" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "n[SAN]nsubjectAltName=DNS:{{ domain_name }},DNS:www.{{ domain_name }}")) | sudo tee /etc/letsencrypt/csrs/{{ domain_name }}.csr"
          args:
            executable: /bin/bash
      

      This task generates a CSR for your domain, with the www subdomain added to the certificate as a SAN.

      You’ll continue to work in letsencrypt-issue.yml in the next step, so don’t close this file yet.

      You’ve written the Ansible tasks to generate the private key and CSR for your certificate. Next, you’ll work on the tasks that will begin the validation and issuance process.

      Step 4 — Starting the ACME Validation Process

      In this step, you’ll write a task to submit the Certificate Signing Request to Let’s Encrypt using the outputted files from the task documented in Step 3. This will return some challenge files, which you’ll need to serve on your web server in order to prove ownership of the domain name and subdomain for which you’re requesting a certificate.

      The following task will submit the CSR for your-domain. Add it to the end of your playbook:

      letsencrypt-issue.yml

      ...
        - name: "Begin Let's Encrypt challenges"
          letsencrypt:
            acme_directory: "{{ acme_directory }}"
            acme_version: "{{ acme_version }}"
            account_key_src: "{{ letsencrypt_account_key }}"
            account_email: "{{ acme_email }}"
            terms_agreed: 1
            challenge: "{{ acme_challenge_type }}"
            csr: "{{ letsencrypt_csrs_dir }}/{{ domain_name }}.csr"
            dest: "{{ letsencrypt_certs_dir }}/{{ domain_name }}.crt"
            fullchain_dest: "{{ letsencrypt_certs_dir }}/fullchain_{{ domain_name }}.crt"
            remaining_days: 91
          register: acme_challenge_your_domain
      

      This task makes wide usage of the variables that you configured in Step 1. It registers a variable containing the ACME challenge files that you’ll use in the next step. You’ll need to manually adjust the name of the variable to contain your-domain, but with all . characters replaced with a _, as dots cannot be used in a variable name. For example, the variable for example.com would become acme_challenge_example_com.

      You’ll continue to work in letsencrypt-issue.yml in the next step, so don’t close this file yet.

      You’ve written a task to submit your CSR to Let’s Encrypt. Next, you will add a task to implement the ACME challenge files for finalization of the certificate validation process.

      Step 5 — Implementing the ACME Challenge Files

      In this step, you will write an Ansible task to read and implement the ACME challenge files. These files prove that you’re eligible to acquire a certificate for the requested domains and subdomains.

      The ACME challenge files must be served on a web server listening on port 80, at the /.well-known/acme-challenge/ path for the domain or subdomain that you’re requesting a certificate for. For example, in order to validate the certificate request for www.your-domain, the ACME challenge file will need to be accessible over the internet at the following path: http://www.your-domain/.well-known/acme-challenge.

      The method for serving these files at the required destinations will vary significantly depending on your current web server setup. However, in this guide, we will assume that you have a web server (as per the prerequisite tutorial) configured to serve files out of the /var/www/html directory. Therefore you may need to adjust the task accordingly in order to be compatible with your own web server setup.

      Firstly, add the following task that creates the .well-known/acme-challenge/ directory structure required to serve the files to the end of your playbook:

      letsencrypt-issue.yml

      ...
        - name: "Create .well-known/acme-challenge directory"
          file:
            path: /var/www/html/.well-known/acme-challenge
            state: directory
            owner: root
            group: root
            mode: u=rwx,g=rx,o=rx
      

      Make sure to adjust the path accordingly if you are using a directory other than /var/www/html to serve files with your web server.

      Next, you’ll implement the ACME challenge files that were saved into the acme_challenge_your-domain variable in Step 4 with the following task:

      letsencrypt-issue.yml

      ...
        - name: "Implement http-01 challenge files"
          copy:
            content: "{{ acme_challenge_your_domain['challenge_data'][item]['http-01']['resource_value'] }}"
            dest: "/var/www/html/{{ acme_challenge_your_domain['challenge_data'][item]['http-01']['resource'] }}"
            owner: root
            group: root
            mode: u=rw,g=r,o=r
          with_items:
          - "{{ domain_name }}"
          - "www.{{ domain_name }}"
      

      Note that you need to manually adjust the acme_challenge_your_domain variable name in the task to be set to the name of your ACME challenge variable, which is acme_challenge_ followed by your domain name, but with all . characters replaced with _. This Ansible task copies the ACME validation files from the variable into the .well-known/acme-challenge path on your web server. This will allow Let’s Encrypt to retrieve them in order to verify the ownership of the domain and your eligibility to acquire a certificate.

      You’ll continue to work in letsencrypt-issue.yml in the next step, so don’t close this file yet.

      You’ve written the Ansible tasks required to create the ACME validation directory and files. Next, you will complete the ACME verification process and acquire the signed certificate.

      Step 6 — Acquiring Your Certificate

      In this step, you’ll write a task to trigger Let’s Encrypt to verify the ACME challenge files that you submitted, which will allow you to acquire your signed certificate(s).

      The following task validates the ACME challenge files that you implemented in Step 5 and saves your signed certificates to the specified paths. Add it to the end of your playbook:

      letsencrypt-issue.yml

      ...
        - name: "Complete Let's Encrypt challenges"
          letsencrypt:
            acme_directory: "{{ acme_directory }}"
            acme_version: "{{ acme_version }}"
            account_key_src: "{{ letsencrypt_account_key }}"
            account_email: "{{ acme_email }}"
            challenge: "{{ acme_challenge_type }}"
            csr: "{{ letsencrypt_csrs_dir }}/{{ domain_name }}.csr"
            dest: "{{ letsencrypt_certs_dir }}/{{ domain_name }}.crt"
            chain_dest: "{{ letsencrypt_certs_dir }}/chain_{{ domain_name }}.crt"
            fullchain_dest: "{{ letsencrypt_certs_dir }}/fullchain_{{ domain_name }}"
            data: "{{ acme_challenge_your_domain }}"
      

      Similarly to Step 4, this task makes use of the variables that you configured in Step 1. Once the task has completed, it will save the signed certificate to the specified paths, allowing you to begin using it for your application or service.

      Note that you’ll need to manually adjust the data value in the task to be set to the name of your ACME challenge variable, similarly to Step 5.

      Following is the full playbook showing each of the tasks you’ve added:

      letsencrypt-issue.yml

      - hosts: "host1"
        tasks:
      
        - name: "Create required directories in /etc/letsencrypt"
          file:
            path: "/etc/letsencrypt/{{ item }}"
            state: directory
            owner: root
            group: root
            mode: u=rwx,g=x,o=x
          with_items:
          - account
          - certs
          - csrs
          - keys
      
        - name: "Generate a Let's Encrypt account key"
          shell: "if [ ! -f {{ letsencrypt_account_key }} ]; then openssl genrsa 4096 | sudo tee {{ letsencrypt_account_key }}; fi"
      
        - name: "Generate Let's Encrypt private key"
          shell: "openssl genrsa 4096 | sudo tee /etc/letsencrypt/keys/{{ domain_name }}.key"
      
        - name: "Generate Let's Encrypt CSR"
          shell: "openssl req -new -sha256 -key /etc/letsencrypt/keys/{{ domain_name }}.key -subj "/CN={{ domain_name }}" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "n[SAN]nsubjectAltName=DNS:{{ domain_name }},DNS:www.{{ domain_name }}")) | sudo tee /etc/letsencrypt/csrs/{{ domain_name }}.csr"
          args:
            executable: /bin/bash
      
        - name: "Begin Let's Encrypt challenges"
          letsencrypt:
            acme_directory: "{{ acme_directory }}"
            acme_version: "{{ acme_version }}"
            account_key_src: "{{ letsencrypt_account_key }}"
            account_email: "{{ acme_email }}"
            terms_agreed: 1
            challenge: "{{ acme_challenge_type }}"
            csr: "{{ letsencrypt_csrs_dir }}/{{ domain_name }}.csr"
            dest: "{{ letsencrypt_certs_dir }}/{{ domain_name }}.crt"
            fullchain_dest: "{{ letsencrypt_certs_dir }}/fullchain_{{ domain_name }}.crt"
            remaining_days: 91
          register: acme_challenge_your_domain
      
        - name: "Create .well-known/acme-challenge directory"
          file:
            path: /var/www/html/.well-known/acme-challenge
            state: directory
            owner: root
            group: root
            mode: u=rwx,g=rx,o=rx
      
        - name: "Implement http-01 challenge files"
          copy:
            content: "{{ acme_challenge_your_domain['challenge_data'][item]['http-01']['resource_value'] }}"
            dest: "/var/www/html/{{ acme_challenge_your_domain['challenge_data'][item]['http-01']['resource'] }}"
            owner: root
            group: root
            mode: u=rw,g=r,o=r
          with_items:
          - "{{ domain_name }}"
          - "www.{{ domain_name }}"
      
        - name: "Complete Let's Encrypt challenges"
          letsencrypt:
            acme_directory: "{{ acme_directory }}"
            acme_version: "{{ acme_version }}"
            account_key_src: "{{ letsencrypt_account_key }}"
            account_email: "{{ acme_email }}"
            challenge: "{{ acme_challenge_type }}"
            csr: "{{ letsencrypt_csrs_dir }}/{{ domain_name }}.csr"
            dest: "{{ letsencrypt_certs_dir }}/{{ domain_name }}.crt"
            chain_dest: "{{ letsencrypt_certs_dir }}/chain_{{ domain_name }}.crt"
            fullchain_dest: "{{ letsencrypt_certs_dir }}/fullchain_{{ domain_name }}"
            data: "{{ acme_challenge_your_domain }}"
      

      Save and close your file when you’re finished.

      You’ve added the task to complete the ACME challenges and acquire your signed certificate. Next, you’ll run the playbook against your Ansible host machine in order to run all of the actions.

      Step 7 — Running Your Playbook

      Now that you’ve written the playbook and all of the required tasks, you can run it against your Ansible host machine to issue the certificate.

      From your Ansible server, you can run the playbook using the ansible-playbook command:

      • ansible-playbook letsencrypt-issue.yml

      This will run the playbook, one task at a time. You’ll see output similar to the following:

      Output

      PLAY [host1] ********************************************************************************** TASK [Gathering Facts] ************************************************************************ ok: [host1] TASK [Create required directories in /etc/letsencrypt] **************************************** changed: [host1] => (item=account) changed: [host1] => (item=certs) changed: [host1] => (item=csrs) changed: [host1] => (item=keys) TASK [Generate a Let's Encrypt account key] *************************************************** changed: [host1] TASK [Generate Let's Encrypt private key] ***************************************************** changed: [host1] TASK [Generate Let's Encrypt CSR] ************************************************************* changed: [host1] TASK [Begin Let's Encrypt challenges] ********************************************************* changed: [host1] TASK [Create .well-known/acme-challenge directory] ******************************************** changed: [host1] TASK [Implement http-01 challenge files] ****************************************************** changed: [host1] => (item=your-domain) changed: [host1] => (item=www.your-domain) TASK [Complete Let's Encrypt challenges] ****************************************************** changed: [host1] PLAY RECAP ************************************************************************************ host1 : ok=9 changed=8 unreachable=0 failed=0

      If any errors are encountered while the playbook is running, these will be outputted for your review.

      Once the playbook has finished, your valid Let’s Encrypt certificate will be saved to the /etc/letsencrypt/certs directory on your host machine. You can then use this, along with the private key in /etc/letsencrypt/keys, to secure connections to your web server, mail server, etc.

      Let’s Encrypt certificates are valid for 90 days by default. You will receive renewal reminders via email to the address that you specified in Step 1. To renew your certificate, you can run the playbook again. Make sure to double check that any services using your certificate have picked up the new one, as sometimes you may need to manually install it, move it to a particular directory, or restart the service for it to properly adopt the new certificate.

      In this step, you ran your playbook which issued your valid Let’s Encrypt certificate.

      Conclusion

      In this article you wrote an Ansible playbook to request and acquire a valid Let’s Encrypt certificate.

      As a next step, you can look into using your new playbook to issue certificates for a large fleet of servers. You could even create a central ACME validation server that can issue certificates centrally and distribute them out to web servers.

      Finally, if you’d like to learn more about the ACME specification and Let’s Encrypt project, you may wish to review the following links:

      You may also like to view some other relevant Ansible tutorials:



      Source link