Configuration error trying authenticated acme api

1. Caddy version (caddy version):

v2.3.0 h1:fnrqJLa3G5vfxcxmOH/+kJOcunPLhSBnjgIvjXV/QTA=

2. How I run Caddy:

systemctl start caddy

a. System environment:

Description: CentOS Linux release 7.9.2009 (Core)

b. Command:

caddy validate --config /etc/caddy/Caddyfile.json

c. Service/unit/compose file:

# caddy.service
#
# For using Caddy with a config file.
#
# Make sure the ExecStart and ExecReload commands are correct
# for your installation.
#
# See https://caddyserver.com/docs/install for instructions.
#
# WARNING: This service does not use the --resume flag, so if you
# use the API to make changes, they will be overwritten by the
# Caddyfile next time the service is restarted. If you intend to
# use Caddy's API to configure it, add the --resume flag to the
# `caddy run` command or use the caddy-api.service file instead.

[Unit]
Description=Caddy
Documentation=https://caddyserver.com/docs/
After=network.target network-online.target
Requires=network-online.target

[Service]
User=caddy
Group=caddy
ExecStart=/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/bin/caddy reload --config /etc/caddy/Caddyfile
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_BIND_SERVICE

[Install]
WantedBy=multi-user.target

d. My complete Caddyfile or JSON config:

{
    "apps": {
        "http": {
            "servers": {
                "srv0": {
                    "listen": [
                        ":443"
                    ],
                    "routes": [
                        {
                            "match": [
                                {
                                    "host": [
                                        "<redacted>"
                                    ]
                                }
                            ],
                            "handle": [
                                {
                                    "handler": "subroute",
                                    "routes": [
                                        {
                                            "handle": [
                                                {
                                                    "handler": "vars",
                                                    "root": "<redacted>"
                                                },
                                                {
                                                    "handler": "authentication",
                                                    "providers": {
                                                        "http_basic": {
                                                            "accounts": [
                                                                {
                                                                    "password": "<redacted>",
                                                                    "username": "<redacted>"
                                                                }
                                                            ],
                                                            "hash": {
                                                                "algorithm": "bcrypt"
                                                            },
                                                            "hash_cache": {}
                                                        }
                                                    }
                                                },
                                                {
                                                    "encodings": {
                                                        "gzip": {},
                                                        "zstd": {}
                                                    },
                                                    "handler": "encode"
                                                },
                                                {
                                                    "browse": {},
                                                    "handler": "file_server",
                                                    "hide": [
                                                        "/etc/caddy/Caddyfile"
                                                    ]
                                                }
                                            ]
                                        }
                                    ]
                                }
                            ],
                            "terminal": true
                        }
                    ]
                }
            }
        },
        "tls": {
            "automation": {
                "policies": {
                    "issuers": {
                        "acme": {
                            "module": "acme",
                            "ca": "<redacted>",
                            "email": "<redacted>",
                            "external_account": {
                                "key_id": "<redacted>",
                                "mac_key": "<redacted>"
                            }
                        }
                    }
                }
            }
        }
    }
}

3. The problem I’m having:

I’m not successfully getting caddy to accept the config. I’m unsure if it’s correct.

4. Error messages and/or full log output:

2021/02/17 15:31:11.619	INFO	using provided configuration	{"config_file": "/etc/caddy/Caddyfile.json", "config_adapter": ""}
validate: loading http app module: provision http: getting tls app: loading tls app module: decoding module config: tls: json: cannot unmarshal object into Go struct field AutomationConfig.automation.policies of type []*caddytls.AutomationPolicy

5. What I already tried:

I’m not really sure where to begin to troubleshoot. I think I’ve followed the instructions in the referenced topic above, but caddy complains :stuck_out_tongue:

6. Links to relevant resources:

Continuing the discussion from Custom ACME endpoint with authentication?

You seem to be using the caddy.service. If you plan on primarily using the API with JSON configuration, you should use the caddy-api.service instead (it ships with the package so you simply need to disable one and enable the other).

Hah, that’s an easy one to miss! issuers should actually be an array of objects, not an object. See in the docs:

"issuers": [{•••}],

The [ ] indicate this.

Ah, right, I missed that! As I also missed that policies also is an array, which I’ve now fixed. The config now validates properly, yey!

As for the caddy-api.service I’m not really sure I’ve understood the implications, but isn’t the api service meant to be used if you’re configuring caddy with it’s admin api? I’m using a Caddyfile (in json format) to get to all the keys needed for my ”special config” since I understood it as I can’t reach the external_account parts using a conventional Caddyfile (at least according to the previous thread). I may very well be mistaken, though.

Thanks a bunch for pointing me in the right direction!

Yeah you can do that with the Caddyfile, actually. See the eab field:

Ah, nice, that way I can have a config file that less tech savvy folks can understand and/or write :slight_smile:

A last question popped up (sorry if it’s too unrelated); is it possible to force a cert renewal with Caddy somehow? I’m trying to implement this third-party acme endpoint solution but I would like to test most situations that can arise, including cert renewals.
I was looking at ignore_loaded_certificates but I’m unable to decipher if it’s actually related to renewals as well.

You can delete it from storage and restart Caddy. The only difference between a fresh issuance and a renewal is that the same private key and account are used with the renewal.