Question

Using cloud-init to automate the Let's Encrypt process on new Ubuntu/nginx droplets

Posted July 27, 2017 4.7k views
NginxUbuntuLet's Encrypt

Assuming you already have a top-level domain setup on DigitalOcean (e.g.: mysite.com) the script below will (for Ubuntu Droplets):

  1. Install nginx and Let’s Encrypt
  2. Create a DigitalOcean Floating IP pointing at the droplet.
  3. Update your top-level domain’s DNS record to point a new subdomain at the droplet, based on the droplet name.
  4. Use Let’s Encrypt (certbot) to generate SSL certs for the domain
  5. Setup a cron job to renew certs periodically.

Using cloud-config.

So if you paste this in to the User-Data section when creating a droplet named mydroplet and you have a domain mysite.com, you’ll end up with a properly configured https://mydroplet.mysite.com that gets an A on the SSLabs test.

The only thing you need to change in the script below is to set the DOAPITOKEN env variable to your token, and DOMAIN to the top-level domain you already have setup in the DO control panel.

#cloud-config
packages:
  - nginx
  #jq is a command-line json processor https://stedolan.github.io/jq/
  - jq
  - unattended-upgrades
runcmd:
  - export DOMAIN=your_domain_here.com
  - export DO_API_TOKEN=PASTE_YOUR_DIGITALOCEAN_API_TOKEN_HERE
  - export PUBLIC_IPV4=$(curl -s http://169.254.169.254/metadata/v1/interfaces/public/0/ipv4/address)
  - export DROPLET_ID=$(curl -s http://169.254.169.254/metadata/v1/id)
  - export DROPLET_NAME=$(curl -s http://169.254.169.254/metadata/v1/hostname)
  # get the email for letsencrypt from do api
  - 'export EMAIL=$(curl -X GET -H "Content-Type: application/json" -H "Authorization: Bearer $DO_API_TOKEN"  https://api.digitalocean.com/v2/account  | jq -r ".account.email")'
  # install certbot, update
  - add-apt-repository ppa:certbot/certbot -y
  - apt-get update
  - apt install python-certbot-nginx -y
  # add domain name to nginx config, restart it
  - sed -i 's/server_name _;/server_name '$DROPLET_NAME"."$DOMAIN';/' /etc/nginx/sites-available/default
  - systemctl restart nginx
  # create a floating ip
  - 'export FLOATING_IP=$(curl -X POST -H ''Content-Type: application/json'' -d ''{"droplet_id":"''"$DROPLET_ID"''"}'' -H "Authorization: Bearer $DO_API_TOKEN"  https://api.digitalocean.com/v2/floating_ips  | jq -r ".floating_ip.ip")'
  # create a subdomain a-record for this droplet
  - 'curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $DO_API_TOKEN" -d "{\"type\":\"A\", \"name\":\"$DROPLET_NAME\", \"data\":\"$FLOATING_IP\"}" https://api.digitalocean.com/v2/domains/$DOMAIN/records'
  - sleep 30s
  - certbot --nginx -n -d $DROPLET_NAME"."$DOMAIN --email $EMAIL --agree-tos --redirect --hsts
  - systemctl reboot
# add renewal cron
write_files:
  - owner: root:root
    path: /etc/cron.d/letsencrypt_renew
    content: "15 3 * * * /usr/bin/certbot renew --quiet"
1 comment
  • Can you do this for a LAMP stack? For example, let’s say I already have a domain pointing to DO nameservers and have added it inside of DO. How can I enable it in cloud-init and then do the Let’s Encrypt SSL with Apache instead of ngix. Thank you

Submit an answer

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!