WildCard SSL certificates with Letsencrypt in Azure App-Service

The default certificate manager in Azure App Service does not support wildcard domains. Letsencrypt offers free wildcard ssl certificates. This post will detail all the steps needed to enable WildCard SSL certificates with Letsencrypt in Azure App-Service. Its assumed that you already have:

We’ll be scripting the commands and baking them into a startup script, and a cron job.

DNS

Letsencrypt needs to verify that you are the owner of the domain when requesting wildcard certificates. The authorization takes place over DNS. The other authorization methods don’t work with wildcard ssl certs. There is a list of supported DNS providers which certbot can use to automatically create and remove the verification entries. Although Microsoft’s own DNS services are not supported by certbot, cloudflare is:

# install our certbot dns plugin, and our Nginx plugin
apt-get -y install python3-certbot-dns-cloudflare python-3-certbot-nginx
#verify that its working
certbot plugins

Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* dns-cloudflare
Description: Obtain certificates using a DNS TXT record (if you are using
Cloudflare for DNS).
Interfaces: Authenticator, Plugin
Entry point: dns-cloudflare =
certbot_dns_cloudflare._internal.dns_cloudflare:Authenticator

* standalone
Description: Spin up a temporary webserver
Interfaces: Authenticator, Plugin
Entry point: standalone = certbot._internal.plugins.standalone:Authenticator

* webroot
Description: Place files in webroot directory
Interfaces: Authenticator, Plugin
Entry point: webroot = certbot._internal.plugins.webroot:Authenticator
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

With certbot and the cloudflare plugins installed, provide some credentials to the plugin. Certbot creates DNS entries for verification automatically. We will store the cloudflare api token in our environment;

Get the API Token from Cloudflare

  • Login to Cloudflare
  • Go to Profile > Api Tokens
  • Generate a new api token
  • Use the ‘Edit Zone DNS’ template
  • in ‘Zone Resources’, select the domain you want to use for the wildcard certs
  • Click Continue
  • Take a note of the API Token

Add the token to Azure Environment

  • In Azure, go to Resources > App-Service
  • Select ‘Environment Variables’ from the left hand menu
  • Add a new variable, called ‘CLOUDFLARE_API_TOKEN’
  • Save and Apply

Your Startup Script

Assuming you have your CI/CD already configured and deploying to your app store, the next thing that needs to happen is to create a startup script (you can name it anything and put it anywhere in your repo, eg /startup.sh).

Next inside the startup script, add the following:

#!/bin/sh
echo "dns_cloudflare_api_token=${CLOUDFLARE_API_TOKEN}" > /home/site/wwwroot/certbot.ini

chmod 600 /home/site/wwwroot/certbot.ini

This means that you don’t have to commit your api token to a code repo, and that you can have different tokens for different slots, with each token being linked to a specific domain or set of domains.

Adding your Startup Script to the App-Service Configuration

  • Head over to: Azure > resources > App-service > configuration
  • In the “Startup Command” box add the following. [replace startup.sh with what your startup script is called]:
sh /home/site/wwwroot/startup.sh 

Save and apply, now your startup script is executed each time a new instance is created.

Getting the SSL cert from letsencrypt

Finally we have our app-service instance and can fetch our letsencrypt cert.

Replace *.example.com with your domain

certbot certonly \
  --agree-tos \  
  --no-eff-email \  
  --cert-name my-cert \
  --email 'user@example.com' \
  --dns-cloudflare \
  --dns-cloudflare-credentials /home/site/wwwroot/certbot-creds.ini \
  -d '*.example.com'

You should hopefully have a certificate downloaded! the next step is to install it so that nginx can use that certificate

certbot install \
  --nginx \
  --no-redirect \
  --cert-name my-cert \
  -d '*.example.com'

A few notes; along with the startup script, I have my own nginx config file which I drop in place, and I have the cert locations in that; it means I don’t have to run the certbot install command; I also have a couple of files in my repo [options-ssl-nginx.conf and ssl-dhparams.pem]

Auto Renewing the Certificate

In my startup script, I also have a cron task to run every day at 1am defined like this:

echo '0 1 * * * certbot -q renew' > /etc/cron.d/certbot

Adding it all together: the full startup script:

#!/bin/sh

# write key to ini file
echo "dns_cloudflare_api_token=${CLOUDFLARE_API_TOKEN}" > /home/site/wwwroot/certbot.ini

chmod 600 /home/site/wwwroot/certbot.ini

#install certbot-cloudflare
apt-get -y install python3-certbot-dns-cloudflare python3-certbot-nginx

certbot certonly \
  --agree-tos \
  --no-eff-email \
  --email 'user@example.com' \
  --cert-name my-cert \
  --dns-cloudflare \
  --dns-cloudflare-credentials ~/certbot-creds.ini \
  -d '*.example.com'

certbot install \  
  --nginx \  
  --no-redirect \  
  --cert-name my-cert \  
  -d '*.example.com'

echo '0 1 * * * certbot -q renew' > /etc/cron.d/certbot


Leave a Reply