Acme_server implementation

I’m using Caddy v2.3.0 h1:fnrqJLa3G5vfxcxmOH/+kJOcunPLhSBnjgIvjXV/QTA=

and would like to use mTLS for several clients in my local network.

I have Caddy running publicly accessable and a second Caddy within my LAN.

Internet → Caddy public → Caddy LAN → app

If I got it right, by adding the following to the public Caddy, this node will other then reverse proxy, then also act as local ACME server:

acme.localhost {
   acme_server
}

The second Caddy (LAN) can then act as an ACME client by adding the following:

    tls test@intranet.nl {
       ca https://<hostname or IP address ACME Server>/acme/local/directory
       client_auth {
          trusted_ca_cert_file ../<path to certificate>
    }

Does Caddy (with the smallstep library) generate the CA when adding acme_server or do I need to create this manually? If it’s automatically generated, where can I find it?

I though t I could find it here: .local/share/caddy/acme_server/local

But this path only hold a file named db

To trust the CA trusted_ca_cert_file ../<path to certificate> I need to manually copy the CA to each end-node and provide whatever path I gave it, right?

Thanks,
Robbert

Yes, it’s automatic. You can find it in your storage directory (depends how you installed Caddy) in pki/authorities/local/root.crt.

Yep :+1:

One thing to note, the default CA is named “Caddy Local Authority” which is mostly intended for use on localhost. So if you want to deploy a fleet and trust it around, you might want to rename it to avoid confusion. (Not sure it can be done with the Caddyfile currently.)

Matt’s talking about this: JSON Config Structure - Caddy Documentation

But yes, not configurable in Caddyfile yet. But like he said, not necessary, just something to be aware of in case confusion arises about the name (but it doesn’t affect functionality at all).

1 Like

You must have read my mind. It was going to be my next question. How to rename the default name (in Caddyfile).

I won’t go through that trouble (JSON) (yet) but I was just currious.

Thanks,
Robbert

2 Likes

Thanks for confirming!

1 Like

I tried to add mTLS to a working http setup and when I browse (Firefox) to the local node at https://192.168.2.50 it returns

Secure Connection Failed

An error occurred during a connection to 192.168.2.50. Peer reports it experienced an internal error.

Error code: SSL_ERROR_INTERNAL_ERROR_ALERT

log is showing following:

{"level":"info","ts":1611778553.4474347,"logger":"http","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv0"}
{"level":"info","ts":1611778553.4475944,"logger":"http","msg":"enabling strict SNI-Host matching because TLS client auth is configured","server_name":"srv0"}
{"level":"info","ts":1611778553.4514475,"msg":"autosaved config","file":"/config/caddy/autosave.json"}
{"level":"info","ts":1611778553.4514616,"msg":"serving initial configuration"}
{"level":"info","ts":1611778553.4544322,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0xc000218e00"}
{"level":"info","ts":1611778553.4545352,"logger":"tls","msg":"cleaned up storage units"}

There are 2 nodes;

  1. Caddy on Debian (192.168.2.2) acting as ACME Server and reverse proxy for the outside world
  2. Caddy in docker on Debian (192.168.2.50) acting as ACME client and webserver for Nextcloud

1.Caddyfile

#
# ACME Server
acme.localhost {
   acme_server
}

# Reverse proxy
#
nextcloud.intranet.nl {
   reverse_proxy https://192.168.2.50
}

2.Caddyfile:

:443 {

        root    * /var/www/html
        tls robbert@intranet.nl {
           ca https://192.168.2.2/acme/local/directory
           client_auth {
              trusted_ca_cert_file /data/root.crt
              }
        }
        file_server

        php_fastcgi app:9000
        header {
                # enable HSTS
                # Strict-Transport-Security max-age=31536000;
        }

        redir /.well-known/carddav /remote.php/dav 301
        redir /.well-known/caldav /remote.php/dav 301

        # .htaccess / data / config / ... shouldn't be accessible from outside
        @forbidden {
                path    /.htaccess
                path    /data/*
                path    /config/*
                path    /db_structure
                path    /.xml
                path    /README
                path    /3rdparty/*
                path    /lib/*
                path    /templates/*
                path    /occ
                path    /console.php
        }

        respond @forbidden 404

}

So I think I am making connection with the 2nd Caddy node (Nextcloud) but there is something wrong with the generated certificate?

If you’re running Caddy in a container (why…) you’ll need to add its root CA to your host system’s trust store manually.

Oh, that make sense… :man_facepalming:

I was already running other tests with the docker containers. It was easy to continue with that test setup.

Now I have 2 nodes that run Caddy nativly but I’m having more and more troubles. I moved back to the very basics but I’m still having mixed results.

Caddy 1: running at 192.168.2.2 (port 443/80 forwared in router)

#
# ACME Server
acme.localhost {
   acme_server
}

# Reverse proxy
#
nextcloud.intrafit.nl {
   reverse_proxy https://192.168.2.50
}

Caddy 2: running at 192.168.2.50

192.168.2.50:443

respond "Hello , this is your internal website talking!" {

   tls robbert@intrafit.nl {
      ca https://192.168.2.2/acme/local/directory
      client_auth {
         trusted_ca_cert_file /root/nextcloud/root.crt
      }
   }
}

When I browse with Firefox from a different Windows VM to https://192.168.2.50, I get

Secure Connection Failed

An error occurred during a connection to 192.168.2.50. Peer’s certificate has an invalid signature.

Error code: SEC_ERROR_BAD_SIGNATURE

The page you are trying to view cannot be shown because the authenticity of the received data could not be verified.
Please contact the web site owners to inform them of this problem.

Also when I manually install the root certificate in Firefox.

It took me a while to discover that when use Chrome (from a Laptop), I do get a response! I cannot install the root certificate on that maching so I get a warning that the connection is insecure but I do get a reply.

Can this be a cache problem? I cleared the cache in Firefox without seeing a difference.

When on the same laptop I try to access from external through https://nextcloud.intrafit.nl I get HTTP ERROR 502.

The logs show this

2021/01/31 15:18:02.234 ERROR http.log.error x509: certificate signed by unknown authority (possibly because of “x509: ECDSA verification failure” while trying to verify candidate authority certificate “Caddy Local Authority - 2021 ECC Root”) {“request”: {“remote_addr”: “192.168.5.1:59373”, “proto”: “HTTP/2.0”, “method”: “GET”, “host”: “nextcloud.intrafit.nl”, “uri”: “/”, “headers”: {“Sec-Fetch-Site”: [“cross-site”], “Sec-Fetch-Mode”: [“navigate”], “Sec-Fetch-User”: ["?1"], “Upgrade-Insecure-Requests”: [“1”], “User-Agent”: [“Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36”], “Sec-Fetch-Dest”: [“document”], “Cookie”: ["__Host-nc_sameSiteCookielax=true"], “Accept”: [“text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9”], “Accept-Language”: [“en-US,en;q=0.9,nl;q=0.8”], “Cache-Control”: [“max-age=0”], “Accept-Encoding”: [“gzip, deflate, br”]}, “tls”: {“resumed”: false, “version”: 771, “cipher_suite”: 49196, “proto”: “h2”, “proto_mutual”: true, “server_name”: “nextcloud.intrafit.nl”}}, “duration”: 0.007132826, “status”: 502, “err_id”: “c0yywugsm”, “err_trace”: “reverseproxy.statusError (reverseproxy.go:783)”}

So I figured I need to add the root certificate:

nextcloud.intrafit.nl {
   reverse_proxy https://192.168.2.50 {
      transport http {
      tls_trusted_ca_certs /root/.local/share/caddy/pki/authorities/local/root.crt
      }
   }
}

But this seems to give me the same results.

2021/01/31 15:22:11.516 ERROR http.log.error x509: certificate signed by unknown authority (possibly because of “x509: ECDSA verification failure” while trying to verify candidate authority certificate “Caddy Local Authority - 2021 ECC Root”) {“request”: {“remote_addr”: “192.168.5.1:52042”, “proto”: “HTTP/2.0”, “method”: “GET”, “host”: “nextcloud.intrafit.nl”, “uri”: “/”, “headers”: {“Upgrade-Insecure-Requests”: [“1”], “Sec-Fetch-User”: ["?1"], “User-Agent”: [“Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36”], “Accept”: [“text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9”], “Sec-Fetch-Dest”: [“document”], “Cache-Control”: [“max-age=0”], “Sec-Fetch-Mode”: [“navigate”], “Cookie”: ["__Host-nc_sameSiteCookielax=true"], “Accept-Encoding”: [“gzip, deflate, br”], “Accept-Language”: [“en-US,en;q=0.9,nl;q=0.8”], “Sec-Fetch-Site”: [“cross-site”]}, “tls”: {“resumed”: false, “version”: 771, “cipher_suite”: 49196, “proto”: “h2”, “proto_mutual”: true, “server_name”: “nextcloud.intrafit.nl”}}, “duration”: 0.014319558, “status”: 502, “err_id”: “3yi2scsht”, “err_trace”: “reverseproxy.statusError (reverseproxy.go:783)”}

After further testing it seems that there is no certificate generated from teh local ECME server with the above setup.

In that case the error message makes sense as the given CA is not used.

Did I make a mistake in the Caddyfile?

I think this is likely your issue, because your server is like this:

So if you use the IP address for the CA config, then the request won’t be using acme.localhost in SNI, so the acme.localhost matcher won’t accept the request (because it’ll just see the IP address instead).

Do you have a DNS server running in your network? If so, it would probably be correct to configure it to have some domain resolve to your first Caddy instance, which you can then use for the CA config.

This config doesn’t really make sense – why is tls inside the respond directive? That should be an error, but I’m not sure what you’re trying to do there.

Thanks for trying to get me through!

I’ve changed the 2nd Caddy to point to acme.roadrunner

192.168.2.51:443 {

       tls robbert@intrafit.nl {
          ca https:///acme.roadrunner/acme/local/directory
          client_auth {
             trusted_ca_cert_file /root/nextcloud/root.crt
          }
      }

And I configured my local DNS to resolve to the 1st Caddy:

# ping acme.roadrunner
PING acme.roadrunner (192.168.2.2) 56(84) bytes of data.
64 bytes from acme.roadrunner (192.168.2.2): icmp_seq=1 ttl=64 time=0.484 ms
64 bytes from acme.roadrunner (192.168.2.2): icmp_seq=2 ttl=64 time=0.461 ms
64 bytes from acme.roadrunner (192.168.2.2): icmp_seq=3 ttl=64 time=0.461 ms

I kept the 1st Caddy config the same:

# ACME Server
acme.localhost {
   acme_server
}

Caddy 2 log:

2021/02/02 18:35:13.587 INFO using adjacent Caddyfile
2021/02/02 18:35:13.595 INFO admin admin endpoint started {“address”: “tcp/localhost:2019”, “enforce_origin”: false, “origins”: [“127.0.0.1:2019”, “localhost:2019”, “[::1]:2019”]}
2021/02/02 18:35:13.599 INFO http enabling automatic HTTP->HTTPS redirects {“server_name”: “srv0”}
2021/02/02 18:35:13.601 INFO http enabling strict SNI-Host matching because TLS client auth is configured {“server_name”: “srv0”}
2021/02/02 18:35:13.603 DEBUG http starting server loop {“address”: “[::]:443”, “http3”: false, “tls”: true}
2021/02/02 18:35:13.610 DEBUG http starting server loop {“address”: “[::]:80”, “http3”: false, “tls”: false}
2021/02/02 18:35:13.621 INFO http enabling automatic TLS certificate management {“domains”: [“192.168.2.51”]}
2021/02/02 18:35:13.624 INFO autosaved config {“file”: “/root/.config/caddy/autosave.json”}
2021/02/02 18:35:13.626 INFO serving initial configuration
2021/02/02 18:35:13.600 INFO tls.cache.maintenance started background certificate maintenance {“cache”: “0xc000214e00”}
2021/02/02 18:35:13.610 INFO tls cleaned up storage units
2021/02/02 18:35:13.627 INFO tls.obtain acquiring lock {“identifier”: “192.168.2.51”}
2021/02/02 18:35:13 [INFO][FileStorage:/root/.local/share/caddy] Lock for ‘issue_cert_192.168.2.51’ is stale (created: 2021-02-02 18:31:49.627439843 +0000 UTC, last update: 2021-02-02 18:33:34.679417843 +0000 UTC); removing then retrying: /root/.local/share/caddy/locks/issue_cert_192.168.2.51.lock
2021/02/02 18:35:13.630 INFO tls.obtain lock acquired {“identifier”: “192.168.2.51”}
2021/02/02 18:35:13.656 WARN tls.issuance.acme.acme_client HTTP request failed; retrying {“url”: “https:///acme.roadrunner/acme/local/directory”, “error”: “performing request: Get “https:///acme.roadrunner/acme/local/directory”: http: no Host in request URL”}
2021/02/02 18:35:13.909 WARN tls.issuance.acme.acme_client HTTP request failed; retrying {“url”: “https:///acme.roadrunner/acme/local/directory”, “error”: “performing request: Get “https:///acme.roadrunner/acme/local/directory”: http: no Host in request URL”}
2021/02/02 18:35:14.159 WARN tls.issuance.acme.acme_client HTTP request failed; retrying {“url”: “https:///acme.roadrunner/acme/local/directory”, “error”: “performing request: Get “https:///acme.roadrunner/acme/local/directory”: http: no Host in request URL”}
2021/02/02 18:35:14.160 ERROR tls.obtain will retry {“error”: “[192.168.2.51] Obtain: registering account with server: provisioning client: performing request: Get “https:///acme.roadrunner/acme/local/directory”: http: no Host in request URL”, “attempt”: 1, “retrying_in”: 60, “elapsed”: 0.529794157, “max_duration”: 2592000}
2021/02/02 18:36:14.162 WARN tls.issuance.acme.acme_client HTTP request failed; retrying {“url”: “https:///acme.roadrunner/acme/local/directory”, “error”: “performing request: Get “https:///acme.roadrunner/acme/local/directory”: http: no Host in request URL”}
2021/02/02 18:36:14.416 WARN tls.issuance.acme.acme_client HTTP request failed; retrying {“url”: “https:///acme.roadrunner/acme/local/directory”, “error”: “performing request: Get “https:///acme.roadrunner/acme/local/directory”: http: no Host in request URL”}
2021/02/02 18:36:14.667 WARN tls.issuance.acme.acme_client HTTP request failed; retrying {“url”: “https:///acme.roadrunner/acme/local/directory”, “error”: “performing request: Get “https:///acme.roadrunner/acme/local/directory”: http: no Host in request URL”}
2021/02/02 18:36:14.667 ERROR tls.obtain will retry {“error”: “[192.168.2.51] Obtain: registering account with server: provisioning client: performing request: Get “https:///acme.roadrunner/acme/local/directory”: http: no Host in request URL”, “attempt”: 2, “retrying_in”: 120, “elapsed”: 61.036873887, “max_duration”: 2592000}

Hi Matt,

With this I was hoping to create a minimal Caddyfile config that would response with a certificate from the local acme server. I am not?

That still won’t match, because acme.localhost != acme.roadrunner.

It’s just not valid syntax. You want this:

192.168.2.50:443 {
	respond "Hello, this is your internal website talking!"

	tls ... {
		...
	}
}

Your braces were in the wrong places.

Yeah, I’d recommend brushing up on: Caddyfile Concepts — Caddy Documentation

I’m not sure why an error didn’t get emitted, but I’ll fix that. Edit: done here: caddyhttp: Check for invalid subdirectives of static_response · caddyserver/caddy@8ec90f1 · GitHub

There seems to be a lot going on here… Is there anything else?

1 Like

@francislavoie Thanks for correcting me there. I tried various notations before but only now I recognize the difference in outcome from the log. With the bracket wrong, Caddy was ignoring the certificate portion completely and used default config. The CA was therefore not matching.

@matt I wanted to test the new code but I run into an error while building the code. I couldn’t find a solution. I’ll post it in a seperate topic.

Concerning the local acme server setup. I tried several options. Perhaps I should have included that info but looking at the error log I was convinced it was wrong.

As soon as I change

acme.localhost {
   acme_server
}

into something else e.g.

acme.roadrunner{
   acme_server
}

It will produce errors like below that looks like to me it tis rying to do something external.

2021/02/03 08:54:12.042 INFO using adjacent Caddyfile
2021/02/03 08:54:12.046 INFO admin admin endpoint started {“address”: “tcp/localhost:2019”, “enforce_origin”: false, “origins”: [“localhost:2019”, “[::1]:2019”, “127.0.0.1:2019”]}
2021/02/03 08:54:12.051 INFO http server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS {“server_name”: “srv0”, “https_port”: 443}
2021/02/03 08:54:12.051 INFO http enabling automatic HTTP->HTTPS redirects {“server_name”: “srv0”}
2021/02/03 08:54:12.076 INFO tls.cache.maintenance started background certificate maintenance {“cache”: “0xc000227ab0”}
2021/02/03 08:54:12.113 INFO tls cleaned up storage units
2021/02/03 08:54:12.177 INFO pki.ca.local root certificate is already trusted by system {“path”: “storage:pki/authorities/local/root.crt”}
2021/02/03 08:54:12.180 DEBUG http starting server loop {“address”: “[::]:443”, “http3”: false, “tls”: true}
2021/02/03 08:54:12.181 DEBUG http starting server loop {“address”: “[::]:80”, “http3”: false, “tls”: false}
2021/02/03 08:54:12.181 INFO http enabling automatic TLS certificate management {“domains”: [“acme.roadrunner”]}
2021/02/03 08:54:12.182 INFO autosaved config {“file”: “/root/.config/caddy/autosave.json”}
2021/02/03 08:54:12.183 INFO serving initial configuration
2021/02/03 08:54:12.183 INFO tls.obtain acquiring lock {“identifier”: “acme.roadrunner”}
2021/02/03 08:54:12.184 INFO tls.obtain lock acquired {“identifier”: “acme.roadrunner”}
2021/02/03 08:54:12.186 INFO tls.issuance.acme waiting on internal rate limiter {“identifiers”: [“acme.roadrunner”]}
2021/02/03 08:54:12.187 INFO tls.issuance.acme done waiting on internal rate limiter {“identifiers”: [“acme.roadrunner”]}
2021/02/03 08:54:12.869 DEBUG tls.issuance.acme.acme_client http request {“method”: “GET”, “url”: “https://acme-v02.api.letsencrypt.org/directory”, “headers”: {“User-Agent”:[“Caddy/2.3.0 CertMagic acmez (linux; amd64)”]}, “status_code”: 200, “response_headers”: {“Cache-Control”:[“public, max-age=0, no-cache”],“Content-Length”:[“658”],“Content-Type”:[“application/json”],“Date”:[“Wed, 03 Feb 2021 08:54:12 GMT”],“Server”:[“nginx”],“Strict-Transport-Security”:[“max-age=604800”],“X-Frame-Options”:[“DENY”]}}
2021/02/03 08:54:13.042 DEBUG tls.issuance.acme.acme_client http request {“method”: “HEAD”, “url”: “https://acme-v02.api.letsencrypt.org/acme/new-nonce”, “headers”: {“User-Agent”:[“Caddy/2.3.0 CertMagic acmez (linux; amd64)”]}, “status_code”: 200, “response_headers”: {“Cache-Control”:[“public, max-age=0, no-cache”],“Date”:[“Wed, 03 Feb 2021 08:54:12 GMT”],“Link”:[“https://acme-v02.api.letsencrypt.org/directory;rel=“index””],“Replay-Nonce”:[“0003s6c1bz_FtCFlDk5QUYEFSedT-UrItbNh4wreNNW6w1g”],“Server”:[“nginx”],“Strict-Transport-Security”:[“max-age=604800”],“X-Frame-Options”:[“DENY”]}}
2021/02/03 08:54:13.221 DEBUG tls.issuance.acme.acme_client http request {“method”: “POST”, “url”: “https://acme-v02.api.letsencrypt.org/acme/new-order”, “headers”: {“Content-Type”:[“application/jose+json”],“User-Agent”:[“Caddy/2.3.0 CertMagic acmez (linux; amd64)”]}, “status_code”: 400, “response_headers”: {“Boulder-Requester”:[“108797708”],“Cache-Control”:[“public, max-age=0, no-cache”],“Content-Length”:[“217”],“Content-Type”:[“application/problem+json”],“Date”:[“Wed, 03 Feb 2021 08:54:13 GMT”],“Link”:[“https://acme-v02.api.letsencrypt.org/directory;rel=“index””],“Replay-Nonce”:[“0004yNqaE5pHW9gvn4-53EKO_fakgHp74Jc0e6IT6HjyiAA”],“Server”:[“nginx”]}}
2021/02/03 08:54:13.226 INFO tls.issuance.acme waiting on internal rate limiter {“identifiers”: [“acme.roadrunner”]}
2021/02/03 08:54:13.229 INFO tls.issuance.acme done waiting on internal rate limiter {“identifiers”: [“acme.roadrunner”]}
2021/02/03 08:54:13.990 DEBUG tls.issuance.acme.acme_client http request {“method”: “GET”, “url”: “https://acme.zerossl.com/v2/DV90”, “headers”: {“User-Agent”:[“Caddy/2.3.0 CertMagic acmez (linux; amd64)”]}, “status_code”: 200, “response_headers”: {“Access-Control-Allow-Origin”:[""],“Cache-Control”:[“max-age=-1”],“Content-Length”:[“644”],“Content-Type”:[“application/json”],“Date”:[“Wed, 03 Feb 2021 08:54:13 GMT”],“Server”:[“nginx”],“Strict-Transport-Security”:[“max-age=15552000”]}}
2021/02/03 08:54:14.527 DEBUG tls.issuance.acme.acme_client http request {“method”: “HEAD”, “url”: “https://acme.zerossl.com/v2/DV90/newNonce”, “headers”: {“User-Agent”:[“Caddy/2.3.0 CertMagic acmez (linux; amd64)”]}, “status_code”: 200, “response_headers”: {“Access-Control-Allow-Origin”:["
"],“Cache-Control”:[“max-age=-1”],“Content-Type”:[“application/octet-stream”],“Date”:[“Wed, 03 Feb 2021 08:54:14 GMT”],“Link”:[“https://acme.zerossl.com/v2/DV90;rel=“index””],“Replay-Nonce”:[“wCP4wu8POUHp51pju9KUgGFXcO0kq0wjQ0UAt-wcjh8”],“Server”:[“nginx”],“Strict-Transport-Security”:[“max-age=15552000”]}}
2021/02/03 08:54:15.130 DEBUG tls.issuance.acme.acme_client http request {“method”: “POST”, “url”: “https://acme.zerossl.com/v2/DV90/newOrder”, “headers”: {“Content-Type”:[“application/jose+json”],“User-Agent”:[“Caddy/2.3.0 CertMagic acmez (linux; amd64)”]}, “status_code”: 400, “response_headers”: {“Access-Control-Allow-Origin”:["*"],“Cache-Control”:[“max-age=0, no-cache, no-store”,“max-age=-1”],“Content-Length”:[“121”],“Content-Type”:[“application/problem+json”],“Date”:[“Wed, 03 Feb 2021 08:54:15 GMT”],“Link”:[“https://acme.zerossl.com/v2/DV90;rel=“index””],“Replay-Nonce”:[“t1_OPv-Z9rB4V_aJySImLh6lOVSzsQEkJZIskZKlCJY”],“Server”:[“nginx”]}}
2021/02/03 08:54:15.133 ERROR tls.obtain will retry {“error”: “[acme.roadrunner] Obtain: [acme.roadrunner] creating new order: request to https://acme.zerossl.com/v2/DV90/newOrder failed after 1 attempts: HTTP 400 urn:ietf:params:acme:error:rejectedIdentifier - Invalid DNS identifier [acme.roadrunner] (ca=https://acme.zerossl.com/v2/DV90)”, “attempt”: 1, “retrying_in”: 60, “elapsed”: 2.94887413, “max_duration”: 2592000}

You’re missing a space before the { which is important here. Caddy will parse that as being part of the hostname. Spaces are important in the Caddyfile.

But now what’s happening in your logs is that since you’re using a non-local hostname, Caddy tries to fetch a certificate for it from Let’s Encrypt or ZeroSSL. You’ll need to specify tls internal for that site for it to use your local CA.

1 Like

Sorry that missing space was a typo when writing down that post. The actual Caddyfile was correct.

I’ve tried quite a few configurations without joy.

To get the principles right, I need to set tls internal on the server side only or also at client side?

The acme server side

acme.roadrunner {
   acme_server
   tls internal
}

Since at the client side I’m already pointing to a local acme server, I don’t think tls internal is required?

ca https://acme.roadrunner/acme/local/directory

On the acme server side I copy the file root.crt from .local/share/caddy/pki/authorities/local to the client and point to it in the Caddyfile e.g. trusted_ca_cert_file /root/root.crt or should I use ca_root /root/root.crt I tried it all anyway.

I’d be very happy if you could fix the below Caddyfile to get a certificate from the above acme_server.

192.168.2.50:443 {

respond "Hello, this is your internal website @ 192.168.2.50"

   tls {
      ca https://acme.roadrunner/acme/local/directory
      client_auth {
         trusted_ca_cert_file /root/root.crt
      }
   }
}

The closest I’m getting (with several configs) is that the CA is refused:

2021/02/03 19:58:06.517 ERROR tls.obtain will retry {“error”: “[192.168.2.50] Obtain: registering account with server: provisioning client: performing request: Get “https://acme.roadrunner/acme/local/directory”: x509: certificate signed by unknown authority (possibly because of “x509: ECDSA verification failure” while trying to verify candidate authority certificate “Caddy Local Authority - 2021 ECC Root”)”, “attempt”: 1, “retrying_in”: 60, “elapsed”: 0.643672559, “max_duration”: 2592000}

It don’t like my CA. Am I pointing to the wrong file? Using wrong syntax?

@matt OK, I managed to compile the latest master branche and I can confirm the check is working!

# caddy run
2021/02/03 20:16:06.297 INFO    using adjacent Caddyfile
run: adapting config using caddyfile: parsing caddyfile tokens for 'respond': Caddyfile:17 - Error during parsing: unrecognized subdirective 'tls'

Where the official release would just run without reporting an issue.

1 Like