Caddy never stops

  1. Caddy v2.5.2 on OSX

  2. running caddy directly on the mac ( I didn’t run brew services start caddy). Following the docs to reverse proxy a server pushing SSE on localhost:4043 (Elixir http/2). I test the backend with curl https://localhost:4043/sse directly (it’s ok) and expected to test via Caddy with ..:5043/sse.

  • firstly with caddy reverse-proxy --from localhost:5043 --to localhost:4043 but this gave me “start: tcp: listening on :80: listen tcp :80: bind: address already in use”.
  • then tried with a Caddyfile and caddy run --config Caddyfile, which gave me:
    “listen tcp 127.0.0.1:2019: bind: address already in use” ??
:5043 {
  reverse_proxy 127.0.0.1:4043
}
  1. Problem: obviously, this is completely wrong, but just following the doc. However, Caddy never stops. It restarts continuously after a kill. caddy stop does nothing neither. A kill -9 or -2 pid where pid = lsof -i:5043 or pid = lsof -i:2019 just makes Caddy to restart.

  2. Only possibility to stop Caddy = uninstall it to stop this.

Please fill out the help topic template, as per the forum rules.

This means you probably have another web server running on your machine using port 80. Turn that off so Caddy can use it.

Keep in mind that doing --from localhost:5043 will try to set up Caddy to run with HTTPS (because Caddy is HTTPS by default), which means it will try to also set up automatic HTTP->HTTPS redirects, which uses port 80.

If you don’t want this, then either put http:// in front of the address to only use HTTP, or use a Caddyfile and turn off auto_https features using the global option.

This means Caddy is already running (or something else already using port 2019). Caddy uses this for its admin endpoint.

Then you must have Caddy running as a service somehow. Caddy doesn’t have a mechanism to automatically restart itself on its own.

This means you probably have another web server running on your machine using port 80. Turn that off so Caddy can use it.
This means Caddy is already running (or something else already using port 2019). Caddy uses this for its admin endpoint.

Yes, thanks, I followed you and restarted everything, clean sheet.

Keep in mind that doing --from localhost:5043 will try to set up Caddy to run with HTTPS (because Caddy is HTTPS by default), which means it will try to also set up automatic HTTP->HTTPS redirects, which uses port 80.

Yes this is what I want.
The server has his own self-signed certificates (from mkcert) and can run http2.

I am not trying to serve files. I am pushing SSEs from servers to clients in the browser so I want a continuation between the browser and back-end servers through Caddy, all along with http2.
The backend server only responds at https://localhost:4043/sse, not to http://localhost:4043 for example.

I can run caddy start --config Caddyfile and I can caddy stop. Good!

> caddy run --config Caddyfile

# Caddyfile
:5043 {
	reverse_proxy /sse 127.0.0.1:4043/sse
}
...
Successfully started Caddy (pid=9212) - Caddy is running in the background

Caddy listens on 2019 and on port 5043 (same PID as per lsof -i:)

However when I curl to 5043/sse, it don’t get the expected response:

> curl https://localhost:5043/sse

*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 5043 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* error:1400410B:SSL routines:CONNECT_CR_SRVR_HELLO:wrong version number
* Closing connection 0
curl: (35) error:1400410B:SSL routines:CONNECT_CR_SRVR_HELLO:wrong version number

I understand that I is some resolving issues and may need a proper server name. Probably need more knowledge.

At least I found two articles in the wiki, this one and that one.

Here, I think you’re talking about the upstream server. That’s not the same thing.

The --from is the address Caddy listens on. The --to is the upstream’s address.

Caddy is HTTPS by default for the “from” address. But the proxy is HTTP by default (because typically services are within your network, and encryption is no longer needed since you’re in a trusted network).

Caddy will be issuing its own certificate for localhost, using its internal CA (similar to mkcert, except it’s built into Caddy and it’s automated). Caddy will attempt to install the root certificate of its CA to your system’s trust store, but that may fail. And if you’re making requests from other machines, you’d need to install the root CA cert to those machines manually, to establish trust.

If you want to proxy over HTTPS, you need to use https:// for the upstream address. But also, keep in mind that the upstream server might have Host header matching, so you may need to override the Host header as well to make it connect correctly. See the docs: reverse_proxy (Caddyfile directive) — Caddy Documentation

There’s a few things wrong here.

First, you didn’t specify a domain name, so Caddy won’t be able to automatically issue a certificate (as I explained above). If you specified localhost:5043 instead, it would do so.

For the proxy, keep in mind that your /sse matcher will only match exactly /sse and not /sse/foo. Path matching is exact in Caddy. You might want /sse* if different paths may be used. You probably don’t need the path matcher at all though, if this is all you’re serving on this site.

Also, you cannot specify a path in the upstream address. It must be just a host and port, with an optional scheme. If you need to change the path prefix, then you should use a rewrite. But I don’t think you need that here.

All that said, I don’t think you need the complexity of serving your upstream app over HTTPS, since Caddy will terminate TLS to the client. If you do HTTPS to Caddy, then HTTPS to the upstream, that’s actually two separate TLS connections, not just one. Since the upstream is running on the same machine, there’s no real benefit to that, it’s just more overhead.

2 Likes

Thank you.

you didn’t specify a domain name, so Caddy won’t be able to automatically issue a certificate (as I explained above). If you specified localhost:5043 instead, it would do so.

I did try but when I do use localhost:5043, then I get:

listen tcp :80: bind: address already in use
start: caddy process exited with error: exit status 1

whilst lsof -i:80 is void.

I don’t think you need the complexity of serving your upstream app over HTTPS, since Caddy will terminate TLS to the client.

Yes, indeed, I should have explained my intentions more clearly. I needed HTTPS because I wanted HTTP/2 because it’s SSE, limited with HTTP. But even If Caddy is upfront, I might still need HTTP/2 from the upstream server througn Caddy to the client. Because I thought it might be a mess between all certificates, I was hesitating to put a reverse-proxy but I need 2 servers.
I will check also the headers. Thanks for your time.

Are you sure you don’t have something like Apache or Nginx running?

Like I said, you can turn off listening on port 80 via the auto_https global option:

You could use h2c:// to do HTTP/2 from Caddy to your upstream, without TLS.

2 Likes

Please run with sudo and try again.

1 Like

Indeed, httpd is there. Great! Didn’t understood…

Wiki for osx:

sudo launchctl unload /System/Library/LaunchDaemons/org.apache.httpd.plist 2>/dev/null

so now I can hide the servers and it remains to let the browser trust Caddy’s certificates I believe.