How to listen both http & https with Unix socket

1. Caddy version (caddy version):

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

2. How I run Caddy:

a. System environment:

Mac 11.1

b. Command:

caddy run --config CONFIG

c. Service/unit/compose file:

N/A

d. My complete Caddyfile or JSON config:

N/A

3. The problem I’m having:

I would like to run Caddy on HTTP with unix socket http.sock and on HTTPS with unix https.sock. How would I express it in Caddyfile?

4. Error messages and/or full log output:

Both http.sock and https.sock are served with HTTPS.

5. What I already tried:

N/A

6. Links to relevant resources:

N/A

This relevant section of the docs should have the answer: Conventions — Caddy Documentation

Perhaps I wasn’t clear. I want Caddy to serve both HTTP and HTTPS requests with two different Unix sockets.

{
  "admin": {
    "listen": "127.0.0.1:22019"
  },
  "apps": {
    "http": {
      "servers": {
        "candy": {
          "listen": [
            "unix//tmp/http.sock",
            "unix//tmp/https.sock"
          ],
          "routes": [
            {
              "handle": [
                {
                  "handler": "reverse_proxy",
                  "transport": {
                    "protocol": "http"
                  },
                  "upstreams": [
                    {
                      "dial": "192.168.64.36:30784"
                    }
                  ]
                }
              ],
              "match": [
                {
                  "host": [
                    "app1.test"
                  ]
                }
              ],
              "terminal": true
            },
            {
              "handle": [
                {
                  "handler": "reverse_proxy",
                  "transport": {
                    "protocol": "http"
                  },
                  "upstreams": [
                    {
                      "dial": "192.168.64.36:31525"
                    }
                  ]
                }
              ],
              "match": [
                {
                  "host": [
                    "app2.test"
                  ]
                }
              ],
              "terminal": true
            }
          ]
        }
      }
    },
    "tls": {
      "automation": {
        "policies": [
          {
            "issuers": [
              {
                "module": "internal"
              }
            ],
            "subjects": [
              "app1.test",
              "app2.test"
            ]
          }
        ]
      }
    }
  }
}

When curl --unix-socket /tmp/http.sock http://app1.test, I got Client sent an HTTP request to an HTTPS server. But with curl --unix-socket /tmp/http.sock https://app1.test, Caddy works as expected. AFAICT, there is no way to tell a unix socket to serve HTTP or HTTPS. All unix sockets serve HTTPS requests only.

1 Like

I don’t have much time right now, but before I loop back into this I’m just curious: why do you need both HTTP and HTTPS on unix sockets?

@matt:

why do you need both HTTP and HTTPS on unix sockets

I want to do something similar to GitHub - sstephenson/launch_socket_server: Bind to privileged ports on OS X without running your server as root to let Caddy accept connections on ports < 1024 with launchd. The idea is to have a “launch_socket_server” to proxy port 80 and port 443 requests to two different unix sockets and Caddy listens to these two unix sockets coordinately for HTTP and HTTPS requests.

Is there a reason that Caddy can’t serve HTTP on a Unix socket? Perhaps Conventions — Caddy Documentation needs a way to specify whether the unix socket path is for HTTP or HTTPS.

I think the problem is that you’re trying to use one server for both HTTP and HTTPS. You can’t really do both on a single server (as in, apps/http/servers in your config). There’s nothing there to tell Caddy to not serve HTTPS on one of them.

So I think you need to make one server for your HTTP listener socket, and a 2nd for HTTPS. And on your HTTP one, I think you’ll need to set "automatic_https": {"disable": true}.

1 Like

Yeah, Francis beat me to it; but a server can either serve HTTP or HTTPS, it can’t do both (well, not without protocol sniffing) (with the single exception of knowing not to serve HTTPS on the HTTP port, if listening on both - but unix sockets are not ports).

Automatic HTTPS is what is enabling HTTPS on your server: Automatic HTTPS — Caddy Documentation

So as Francis said, you’ll need to disable it if you want to run HTTP.

Cool, I will check out splitting into two servers. FWIW, if I listen on ports instead (:80 and :443), I was able to get both HTTP & HTTPS to work with one server and I wouldn’t need to disable automatic_https.

{
  "admin": {
    "listen": "127.0.0.1:22019"
  },
  "apps": {
    "http": {
      "servers": {
        "candy": {
          "listen": [
            ":80",
            ":443"
          ],
          "routes": [
            {
              "handle": [
                {
                  "handler": "reverse_proxy",
                  "transport": {
                    "protocol": "http"
                  },
                  "upstreams": [
                    {
                      "dial": "192.168.64.36:30784"
                    }
                  ]
                }
              ],
              "match": [
                {
                  "host": [
                    "app1.test"
                  ]
                }
              ],
              "terminal": true
            },
            {
              "handle": [
                {
                  "handler": "reverse_proxy",
                  "transport": {
                    "protocol": "http"
                  },
                  "upstreams": [
                    {
                      "dial": "192.168.64.36:31525"
                    }
                  ]
                }
              ],
              "match": [
                {
                  "host": [
                    "app2.test"
                  ]
                }
              ],
              "terminal": true
            }
          ]
        }
      }
    },
    "tls": {
      "automation": {
        "policies": [
          {
            "issuers": [
              {
                "module": "internal"
              }
            ],
            "subjects": [
              "app1.test",
              "app2.test"
            ]
          }
        ]
      }
    }
  }
}

Sounds good.

Yep, that’s because of this:

The server is serving HTTPS, but it also knows that the standardized HTTP port is 80, so it will not enable HTTPS on that port. This allows you to specify both HTTP and HTTPS versions of your site more conveniently. But with unix sockets, there is no such convention.

1 Like

This topic was automatically closed after 30 days. New replies are no longer allowed.