Example: TP-Link Omada Controller

I spent some time today building a Caddyfile example for TP-Link Omada Controller software. Decided to share (and so fellow Googlers might save themselves some headaches going forward).

CaddyFile:

(snippet) {
        header {
                Strict-Transport-Security "max-age=31536000; includeSubdomains"
                X-XSS-Protection "1; mode=block"
                X-Frame-Options "DENY"
                -server
        }
        tls me@email.com {
                dns cloudflare {env.CLOUDFLARE_API_TOKEN}
        }
        log {
                output file /data/logs/caddy.log {
                        roll_size 20MiB
                        roll_keep 5
                }
        }
}

omada.url.com {
        reverse_proxy https://1.2.3.4:8043 {
                transport http {
                        tls_insecure_skip_verify
                }
                header_up Host "omada.url.com:443"
        }
        import snippet
}

Few things to note:

  1. I forward 8043 > 443 in my docker config. I used to do 8043>8043 but my setup changed that wouldn’t allow for that.
  2. set 1.2.3.4 to your Omada controller. Also check your controller’s HTTPS port - the default for docker is 8043, which is what I’m using, personally. To confirm - you should be able to navigate to https://1.2.3.4:8043 (replacing with your values) and the controller should work great. If it doesn’t, this won’t work either.
  3. My snippet has some me-specific things that might not apply to you (Cloudflare DNS challenge, for example).
  4. Set your Omada Controller Hostname/IP in the controller to be omada.url.com:443
  5. You MUST use the header_up host header modification. It modifies the host header sent to the Omada controller to append the :8043 port. If this port isn’t in the host header, the Omada 302s the request to ensure HTTPs is being used (what a silly design, but whatever).
  6. An FYI - tls_insecure_skip_verify is inherently insecure. But since I trust the source, I’m not personally concerned. Ideally you would instead specify tls_trusted_ca_certs to trust the known certificate from the upstream. And the most ideal situation would be to add a valid cert to your Omada controller.

With this in place, my TPLink Omada Controller loads up great via Caddy!

5 Likes

What version of the Omada Controller are you running?

I’m not having any luck with the posted config, have you made any updates?

Hey @warllo, I’d suggest you might want to start a Help post and fill out some details. Link to this wiki page when you post it, but still fill out all the relevant information; we’d be much better equipped to sort out whatever issue you’re running into this way.

2 Likes

Eventually got it working for me, had to use tls_insecure_skip_verify to get it to work.

Sorry (also sorry for not seeing this!), not sure what happened when I’d pasted the original post - updated it, and can confirm you need tls_insecure_skip_verify to make it work. Thanks for the heads up!

I was unable to get the posted config working, but after some poking got the following config working. The general approach is the one I found in use in most nginx reverse proxy configs for the Omada controller: replace Host with the host with port 8043 appended, and strip out the :8043 port in the Location headers coming back from the controller.

@wifi host wifi.drglove.ca
handle @wifi {
    reverse_proxy tplink-omada-controller.drglove.ca:8043 {
        transport http {
            tls_insecure_skip_verify
        }
        header_up Host {host}:8043
        header_down Location :8043 :443
    }
}
5 Likes

It seems that it does not work anymore. I had to do it the hackish way and handle normal browser 443/80 requests through caddy and the rest directly by the omada software:

(logging) {
  log {
    format console
    level debug
  }
}

omada.domain {
  @default {

  }
  encode gzip zstd
  log {

  }
  reverse_proxy omada-controller:8043 {
       header_up X-Real-IP {remote_host}
       header_up Host "omada.domain:8043"
       header_down Location :8043 :443
       transport http {
                        tls_insecure_skip_verify
                }
  }
  tls martin@
   header {
                Strict-Transport-Security "max-age=31536000; includeSubdomains"
                X-XSS-Protection "1; mode=block"
                X-Frame-Options "DENY"
                -server
  }
}

I could not see the device requests. Neither in the caddy logs nor in the omada software. Just the requests from the device and very short answers in tcpdump (which are encrypted) :confused:

version: "3.1"

networks:
  omada-net:
    external: false

services:
  caddy:
    image: caddy
    container_name: caddy
    restart: unless-stopped
    ports:
      - 80:80
      - 443:443
    volumes:
      - /data/caddy/data:/data
      - /data/caddy/config:/config
      - /data/caddy/Caddyfile:/etc/caddy/Caddyfile:ro
    networks:
      - omada-net
  omada-controller:
    container_name: omada-controller
    image: mbentley/omada-controller:5.13-chromium
    restart: unless-stopped
    ulimits:
      nofile:
        soft: 4096
        hard: 8192
    stop_grace_period: 60s
    networks:
      - omada-net
    ports:
      - 8043:8043
      - 8843:8843
      - 8088:8088
      - 27001:27001/udp
      - 29810:29810/udp
      - 29811:29811
      - 29812:29812
      - 29813:29813
      - 29814:29814
      - 29815:29815
      - 29816:29816
    environment:
      - PUID=508
      - PGID=508
      - MANAGE_HTTP_PORT=80
      - MANAGE_HTTPS_PORT=8043
      - PORTAL_HTTP_PORT=8088
      - PORTAL_HTTPS_PORT=8843
      - PORT_APP_DISCOVERY=27001
      - PORT_ADOPT_V1=29812
      - PORT_UPGRADE_V1=29813
      - PORT_MANAGER_V1=29811
      - PORT_MANAGER_V2=29814
      - PORT_DISCOVERY=29810
      - PORT_TRANSFER_V2=29815
      - PORT_RTTY=29816
      - SHOW_SERVER_LOGS=true
      - SHOW_MONGODB_LOGS=false
      - SSL_CERT_NAME=tls.crt
      - SSL_KEY_NAME=tls.key
      - TZ=Europe/Berlin
    volumes:
      - /data/backups:/backups
      - omada-data:/opt/tplink/EAPController/data
      - omada-logs:/opt/tplink/EAPController/logs
volumes:
  omada-data:
  omada-logs: