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 in Azure App-Service. Its assumed that you already have:
- A linux app-service running
- CI/CD setup either from Azure Devops, Github Actions or similar
- DNS controlled by a supported certbot DNS provider (I’ll be using cloudflare in the example)
- Have wildcard subdomains working on your azure App-Service
- You are using Nginx
We’ll be scripting the commands and baking them into a startup script, and a cron job. This will give us wildcard SSL certificates with Letsencrypt in Azure App-Service!
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 WildCard SSL certificates with Letsencrypt in Azure App-Service 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 WildCard SSL certificates with Letsencrypt in Azure App-Service
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 WildCard SSL certificates with Letsencrypt in Azure App-Service
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 WildCard SSL certificates with Letsencrypt in Azure App-Service 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