Reverse proxy to docker daemon api: "Client sent an HTTP request to an HTTPS server"

1. The problem I’m having:

trying to use caddy on a vm host server as a reverse proxy to an insecure docker daemon on a vm using url rewrite, but i’m getting “Client sent an HTTP request to an HTTPS server” when i run docker commands.

my host server is named heart and the vm is named aorta

the caddy site (heart.home.lan:2376) is configured to use internal tls and is configured to proxy traffic to the vm via the vm’s hostname and insecure daemon port (aorta:2375).

i’m using handle_path in my caddyfile because i want my requests to the daemon to be path’d so i can run multiple reverse proxies to multiple daemons. i.e. i plan to also launch a vm named vena-cava. so, my daemon urls would work like this:

  • heart.home.lan:2376/aorta/docker → aorta:2375
  • heart.home.lan:2376/vena-cava/docker → vena-cava:2375

note, i can successfully run docker commands against the vm, directly:

> .\docker.exe -H aorta:2375 info
 Version:    24.0.2
 Context:    default
 Debug Mode: false

 Containers: 0
  Running: 0
  Paused: 0
  Stopped: 0
 Images: 0
 Server Version: 24.0.5
 Storage Driver: windowsfilter
 Logging Driver: json-file
  Volume: local
  Network: ics internal l2bridge l2tunnel nat null overlay private transparent
  Log: awslogs etwlogs fluentd gcplogs gelf json-file local logentries splunk syslog
 Swarm: inactive
 Default Isolation: process
 Kernel Version: 10.0 20348 (20348.859.amd64fre.fe_release_svc_prod2.220707-1832)
 Operating System: Microsoft Windows Server Version 21H2 (OS Build 20348.1850)
 OSType: windows
 Architecture: x86_64
 CPUs: 12
 Total Memory: 950.9MiB
 Name: aorta
 ID: d8a521ff-96c1-4746-b02f-3f20dc1b57c6
 Docker Root Dir: C:\ProgramData\Docker\data-root
 Debug Mode: false
 Experimental: false
 Insecure Registries:
 Live Restore Enabled: false
 Product License: Community Engine

WARNING: API is accessible on without encryption.
         Access to the remote API is equivalent to root access on the host. Refer
         to the 'Docker daemon attack surface' section in the documentation for
         more information:

2. Error messages and/or full log output:

> .\docker.exe -H heart.home.lan:2376/aorta/docker info
 Version:    24.0.2
 Context:    default
 Debug Mode: false

ERROR: Error response from daemon: Client sent an HTTP request to an HTTPS server.
errors pretty printing info

3. Caddy version:

> caddy.exe version
v2.6.4 h1:2hwYqiRwk1tf3VruhMpLcYTg+11fCdr8S3jhNAdnPy8=

4. How I installed and ran Caddy:

a. System environment:

windows server core 2022
direct install (not installed in a container or vm)

b. Command:

i run caddy as a windows service with this command:

"D:\Program Files\Caddy\caddy.exe" run --adapter caddyfile --config "D:\ProgramData\Caddy\Caddyfile"

c. Service/unit/compose file:

> sc.exe qc caddy
[SC] QueryServiceConfig SUCCESS

        TYPE               : 10  WIN32_OWN_PROCESS
        START_TYPE         : 2   AUTO_START
        ERROR_CONTROL      : 1   NORMAL
        BINARY_PATH_NAME   : "D:\Program Files\Caddy\caddy.exe" run --adapter caddyfile --config "D:\ProgramData\Caddy\Caddyfile"
        LOAD_ORDER_GROUP   :
        TAG                : 0
        DISPLAY_NAME       : caddy
        DEPENDENCIES       :
        SERVICE_START_NAME : LocalSystem

d. My complete Caddy config:

    admin off
    log {
        format json {
            time_format iso8601
        output file "D:\ProgramData\Caddy\caddy.log" {
    storage file_system "D:\ProgramData\Caddy"

heart.home.lan {
    respond "Hello, world!"
    tls internal

heart.home.lan:2376 {
    handle_path /aorta/docker {
        reverse_proxy http://aorta:2375
    tls internal

5. Links to relevant resources:

You probably need to specify https:// ?

I don’t know anything about Docker’s -H flag, I’ve never used it.

I don’t know anything about the Docker API, but please read The "subfolder problem", OR, "why can't I reverse proxy my app into a subfolder?", you may have an easier time by using subdomains instead of subpaths for each, to avoid messing around with URLs.

Also you only used /aorta/docker as your path matcher, which will only match exactly that path and nothing else, so you might need to add a * as a suffix to match paths below that.

-H doesn’t accept https on the hostname, just a socket type (e.g. tcp:// or npipe://, etc.). however, your suggestion made me realize i need to explicitly tell docker to use tls via --tls --tlscacert ... like this:

.\docker.exe -H heart.home.lan:2376/aorta/docker --tls --tlscacert C:\Users\Administrator\heart.home.lan.crt info

where heart.home.lan.crt is the cert chain caddy generated for the site.

1 Like

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