certera-io / certera

A central validation server for Let's Encrypt certificates
https://docs.certera.io
Other
72 stars 14 forks source link

Certera + NGINX + Varnish #9

Closed AntonioCayulao closed 4 years ago

AntonioCayulao commented 4 years ago

Hi everyone, I need to add a certificate to one site that has NGINX + Varnish working. For example, if I do this using Certbot I have to do the following:

/etc/varnish/default.vcl:

sub vcl_recv {
  if (req.url ~ "^/\.well-known/acme-challenge/") {
    set req.backend_hint = certbot;
    return(pipe);
  }
}

sub vcl_pipe {
  if (req.backend_hint == certbot) {
    set req.http.Connection = "close";
    return(pipe);
  }
}

backend certbot {
  .host = "127.0.0.1";
  .port = "8089";
}

/etc/nginx/conf.d/example.conf

server {
  listen 8089;
  server_name_;

  location ^~ /.well-known/acme-challenge/ {
    allow all;
    default_type "text/plain";
    alias /srv/www/.well-known/acme-challenge/;
  }
}

The doc says that with Certera NGINX looks like this:

server {
  (...)
  location ^~ /.well-known/acme-challenge/ {
    default_type "text/plain";              
    rewrite /.well-known/acme-challenge/(.*) https://<your_certera_site_hostname>/.well-known/acme-challenge/$1 break;
  }
}

I don't know how to make this including Varnish software. Let's Encrypt has a limit to make a request by the hour, so I can't make a lot of tests until finding the right configuration. Can you help me, please? Greetings!

certeraio commented 4 years ago

Hi @AntonioCayulao,

The big thing to keep in mind is that the validation, obtaining and applying the certificate are all separate with Certera.

The docs outline two ways to perform validation: HTTP-01 and DNS-01. The snippet you referenced is for HTTP-01 validation. When a request comes from ACME servers to validate your domain, it will hit that /.well-known/acme-challenge/<token> endpoint. NGINX will then forward that request to Certera. Certera then responds to ACME and validates the request and takes care of obtaining and storing the certificate and keys.

Then, you need to figure out the best way to obtain the certificate from your Certera instance and apply it to wherever you want. If you have NGINX in front of Varnish, you can just configure NGINX to terminate your SSL connection and not have to do anything with SSL with regards to Varnish (if I understand it correctly).

Here's a script to get the certificate from your Certera instance and apply it to your NGINX that is a reverse proxy to your Varnish.

#!/bin/bash
echo "Starting certificate renewal check"
date
curl https://certera.mysite.com/api/certificate/varnish.mysite.com -H "apiKey:myCertS3cr3t" > /some/path/varnish.mysite.com.crt
curl https://certera.mysite.com/api/key/varnish.mysite.com -H "apiKey:myKeyS3cr3t" > /some/path/varnish.mysite.com.key

cert=$(openssl x509 -in /some/path/varnish.mysite.com.crt -noout -sha256 -fingerprint)
existingCert=$(sudo openssl x509 -in /etc/nginx/ssl/nginx.crt -noout -sha256 -fingerprint)

if [ "$cert" != "$existingCert" ]; then
  echo "New cert available"

  # Copy over existing cert & key
  cp /some/path/varnish.mysite.com.crt /etc/nginx/ssl/nginx.crt
  cp /some/path/varnish.mysite.com.key /etc/nginx/ssl/nginx.key

  # Reload nginx
  nginx -t && nginx -s reload
else
  echo "Cert not changed"
fi

You can easily modify & test the above to make sure things work. Then, set it to run daily using CRON.

With regards to the limits, I recommend using a staging Let's Encrypt certificate to make sure you have all of it ironed out. Then, simply change the values in the script to get the correct certificate once things are working.