Lua + Nginx | Openresty : Using many SSL certificates in a server block


With Nginx you can use many SSL certificates with many server blocks. You can’t do this with only one server block.

But with Openresty or Nginx + lua module, you can do it

Example configuration:

server {
	listen 80 default_server;
	listen [::]:80 default_server;
	 
	# SSL configuration	 
	listen 443 ssl default_server;
	listen [::]:443 ssl default_server;
	 
	root /var/www/html;
	 
	resolver 8.8.8.8;

	# Add index.php to the list if you are using PHP
	index index.html index.htm index.nginx-debian.html;

	server_name _;
	 
	# SSL
	ssl_certificate /var/www/html/certs/maindomain.net.cert;
	ssl_certificate_key /var/www/html/certs/maindomain.net.key;
	ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
	ssl_prefer_server_ciphers on;
	ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
	# Improve HTTPS performance with session resumption
	ssl_session_cache shared:SSL:50m;
	ssl_session_timeout 1d;
	# DH parameters
	ssl_dhparam /etc/nginx/ssl/dhparam.pem;
	 
	ssl_certificate_by_lua_block {
        
		local ssl = require "ngx.ssl"
		local name = ssl.server_name()
		
		if name then
		
			if name:match("maindomain") then
				
			else
			  
				local mycheck = name:match("%.xyz$")
				
				-- clear the fallback certificates and private keys
				-- set by the ssl_certificate and ssl_certificate_key
				-- directives above:
				local ok, err = ssl.clear_certs()
				if not ok then
					ngx.log(ngx.ERR, "failed to clear existing (fallback) certificates")
					return ngx.exit(ngx.ERROR)
				end

				local my_load_certificate_chain = function()
					local f = io.open("/var/www/html/certs/cert.pem","rb")
					local a = f:read("a*")
					f:close()
					return a
				end
				local pem_cert_chain = assert(my_load_certificate_chain())

				local der_cert_chain, err = ssl.cert_pem_to_der(pem_cert_chain)
				if not der_cert_chain then
					ngx.log(ngx.ERR, "failed to convert certificate chain ",
							"from PEM to DER: ", err)
					return ngx.exit(ngx.ERROR)
				end

				local ok, err = ssl.set_der_cert(der_cert_chain)
				if not ok then
					ngx.log(ngx.ERR, "failed to set DER cert: ", err)
					return ngx.exit(ngx.ERROR)
				end
				
				local my_load_private_key = function()
					local f = io.open("/var/www/html/certs/privkey.pem","rb")
					local a = f:read("a*")
					f:close()
					return a
				end
				 
				local pem_pkey = assert(my_load_private_key())
				local passphrase = "yourPassword" -- or nil

				local der_pkey, err = ssl.priv_key_pem_to_der(pem_pkey, passphrase)
				if not der_pkey then
					ngx.log(ngx.ERR, "failed to convert private key ",
							"from PEM to DER: ", err)
					return ngx.exit(ngx.ERROR)
				end

				local ok, err = ssl.set_der_priv_key(der_pkey)
				if not ok then
					ngx.log(ngx.ERR, "failed to set DER private key: ", err)
					return ngx.exit(ngx.ERROR)
				end
			
			end
		end
    }
    ...
}

You can use certificate base on domain

change: "/var/www/html/certs/cert.pem"

to: "/var/www/html/certs/"..name..".cert"

and change: "/var/www/html/certs/privkey.pem"

to: "/var/www/html/certs/"..name..".pem"

Leave a Reply