Tutorials#

Issuing and renewing Let’s Encrypt TLS certificates via certbot#

This instruction describes how to issue and renew (including automatically) Let’s Encrypt TLS certificates (traditionally called SSL certificates) for domains in K2 Cloud. Domain ownership is verified through the DNS-01 challenge method. The verification record is placed in the domain’s DNS zone, using the Route53 API.

To issue and renew certificates, the certbot utility is used, which runs in a Docker container, allows for the issuance of wildcard certificates (among others) and does not require any web server configuration changes.

Prerequisites#

To configure the issuing of Let’s Encrypt TLS certificates, you will need:

  • a Linux instance with Docker installed and running;

  • API access settings;

  • a domain name registered in a public top-level zone (for example, .ru, .com, .net);

  • a public DNS zone for this domain, created in the K2 Cloud DNSaaS service;

  • a DNSaaS service configured to delegate this domain to DNS servers specified in the public DNS zone.

Note

The domain delegation is the responsibility of the domain registrar and is not covered by this instruction.

Note

To perform the actions, create a separate user and assign the policy Route53FullAccess to the user.

Configuring the environment#

  1. Create an .env file with the following content:

    $ nano ~/.env
    
    CERTBOT_VERSION=v3.0.1
    AWS_ACCESS_KEY_ID=${C2_PROJECT}:${BASE_ACCESS_KEY}
    AWS_SECRET_ACCESS_KEY=${EC2_SECRET_KEY}
    AWS_ENDPOINT_URL=https://route53.k2.cloud
    AWS_DEFAULT_REGION=ru-msk
    

    Note

    To ensure that certificates are issued correctly, specify values for the AWS_ENDPOINT_URL and AWS_DEFAULT_REGION environment variables.

    Use ru-msk as the value for the AWS_DEFAULT_REGION environment variable.

  2. Create a docker-compose.yml file with the following content:

    $ nano ~/docker-compose.yml
    
    services:
      certbot:
        image: certbot/dns-route53:${CERTBOT_VERSION}
        container_name: certbot
        environment:
          - AWS_ACCESS_KEY_ID=${C2_PROJECT}:${BASE_ACCESS_KEY}
          - AWS_SECRET_ACCESS_KEY=${EC2_SECRET_KEY}
          - AWS_ENDPOINT_URL=${ROUTE53_URL}
          - AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION}
        volumes:
          - certbot-etc:/etc/letsencrypt
    

    Note

    The values of the {C2_PROJECT}:${BASE_ACCESS_KEY}, {EC2_SECRET_KEY} and {ROUTE53_URL} variables are given in the API access settings file. This file can be obtained via the web interface. To do this, click on the user’s login in the upper right corner and select Profile Get API access settings.

Issuing a certificate#

To have a certificate issued, submit a request:

$ docker compose run --rm certbot certonly \
--dns-route53 \
--email admin@example.com \
--agree-tos \
--no-eff-email \
-d example.com \
-d '*.example.com'

Upon successful completion, the issued certificates will be saved to the ./letsencrypt/live/$domain/ directory:

  • fullchain.pem — the chain of certificates starting from the root one;

  • privkey.pem — the private key of the certificate.

If command execution returns an error, a message with error cause and resolution method will be displayed in the instance console.

Renewing a certificate#

Let’s Encrypt TLS certificates are valid for 90 days.

To have a certificate renewed, submit a request:

$ docker compose run --rm certbot renew

Auto-renewing a certificate#

To set up certificate auto-renewal:

  1. Open the cron editor:

    $ crontab -e
    
  2. Add the following string (replace paths and keys with your own ones):

    $ 0 3 * * * docker compose run --rm certbot renew \
    --quiet \
    --deploy-hook "docker restart nginx"
    

The cron expression 0 3 * * * sets the command run period to “every day at 3 AM”. To set a different run period, edit the expression as per the cron specification.

Note

If the --deploy-hook "docker restart nginx" parameter is specified, the web server will be restarted only if the certificate is successfully renewed. The docker restart nginx value in the example applies only if nginx is used as the web server. When using other web servers, adjust the parameter value accordingly.