Are nested caddyfile blocks possible?

Me again. Having a hard time parsing through a structure like this:

example.com {
  oauth /admin {
    login_path /login
    cookie_secret abcdefg
    github {
      client_secret abcdefg
      client_id abcdefg
      callback_path /ghcb
    }
    google {
      client_secret hijklm
      client_id hijklm
      callback_path /goocb
    }
  }
}

I do an outer level for c.NextBlock() loop, but then when I get to the provider specific blocks, I’m not sure if there’s a way to do another NextBlock() loop to read the inner keys. Is there an example of this somewhere?

The Caddyfile parser doesn’t really support nested blocks (intentionally - flat configs mean simpler configs which is a goal) – can you flatten the subdirectives? e.g. github_client_secret

That’s possible, but I don’t love it. For each provider there are top-level common fields, but also potentially provider specific things (specific users or groups to check for access maybe). Having them grouped looks a lot better to my eye maybe.

Flattening could work, it would just require a little more collecting stuff to make sure I got it all before I fully initialize the provider itself. May not be a problem.

But using the github_xxx style would remove the possibility of supporting multiple providers of the same type. Not sure exactly the use case, but perhaps I have a second application to use for admin access, or one that requires different scopes perhaps.I have blocked multiple providers of the same type for now, but this way would likely ensure that is a permanent restriction.

As for grouping, they can still be grouped visually by putting an empty line before the group, I suppose.

You have complete control over subdirectives, so to handle multiple providers of the same types, perhaps custom or dynamic subdirectives make sense? Like a mapping. A user could define the provider types/names they have and then use those as the subdirective name. In other words, your users could define a github provider with a name gh1 for example, and then use gh1_client_secret for example.

I do see in your case how having a nested block could be useful but I am not sure if it generalizes well; we tried it with log rolling directives and it was kind of ugly.

Perhaps this is a solved issue now, but

@captncraig a while back you were suggesting a Caddyfile structure like this

oauth github {
 clientId ...
 clientSecret ...
 scopes user,repo
 path /foo #will require auth
 path /bar
 login_url /oauth/login # route to initiate oauth flow
 callback_url /oauth/callback
 cookie_secret aslkfjaslk;fjals;kfjlask;fj
 redirect_when_blocked /login #your page to show if they get redirected from a protected page
}    

from https://github.com/mholt/caddy/issues/246

I think if this could be done it serves both purposes, being quite elegant and not requiring sub nesting