By Ghouse Mohamed
Generating SSL certificates using Let's Encrypt and Certbot has long been the norm. It is often used as a default choice when it comes to generating SSL certificates. Certbot makes it intuitive and seamless to generate SSL certificates for any site we wish.
What if we wanted to generate SSL certificates on the fly, entirely automating the generation of such certificates on-demand. This is made possible using Openresty as a webserver.
Openresty is a superset of Nginx, with many carefully written Lua Libraries, and 3rd party Nginx modules. It is designed to help developers build dynamic web gateways, web services and web applications. Openresty turns the nginx server into a powerful app, using the Lua programming language underneath to script various existing nginx C modules. They are highly performant servers capable of handling 10k ~ 1000k+ connections in a single box. Applications of Openresty include building dynamic web portals, web gateways, web application firewalls and dynamic web sites.
We will be using lua-resty-auto-ssl plugin for openresty to handle SSL registrations and renewal inside Openresty with Let's encrypt. This OpenResty plugin automatically and transparently issues SSL certificates from Let's Encrypt as requests are received.
This is how a typical request lifecycle would look like using this plugin:
Let's make sure we have certbot installed:
sudo apt-get update
apt install certbot
Now that we have certbot installed, we can proceed with the openresty installation.
Import GCP key from official openresty server:
wget -qO - https://openresty.org/package/pubkey.gpg | sudo apt-key add -
Add openresty repository using the GCP key. After installing the software-properties-common
sudo apt-get -y install software-properties-common
and run,
sudo add-apt-repository -y "deb http://openresty.org/package/ubuntu $(lsb_release -sc) main"
Install openresty using apt
sudo apt-get install openresty
Run sudo service openresty start
to start the Openresty service.
Visit the server's public IP address to check if Openresty was successfully installed. You should get a screen looking like this:
If you already have Nginx running, then you might have to disable and stop the already running Nginx service like so:
sudo systemctl disable nginx
sudo systemctl stop nginx
Now that we have Openresty running as a service, we can go ahead and install LuaRocks, and the associated openresty plugin
lua-resty-auto-ssl
which we are using to auto generate our SSL certificates.
Run these commands to install LuaRocks and lua-resty-auto-ssl
sudo apt-get install -y luarocks
sudo apt-get install -y luarocks
sudo luarocks install lua-resty-auto-ssl
After running these commands in your terminal you should see this:
1
You should see this : lua-resty-auto-ssl 0.13.1-1 is now installed in /usr/local (license: MIT)
First let's create a directory where the regular and fallback certificates can be stored
sudo mkdir /etc/resty-auto-ssl
After this, we want to give the concerned user running the nginx workers permission to this directory. In this case,
we are going with root
. Replace this with your appropriate user.
sudo chown root /etc/resty-auto-ssl
After this we want to generate fallback certificates using openssl, and this fallback certificate will be used in case a certificate for a subdomain or domain could not be generated.
1
2
3
4
openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 \
-subj '/CN=sni-support-required-for-valid-ssl' \
-keyout /etc/ssl/resty-auto-ssl-fallback.key \
-out /etc/ssl/resty-auto-ssl-fallback.crt
Now we are ready to modify the nginx.conf
file under /etc/openresty
, and set it up along with lua-resty-auto-ssl
cd /etc/openresty
Let's remove the default nginx configuration file and write our own from scratch.
1
2
rm nginx.conf
vi nginx.conf
Insert the following in the nginx.conf
file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#Important to note the user. Change the name of user in charge accordingly
user root;
events {
worker_connections 1024;
}
http {
lua_shared_dict auto_ssl 1m;
lua_shared_dict auto_ssl_settings 64k;
resolver 8.8.8.8 ipv6=off;
init_by_lua_block {
auto_ssl = (require "resty.auto-ssl").new()
auto_ssl:set("allow_domain", function(domain)
return true
end)
auto_ssl:init()
}
init_worker_by_lua_block {
auto_ssl:init_worker()
}
server {
listen 443 ssl;
ssl_certificate_by_lua_block {
auto_ssl:ssl_certificate()
}
ssl_certificate /etc/ssl/resty-auto-ssl-fallback.crt;
ssl_certificate_key /etc/ssl/resty-auto-ssl-fallback.key;
}
server {
listen 80;
location /.well-known/acme-challenge/ {
content_by_lua_block {
auto_ssl:challenge_server()
}
}
}
server {
listen 127.0.0.1:8999;
client_body_buffer_size 128k;
client_max_body_size 128k;
location / {
content_by_lua_block {
auto_ssl:hook_server()
}
}
}
}
Restart the Openresty service:
sudo service openresty restart
And voila, SSL certificates will get automatically get generated for any domain/subdomain you visit that is pointing to
your public server IP. If you wish to restrict the automatic generation of SSL certificates to only certain subdomains, you can
certainly do so by modifying the allow_domain
property like so:
1
2
3
auto_ssl:set("allow_domain", function(domain, auto_ssl, ssl_options, renewal)
return ngx.re.match(domain, "^(example.com|example.net)$", "ijo")
end)
You can visit lua-resty-auto-ssl's documentation to introduce custom options for your need.
With this, you now don't have to worry about generating SSL certificates for each of your subdomain individually. If you wish to change the name of your subdomain at any point in time, you do so without the worry of having to generate SSL certificate for it. Openresty will now take care of that for you.