-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Directive "log - output file" on one site address causes log output from another site address to dump to the console #4877
Comments
This is kind of working as intended 🤔 Here's what's happening: Caddy is listening on So if you add a Basically, the behavior for logging for an unspecified host is undefined, so 🤷♂️ Technically, the server is doing what it is supposed to do. I can see how it's non-obvious though. Maybe we could tune the Caddyfile adapter here. |
I wonder if the logging config should accept matchers like routes do. Right now we have this clunky skip-host-oriented thing... |
I think #4691 might solve this by providing a workaround. You could add |
@francislavoie Hmm, but this issue already has a workaround (simply by specifying the site name you don't want logged). (It's late though so I might be misunderstanding.) That does remind me I need to get around to that PR... |
With respect to #4689, #4690 and #4691, my expectation would be for something a little different. It seems more intuitive that there would exist an explicit "skip_hosts" option under the "log" directive, like:
such that the specified "host_list" would be in addition to the current, automatically determined, list of hosts for Reading at https://caddyserver.com/docs/caddyfile/matchers#syntax ,
I don't really see the proposed Wouldn't it be fairly straightforward to parse a |
What I was suggesting is that you would put the I don't think |
That part is not broken. There was no "localhost" site log being generated. Caddy did just what was promised. There is nothing to "fix" there.
Well, in that case, the workaround described - an "empty" site block for any site that was being improperly logged - already works fine. Since this remedy already works, the problem would be, instead, a documentation issue. The thing that was awkward in my case was that the log for "127.0.0.1" was unexpectedly being dumped to the console. If, instead, there was a log for "127.0.0.1" being unexpectedly written to "/var/log/caddy/", that would not have been as much of a problem. I was surprised to see that the json configuration had a "logging" block at the "top level", separate from any site definition below. The "logging" block itself included a "writer" block with an explicit That just made the log dump to the console that much more unpredictable. It may be useful to determine why caddy was dumping to the console instead of creating an unexpected log file. An alternative resolution could be to, instead of an explicit This approach would also generate logs for any site in the list even if that site were not anywhere otherwise defined in the Caddyfile. Of course, an actual log could only be generated if caddy was also binding to some interface having the corresponding site IP address or DNS hostname. Though still, that would also serve as a kind of "misconfiguration check", if any log were to unexpectedly appear for some site that should not exist, supposing that that "stray" site host had actually been added to the list for some reason. For the moment, it seems prudent for an administrator to simply review the JSON config structure for It just seems a bit counterintuitive at first, to have a distinct "logs" configuration block. If I understand, it is not possible for caddy to have different logging schemes for different sites, which otherwise seems would be possible if caddy were to keep a custom "logging" definition below each site |
Ah my bad, misunderstood the problem then. Sorry. I think what we could do is adjust the Caddyfile adapter to add a
That's because logging in Caddy is for all facilities, not just access logs. Access logs are namespaced as |
Would that have to be both a You cannot "skip" a site hostname or site IP address when you do not know that it exists, as in the case where "localhost" is defined and "127.0.0.1" is not defined. You would have to start with the rule "Do not log a site unless the site is defined", and only then, can you limit the set of defined sites with another rule saying "Do not log a defined site that is specified as a Hmm - with a little more testing, I notice that caddy is listening on all interfaces! This is not actually documented at https://caddyserver.com/docs/getting-started , https://caddyserver.com/docs/command-line , https://caddyserver.com/docs/caddyfile-tutorial , https://caddyserver.com/docs/caddyfile/concepts , or especially, at https://caddyserver.com/docs/caddyfile/concepts#addresses ! This is totally surprising and actually counterintuitive behavior, given the priority that the Caddyfile gives to the "Site address", as the prefix to a site definition block! The only comment about caddy binding to all interfaces is at https://caddyserver.com/docs/caddyfile/directives/bind , several layers down in the Caddy menu structure! So now, I see that access to any interface not specifically defined in Caddyfile will cause caddy to spew logging data to the console! This has nothing to do with DNS/resolver mapping "localhost" to "127.0.0.1". Effectively, the Caddy, then, has this awkward characteristic of requiring the same site address to be defined in two different places, even though one site address should be inferred from the other site address. This is not good. Rather, I would expect that, wherever it is that this
Aha! Ok, thanks. It's a more general approach. Of course, that does not justify "wildcard" binding to all network interfaces, or justify dumping "phantom" logs to the console. |
No,
Actually that's exactly what I'm suggesting we do, i.e. add the So basically, taking this Caddyfile:
which adapts to this JSON {
"apps": {
"http": {
"servers": {
"srv0": {
"listen": [
":80"
],
"routes": [
{
"match": [
{
"host": [
"10.0.0.2"
]
}
],
"handle": [
{
"handler": "subroute",
"routes": [
{
"handle": [
{
"body": "ip",
"handler": "static_response"
}
]
}
]
}
],
"terminal": true
},
{
"match": [
{
"host": [
"localhost"
]
}
],
"handle": [
{
"handler": "subroute",
"routes": [
{
"handle": [
{
"body": "localhost",
"handler": "static_response"
}
]
}
]
}
],
"terminal": true
}
],
"logs": {
"skip_hosts": [
"localhost"
]
}
}
}
}
}
} I would make this change to the generated output (scroll down): {
"apps": {
"http": {
"servers": {
"srv0": {
"listen": [
":80"
],
"routes": [
{
"match": [
{
"host": [
"10.0.0.2"
]
}
],
"handle": [
{
"handler": "subroute",
"routes": [
{
"handle": [
{
"body": "ip",
"handler": "static_response"
}
]
}
]
}
],
"terminal": true
},
{
"match": [
{
"host": [
"localhost"
]
}
],
"handle": [
{
"handler": "subroute",
"routes": [
{
"handle": [
{
"body": "localhost",
"handler": "static_response"
}
]
}
]
}
],
"terminal": true
- }
+ },
+ {
+ "handle": [
+ {
+ "handler": "skip_log",
+ }
+ ]
+ }
],
"logs": {
"skip_hosts": [
"localhost"
]
}
}
}
}
}
} Since the
Not really. Most users actually want to bind to all interfaces. Like if you want to accept traffic from internal services running on the same machine, etc. You can use the
You're right, we should document it in the site addresses section to mention the address is not the bind/listener. They are different things. The address produces a request matcher (which in turn affects whether automatic HTTPS triggers, and affects what the logger host will be, etc).
Yeah, that's not its job. The site address does the port part. The bind does the IP interface part.
No, we have, this is intended.
Like I said, the bind address and the domain/site address are not the same thing, and we cannot assume that they are the same thing. That's not a safe assumption to make. |
Ah!
Hmm - then, it would be possible to specify a specific What is the use case for that? And related - why not simply specify the
Thanks! I missed that one. Ok, that makes more sense, having the I suggest that this issue of interface binding should go "right up front" in the documentation, perhaps even being the first section linked under "Quick-starts", including mention of the distinction between "site address" and "bind interface". Interface binding is a pretty fundamental element of any protocol server, especially when that interface can include a unix socket. On a tangent, being able to bind to a unix socket can be very useful when using Network Namespaces in Linux, when you might also want a local interface that is not defined by the network. http over a unix socket can also be useful with Docker Containers and simply for secure local server access, as in the example. Of course, a custom http client may be needed for unix socket access, but Similarly, https://caddyserver.com/docs/api , does not currently provide any examples of http access over a unix socket, even though is does mention specifically "configuring the endpoint to bind to a permissioned unix socket". |
Ish. If someone makes a request to Obviously this is contrived, but the point stands, they are different concepts and binding them together is not a good idea because it would limit what people could do with Caddy. It's at different layers of the networking stack. If you configured the site address with a domain (which is what most users do) then there's no IP interface that you can glean from that for
I think you're greatly overestimating how much users care about this. It's not as important as you think it is. A huge majority of users don't care to configure But like I said, we will adjust the Caddyfile Concepts page's Addresses section to mention it, you made a valid point there. But it absolutely doesn't make sense in the Getting Started guide. It's very much a technical detail that most people don't care about.
Yep, the |
Yes, I was conceding that point. That's why I suggested, simply specify the bind interface explicitly, by name. Then there's no reason to go down that philosophical rabbit hole.
That's what a DNS lookup does. There would be no reason to configure the site address with a domain or host name, unless the name would actually resolve to a functioning IP address. The more significant point is that caddy itself must then finally associate that IP address with an actual socket interface - yes? So just use the interface name. But then, the counter argument will be that a unix socket does not have an interface name in the same sense as a network socket. And the response to that is, then just allow a unix socket path to be used as the interface name. And the response to all that is: Feature Request - maybe caddy could accept a network interface name as an additional type of value to the
Ha! Yes, fair point, very likely. I can only say that it's important to me, and I really appreciate your taking the trouble to clarify. And hopefully a few useful pointers can make their way into the online documentation.
It's easier - well, for some people - when "gotcha issue" warnings are easy to find. Of course, other people do not have to read about binding and interfaces and sockets, if they're not interested. Maybe a link could go into the side-bar menu? Don't make it hard to find.
That's not what I meant. The bind docs unix socket example is "To bind to a Unix domain socket at /run/caddy: That took a bit of trial and error. There should also be a note there about the http "host" header and its interaction with the The hostname "none" is just some arbitrary string, and Using the But, if instead, the
Yet, with that
It's confusing and seems finicky, and I probably don't understand what Maybe |
Except that the server's view of DNS does not necessarily match the client's. For example, the server might be in a private network which has a DNS resolver that resolves the domain to a private IP address, so that clients in the private network get a direct connection to the server, while clients from the internet see a public IP address. This is not uncommon at all, lots of users who run Caddy in their home network do this, because their routers don't support NAT hairpinning so it's the only way they can get their LAN devices to connect to their self-hosted server. Using DNS typically causes problems for more users than I think it would help -- we play with DNS resolvers for the DNS challenge, and some users have trouble with that, since they end up needing to configure an alternate resolver for the result to make sense, etc. Gets complicated real fast. I think many users would be surprised if we automatically used what their domain as the bind host, and it would be very non-obvious what the problem would be if they have issues, because it would be pretty hidden to them unless they understand what commands to run to see what interfaces are in use. We're careful with what we do automatically. It's a balance between visibility/transparancy and "ease of use".
We do.
Re interface names, it's not really "for free", cause you need to get the interface with Anyways, open to the idea but it needs some careful design. It's not that easy, I'm sure there will be some tricky implementation details to work out. FWIW I'm not that interested in working on that myself, I would get no benefit from it personally and I'm just volunteering my time for this project. So someone else would need to contribute it.
They have already, I added a note to the end of https://caddyserver.com/docs/caddyfile/concepts#addresses mentioning
I'll let @mholt follow up on that, he plays with that stuff more than I do |
Ah! Ok, thanks. It's complicated.
Right - that was in the bind docs. More like I was "thinking out loud" there. Other than raising the question about using interface names, I was just recognizing the generality of caddy. I don't know about other web servers, but I'm fascinated with its ability to serve to a local unix socket. I only just tried it.
And then:
Ha! And this also works:
But that's just a one-shot, and hyperlinks will not work, of course. I haven't found a browser that will attach to a unix socket, though lots of people talk about it. At least one issue is that people don't agree on a URL format. My preference is based on the "socket path as port" approach, using ":" delimiters, as in "http://unix:/var/run/server/ht.socket:/path/to/resource.html". Here, the nonstandard "domain" part invokes a special handler, but the domain name seems obvious from the socket type, "Unix Domain Socket". I suppose that a similar approach could be used for an "Interface Name" URL, something like "http://interface:enp4s0:/path/to/resource.html". But then, there is no browser to accept a URL like that, and the interface might as well have an IP address anyway.
It's not a big deal, once I learn how Caddy does things. But I have run into a few more small surprises, after adding explicit
and caddy has to be stopped and restarted, which is easy enough, just not expected. With the explicit But I'm wondering again about this Caddy distinction between a "site address" and a "bind address". Creating an empty site block for 127.0.0.1 in the Caddyfile does not help here, and caddy will fail with:
Even an explicit
I'm confused by the
But caddy will not accept "two sites on the same port", and still fails with the same error:
Assigning a different port to 127.0.0.1 does not help, since the browser is still accessing 127.0.0.1:80:
And now I'm back to questioning the assertion about distinguishing a "site address" and a "bind address":
Caddy is not making a distinction between "localhost" and "127.0.0.1", since both "sites" are using the same port 80. Maybe the description in the |
@thx1111 This is still on my list just so you know. Sorry; been really busy lately. |
@mholt Thanks Matt. While the Caddy configuration file tends to be finicky, I do have a working configuration now. Any improvements you are able to provide will add robustness and avoid confusing surprises for new users. |
I'm going to close this. I'm not seeing anything actionable here. Since this was last discussed, the |
caddy 2.5.1-1 on Arch Linux
From https://caddyserver.com/docs/caddyfile/concepts :
Then,
sudo caddy start --config /etc/caddy/Caddyfile
and point the browser to http://127.0.0.1 . The browser will display a blank page, and the console from which "caddy start" was run will spew logging output for..., "host": "127.0.0.1", ...
!Logging for the other sites,
http://localhost
andhttp://10.0.0.2
, works as anticipated.Log output to the console is not expected and not wanted.
Adding a gratuitous
to the Caddyfile changes
"logs":{"logger_names":{"10.44.0.20":"log0"},"skip_hosts":["localhost"]}
to"logs":{"logger_names":{"10.44.0.20":"log0"},"skip_hosts":["localhost","127.0.0.1"]}
in the json config structure, which is an effective workaround.But still, should that workaround be necessary? Or simply documented?
The text was updated successfully, but these errors were encountered: