How to load certificates using the API

For a specific domain I would like to disable caddy’s automatic certificate retrieval and use my custom certificates.

Therefore I would like register the certificates using the caddy api (JSON Config Structure - Caddy Documentation).

Unfortunately caddy does not recognize the certificates:

$ curl caddyhost:2019/config/apps/tls/certificates -X POST -H "Content-Type: application/json" -d '{"load_pem": [{"certificate": "-----BEGIN CERTIFICATE----MIIGfzCCBWegAwIBAgISA8A1M8hcnrtS0B9BnyoZpvlHMA0GCSqGSIb3DQEBCwUAMEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dG[...]-----END CERTIFICATE-----", "key":"-----BEGIN RSA PRIVATE KEY-----
MIIJNBFTBAAKCAgEA/y7t3GTcrWHJ+lsWGEvhUtAo7/S9l7DHw/A6DW7F88+wO[...]-----END RSA PRIVATE KEY-----"}]}'

$ {"error":"loading new config: loading http app module: provision http: getting tls app: loading tls app module: provision tls: loading certificates: PEM pair 0: tls: failed to find any PEM data in certificate input"}

I already tried to base64 encode both the certificate and the key, but this does not work either (same error message).

I’m pretty sure you need to omit the ASCII armor (i.e. the bits with the ---) for it to work.

If you didn’t realize, PEM is a base64 encoded certificate already, it just has the ASCII armor around it and newlines every 64 characters. DER is the raw binary format, and base64 encoding a DER certificate, then splitting it with newlines every 64 chars, and adding the ASCII armor, gives you a PEM.

Removing the ASCII armor didn’t work either.

What worked though was to use “load_files”, instead of “load_pem”. The content of the files is the same as the strings I have used with the “load_pem” method.

curl caddyhost:2019/config/apps/tls/certificates -X POST -H "Content-Type: application/json" -d '{"load_files": [{"certificate": "/certs/mydomain.com.cer", "key":"/certs/mydomain.com.key"}]}'

I’m confused, since I have validated the “load_pem” data with openssl. The strings were valid…

Since I extensively use the API to automate things as much as possible, I still would like to manage the certificates via the API instead of deploying those files on the host and then reloading caddy. Do you have any other suggestions or even a working example?

I’m basing this on the below test case that’s part of the codebase. It doesn’t map to exactly the same config field, but it should work the same:

If not, I’ll need to do some digging in the codebase to figure out if there’s a meaningful difference.

This is the code that runs to load the certificates - so if you can find details about what tls.X509KeyPair takes, you should be able to figure it out.

I’m just on my phone for the time being and my time is limited - I’ll come back to this when I can if you don’t figure it out.

This topic was automatically closed after 30 days. New replies are no longer allowed.