ACME Protocol with two (or more) NGINX instances?

Continuing the discussion from ACME Protocol now supported directly in NGINX:

Direct support of ACME: Cool! Will simplify setup in a lot of cases.

I am running some of my web sites with two nginxs (any other plural?) and DNS resolves A and AAAA to both of them. So far, both nginxs use the same certificate (per web site).
Does ACME allow to have each server request its own certificate as long as domain validation succeeds for one address each? This would not only simplify configuration but also improve security as there is no longer a need to share the private key.

1 Like

Hi, thanks for asking such a great question.

If I am parsing the Let’s Encrypt docs correctly, yes, ACME allows each server to request its own certificate for the same domain, as long as each server can successfully complete a domain validation challenge.

The Let’s Encrypt FAQ and confirms that you can get certificates for multiple domain names on a single certificate, and also points out that Let’s Encrypt does not store your private keys.

You can issue up to 50 certificates per registered domain every seven days. You can issue up to 5 certificates with the exact same hostnames every seven days.

Let me know if this helps

davemc

1 Like

Thanks for the motivating reply.

I tried and failed.

I upgraded one of my nginx to 1.29.1 (open source). Then I configured within http

resolver 127.0.0.1:53;
acme_shared_zone zone=ngx_acme_shared:1M;
acme_issuer letsencrypt {
uri https://acme-v02.api.letsencrypt.org/directory;
contact redacted@example.com;
state_path /var/cache/nginx/acme-letsencrypt;
accept_terms_of_service.
}

and in server

acme_certificate letsencrypt;
ssl_certificate       $acme_certificate;
ssl_certificate_key   $acme_certificate_key;ssl_certificate_cache max=2;

and there was also a port 80 listener without server_name (doing a redirect to 443).

I configured my browser to connect specifically to that server and got ERR_SSL_PROTOCOL_ERROR. I checked error.log but no indication what went wrong.

Any idea what I am doing wrong? How to get verbose logs about that issue?

Hi Joachim! A cursory Google search shows that ERR_SSL_PROTOCOL_ERROR is likely related to browser settings. What happens if you try to curl the website?

Hi Alessandro,

thanks for stepping in, but I reverted the changes, and as after reverting everything was OK with the exact same URL, I don´t believe in browser settings but a configuration issue with nginx. If only nginx would tell me somehow why it didn´t complete the TLS handshake.

Hi Joachim! May I ask which changes did you revert? Sharing your entire NGINX config would also be helpful in figuring out what the issue could be.

I reverted to the state before any changes. I created the config below on a different system (behind a nginx stream proxy, thus the VPN addresses) as a simplistic example for analysis. I only redacted my actual domain.
#user www-data;
load_module modules/ngx_http_acme_module.so;

worker_processes auto;
pid /run/nginx.pid;
# load_module /usr/lib/nginx/modules/ngx_stream_module.so;
error_log  /var/log/nginx/error.log notice;

events {
        worker_connections 768;
        # multi_accept on;
}

http {
        # nginx-module-acme

        resolver 127.0.0.1:53;
                acme_shared_zone zone=ngx_acme_shared:1M;
        acme_issuer letsencrypt {
                uri https://acme-v02.api.letsencrypt.org/directory;
                contact nginxtest@example.org;
                state_path /var/cache/nginx/acme-letsencrypt;
                accept_terms_of_service;
        }
        access_log /var/log/nginx/access.log;
        server {
                listen [::]:80 ipv6only=off;
                location / {
                        return 401;
                }
        }
        server {
                listen [::]:443 ipv6only=off ssl;
                server_name nginxtest.example.org;
                acme_certificate letsencrypt;
                ssl_certificate       $acme_certificate;
                ssl_certificate_key   $acme_certificate_key;
                ssl_certificate_cache max=2;
                location / {
                        proxy_pass https://www.example.org;
                }
        }
}

curl https://nginxtest.example.org results in
curl: (35) OpenSSL/3.0.13: error:0A000438:SSL routines::tlsv1 alert internal error

error.log and access.log of nginx are both empty

and this is the tcpdump of the handshake:

root@sorg:/usr/lib/nginx/modules# tcpdump -XX port 80 or port 443
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
14:39:12.356834 IP 10.200.200.4.53484 > sorg.https: Flags [S], seq 527931603, win 64860, options [mss 1380,sackOK,TS val 2920877530 ecr 0,nop,wscale 7], length 0
        0x0000:  0015 5db1 170f 0015 5db1 1706 0800 4500  ..].....].....E.
        0x0010:  003c 907d 4000 3f06 6678 0ac8 c804 c0a8  .<.}@.?.fx......
        0x0020:  b151 d0ec 01bb 1f77 98d3 0000 0000 a002  .Q.....w........
        0x0030:  fd5c bf46 0000 0204 0564 0402 080a ae19  .\.F.....d......
        0x0040:  0dda 0000 0000 0103 0307                 ..........
14:39:12.356880 IP sorg.https > 10.200.200.4.53484: Flags [S.], seq 147848682, ack 527931604, win 65160, options [mss 1460,sackOK,TS val 3077788270 ecr 2920877530,nop,wscale 7], length 0
        0x0000:  dc15 c807 88b4 0015 5db1 170f 0800 4500  ........].....E.
        0x0010:  003c 0000 4000 4006 f5f5 c0a8 b151 0ac8  .<..@.@......Q..
        0x0020:  c804 01bb d0ec 08cf fdea 1f77 98d4 a012  ...........w....
        0x0030:  fe88 44f5 0000 0204 05b4 0402 080a b773  ..D............s
        0x0040:  526e ae19 0dda 0103 0307                 Rn........
14:39:12.383969 IP 10.200.200.4.53484 > sorg.https: Flags [.], ack 1, win 507, options [nop,nop,TS val 2920877555 ecr 3077788270], length 0
        0x0000:  0015 5db1 170f 0015 5db1 1706 0800 4500  ..].....].....E.
        0x0010:  0034 907e 4000 3f06 667f 0ac8 c804 c0a8  .4.~@.?.f.......
        0x0020:  b151 d0ec 01bb 1f77 98d4 08cf fdeb 8010  .Q.....w........
        0x0030:  01fb d85e 0000 0101 080a ae19 0df3 b773  ...^...........s
        0x0040:  526e                                     Rn
14:39:12.383969 IP 10.200.200.4.53484 > sorg.https: Flags [P.], seq 1:518, ack 1, win 507, options [nop,nop,TS val 2920877555 ecr 3077788270], length 517
        0x0000:  0015 5db1 170f 0015 5db1 1706 0800 4500  ..].....].....E.
        0x0010:  0239 907f 4000 3f06 6479 0ac8 c804 c0a8  .9..@.?.dy......
        0x0020:  b151 d0ec 01bb 1f77 98d4 08cf fdeb 8018  .Q.....w........
        0x0030:  01fb aa59 0000 0101 080a ae19 0df3 b773  ...Y...........s
        0x0040:  526e 1603 0102 0001 0001 fc03 0379 5c0b  Rn...........y\.
        0x0050:  4f8d 79a0 c951 42a4 a96a dd09 b76e 6ed4  O.y..QB..j...nn.
        0x0060:  1dfe d98e 709c 6b46 bb57 cf6a 0820 a444  ....p.kF.W.j...D
        0x0070:  0fd1 e889 17fc 3144 12d7 e8a8 5865 dcf7  ......1D....Xe..
        0x0080:  407c 8713 1dbe 988b 6af6 8eeb b2a9 003e  @|......j......>
        0x0090:  1302 1303 1301 c02c c030 009f cca9 cca8  .......,.0......
        0x00a0:  ccaa c02b c02f 009e c024 c028 006b c023  ...+./...$.(.k.#
        0x00b0:  c027 0067 c00a c014 0039 c009 c013 0033  .'.g.....9.....3
        0x00c0:  009d 009c 003d 003c 0035 002f 00ff 0100  .....=.<.5./....
        0x00d0:  0175 0000 001d 001b 0000 186e 6769 6e78  .u.........nginx
        0x00e0:  7465 7374 2e6c ___  test.example___.
        0x00f0:  6f72 6700 0b00 0403 0001 0200 0a00 1600  org.............
        0x0100:  1400 1d00 1700 1e00 1900 1801 0001 0101  ................
        0x0110:  0201 0301 0400 1000 0e00 0c02 6832 0868  ............h2.h
        0x0120:  7474 702f 312e 3100 1600 0000 1700 0000  ttp/1.1.........
        0x0130:  3100 0000 0d00 2a00 2804 0305 0306 0308  1.....*.(.......
        0x0140:  0708 0808 0908 0a08 0b08 0408 0508 0604  ................
        0x0150:  0105 0106 0103 0303 0103 0204 0205 0206  ................
        0x0160:  0200 2b00 0504 0304 0303 002d 0002 0101  ..+........-....
        0x0170:  0033 0026 0024 001d 0020 d4ee 4a71 4e21  .3.&.$......JqN!
        0x0180:  6b24 3323 b977 87b1 e58e 88b9 a4d2 f86a  k$3#.w.........j
        0x0190:  7efc 4c22 9667 ec1b 6171 0015 00a9 0000  ~.L".g..aq......
        0x01a0:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x01b0:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x01c0:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x01d0:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x01e0:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x01f0:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x0200:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x0210:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x0220:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x0230:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x0240:  0000 0000 0000 00                        .......
14:39:12.384035 IP sorg.https > 10.200.200.4.53484: Flags [.], ack 518, win 506, options [nop,nop,TS val 3077788298 ecr 2920877555], length 0
        0x0000:  dc15 c807 88b4 0015 5db1 170f 0800 4500  ........].....E.
        0x0010:  0034 74dc 4000 4006 8121 c0a8 b151 0ac8  .4t.@.@..!...Q..
        0x0020:  c804 01bb d0ec 08cf fdeb 1f77 9ad9 8010  ...........w....
        0x0030:  01fa 44ed 0000 0101 080a b773 528a ae19  ..D........sR...
        0x0040:  0df3                                     ..
14:39:12.384286 IP sorg.https > 10.200.200.4.53484: Flags [P.], seq 1:8, ack 518, win 506, options [nop,nop,TS val 3077788298 ecr 2920877555], length 7
        0x0000:  dc15 c807 88b4 0015 5db1 170f 0800 4500  ........].....E.
        0x0010:  003b 74dd 4000 4006 8119 c0a8 b151 0ac8  .;t.@.@......Q..
        0x0020:  c804 01bb d0ec 08cf fdeb 1f77 9ad9 8018  ...........w....
        0x0030:  01fa 44f4 0000 0101 080a b773 528a ae19  ..D........sR...
        0x0040:  0df3 1503 0300 0202 50                   ........P
14:39:12.384312 IP sorg.https > 10.200.200.4.53484: Flags [F.], seq 8, ack 518, win 506, options [nop,nop,TS val 3077788298 ecr 2920877555], length 0
        0x0000:  dc15 c807 88b4 0015 5db1 170f 0800 4500  ........].....E.
        0x0010:  0034 74de 4000 4006 811f c0a8 b151 0ac8  .4t.@.@......Q..
        0x0020:  c804 01bb d0ec 08cf fdf2 1f77 9ad9 8011  ...........w....
        0x0030:  01fa 44ed 0000 0101 080a b773 528a ae19  ..D........sR...
        0x0040:  0df3                                     ..
14:39:12.409132 IP 10.200.200.4.53484 > sorg.https: Flags [.], ack 8, win 507, options [nop,nop,TS val 2920877582 ecr 3077788298], length 0
        0x0000:  0015 5db1 170f 0015 5db1 1706 0800 4500  ..].....].....E.
        0x0010:  0034 9080 4000 3f06 667d 0ac8 c804 c0a8  .4..@.?.f}......
        0x0020:  b151 d0ec 01bb 1f77 9ad9 08cf fdf2 8010  .Q.....w........
        0x0030:  01fb d61b 0000 0101 080a ae19 0e0e b773  ...............s
        0x0040:  528a                                     R.
14:39:12.409409 IP 10.200.200.4.53484 > sorg.https: Flags [F.], seq 518, ack 9, win 507, options [nop,nop,TS val 2920877582 ecr 3077788298], length 0
        0x0000:  0015 5db1 170f 0015 5db1 1706 0800 4500  ..].....].....E.
        0x0010:  0034 9081 4000 3f06 667c 0ac8 c804 c0a8  .4..@.?.f|......
        0x0020:  b151 d0ec 01bb 1f77 9ad9 08cf fdf3 8011  .Q.....w........
        0x0030:  01fb d619 0000 0101 080a ae19 0e0e b773  ...............s
        0x0040:  528a                                     R.
14:39:12.409429 IP sorg.https > 10.200.200.4.53484: Flags [.], ack 519, win 506, options [nop,nop,TS val 3077788323 ecr 2920877582], length 0
        0x0000:  dc15 c807 88b4 0015 5db1 170f 0800 4500  ........].....E.
        0x0010:  0034 74df 4000 4006 811e c0a8 b151 0ac8  .4t.@.@......Q..
        0x0020:  c804 01bb d0ec 08cf fdf3 1f77 9ada 8010  ...........w....
        0x0030:  01fa 44ed 0000 0101 080a b773 52a3 ae19  ..D........sR...
        0x0040:  0e0e                                     ..
^C
10 packets captured
10 packets received by filter
0 packets dropped by kernel

1 Like

If by that you mean forwarding to a single instance, yes, all my nginx so far forward port 80 /.well-known/… to a central instance. But I´d like to get rid of that central instance being both a store of high value credentials and a SPOF.

I could, but in fact then you need to distribute either API credentials (or create + pay as many as needed) or still have an isolated endpoint aka SPOF.

@alessandro
Did you have time to check my configuration? Id definitley appreciate figuring out why it doesn´t work.

Not yet, and it might be a while to be totally honest with you. I have yet to familiarize myself with the ACME module.