Can't parse caddy JSON

1. Caddy version (caddy version):

v2.4.6

2. How I run Caddy:

Execute the exe on cmd

a. System environment:

Windows Server 2022 VM.

b. Command:

caddy run

curl "http://localhost:2019/config/" | jq

c. Service/unit/compose file:

Paste full file contents here.
Make sure backticks stay on their own lines,
and the post looks nice in the preview pane.

d. My complete Caddyfile or JSON config:

Paste config here, replacing this text.
Use `caddy fmt` to make it readable.
DO NOT REDACT anything except credentials.
LEAVE DOMAIN NAMES INTACT.
Make sure the backticks stay on their own lines.

3. The problem I’m having:

I want to get my caddy file as json (using the command, above). However, I get this error:

parse error: Invalid numeric literal at line 3, column 11.

If I use powershell, I get:

$s | ConvertTo-Json

An item with the same key has already been added:

4. Error messages and/or full log output:

5. What I already tried:

6. Links to relevant resources:

You didn’t properly fill out the help topic template. We can’t help you unless you do.

I’ve resolved this. The issue was with Powershell.

I am not sure on the jq error but maybe it’s a jq/Windows thing.

I do have a question:

The caddy json from the config endpoint would be the combination of all the caddyfiles, correct? Eg I will have seperate caddyfiles per site, and the config endpoint will be ocmbining all of this together.

Technically, you have one main Caddyfile, which may import other files. But yes, the caddyfile adapter produces a JSON config.

My last question regarding this. This is more of a scirpting question, but I will ask:

I want to get upsteams for a particular host I reverse proxy to. What is the most efficient way to do this? I looked at the API docs, I can get a list of all upstreams or traverse the json doc. Ipen to any suggestions!

EDIT: I’ve solved this challenge using a custom console app in C#, but I am interested in approaches!

I don’t understand the question. Please show examples of what you’re trying to do. Please explain in detail. Your question is too vague to answer specifically.

Ok so take the caddy json below:

{
  "apps": {
    "http": {
      "servers": {
        "srv0": {
          "experimental_http3": true,
          "listen": [
            ":443"
          ],
          "routes": [
            {
              "handle": [
                {
                  "handler": "subroute",
                  "routes": [
                    {
                      "handle": [
                        {
                          "handler": "reverse_proxy",
                          "transport": {
                            "keep_alive": {
                              "idle_timeout": 1000000000
                            },
                            "protocol": "http",
                            "tls": {
                              "server_name": "killergaming-serverautomation-dev.gssira.com"
                            }
                          },
                          "upstreams": [
                            {
                              "dial": "192.168.3.129:443"
                            }
                          ]
                        }
                      ]
                    }
                  ]
                }
              ],
              "match": [
                {
                  "host": [
                    "killergaming-serverautomation-dev.gssira.com"
                  ]
                }
              ],
              "terminal": true
            }
          ]
        }
      }
    },
    "tls": {
      "automation": {
        "policies": [
          {
            "issuers": [
              {
                "challenges": {
                  "dns": {
                    "provider": {
                      "api_token": "VqljlYA_iccSJluIhz3WGdS6gIngsvF-BUgY1KsL",
                      "name": "cloudflare"
                    }
                  }
                },
                "email": "gurdip.sira@gmail.com",
                "module": "acme"
              },
              {
                "challenges": {
                  "dns": {
                    "provider": {
                      "api_token": "abc",
                      "name": "cloudflare"
                    }
                  }
                },
                "email": "abc",
                "module": "zerossl"
              }
            ],
            "subjects": [
              "killergaming-serverautomation-dev.gssira.com"
            ]
          }
        ]
      }
    }
  },
  "logging": {
    "logs": {
      "default": {
        "level": "DEBUG"
      }
    }
  }
}

I have crossed out a few sensitive details.

However, going forward I am going to have further sites to load balance. Eg, b.gssira.com, c.gssira.com, etc. They will have the same upstreams (IIS servers), as they are production sites.

I will also have the equivalent sites for dev and uat environments, with their own set of 2-3 backend servers.

From the documentation to patch the configuration, I want to remove an upstream that belongs to one url only, and not remove that upstream for ALL urls using it.

The following url will get me the upstream: http://localhost:2019/config/apps/http/servers/srv0/routes/0/handle/0/routes/0/handle/0/upstreams/0/dial

However, in that url, nowhere do I say I am interested in the upstreams for ONLY site “a.gssira.com”. This is what I’d like to do.

It’s up to you to fetch the current config, navigate through it, then determine what operations you want to perform.

You could also just modify the JSON yourself then push the whole modified config back up. It’s pretty much the same thing.

1 Like

Sorted this too with some custom C# to parse the JSON.

A quick question whcih is not related to this. The caddy server listens on localhost. How can I bind it to the name of the server itself? As I’d like to access the config endpoint remotely.

You’re asking about the admin endpoint? Change the admin config. See the docs.