Skip to content
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

Reverse Proxy Documentation #1056

Open
RowMax03 opened this issue Nov 26, 2024 · 10 comments
Open

Reverse Proxy Documentation #1056

RowMax03 opened this issue Nov 26, 2024 · 10 comments

Comments

@RowMax03
Copy link

Feature does not already exist?

I searched and did not find an existing feature request

Summarize feature

I think many people run diyhue hue and their whole setup inside docker. The limitation that you need the http ports open in order to run diyhue is bad when using a reverse proxy for other services. I saw the issue and some solutions but they where 5 years old and the source code looks way different now.

Especially a documentation to have some specific traefik rule to forward only hue request to port 80 or 443 internally would be great because setting a host name doesn't work if I understood correctly.

@hendriksen-mark
Copy link
Member

Hi, first the hue app requires port 80 and 443. You want te be able to rout the ports inside to a different port, so diyhue listen to port 8080 and 8443 and out side it is reachable on port 80 and 443?

@RowMax03
Copy link
Author

Depending on how the url parameters are you could also very specifically route some traffic to to diyhue. For example everything to /api on the ip adress itself could get routed to diyhue using traefik. Or things that alway appear in the header. Being able to change the port in the docker compose would also work I guess.

@hendriksen-mark
Copy link
Member

I i understand you correctly, you want to redirect url endpoints to something else?
Why would you want to do that?
We replicate what the original bridge does, we are not going to change the api or add a api because there is no benefit.
If you want to change that in docker you may but that is out of our scope.

@eckynde
Copy link

eckynde commented Nov 26, 2024

I also have a docker compose and traefik reverse proxy setup and I'm looking to add diyhue. Not sure when I'll get to it but once I've figured it out I'll post my config here.

Traefik listens on 80 and 443 and proxies to different services/web servers using rules, mostly by checking the host in the http request (subdomain). Doing this has many benefits like SSL offloading and running multiple services on a server with just one IP.

In a perfect world we would be able to use a subdomain to reach the diyhue bridge emulator, but from what I gather, the apps are limited to IP only.

This shouldn't be a problem though: It should be possible to configure traefik to send any http/https traffic for the IP (no subdomain) to the diyhue container. Any traffic to a subdomain still goes to the other services.

As for the diyhue container, it can continue running using default http/https ports, but we do not publish them in the docker compose file anymore. The ports are still accessible from the docker network but docker won't try binding those ports on the host. Which is good because those ports are already bound by traefik. Instead we can put the diyhue container on the proxy/traefik network and configure traefik to send requests for the ip (with no host/subdomain) to diyhue.

Here are some links to some potential puzzle pieces:

As I wrote above, I'll be sure to update you when I've had the time to actually put my plan to the test, but maybe this already gives you a couple ideas.

Home Assistant Community
I wanted to use the Hue App to control Home Assistant lights as some members of the family prefer the Hue App to the Home Assistant interface. So I set out to add Home Assistant integration into diyHue (https://diyhue.org/) and as luck would have it at the same time @MaxBec92 created the DiyHue Addon that has now been included in the diyhue project (https://github.com/diyhue/hassio-addon) here is how to configure everything you need to get the Hue App working to control Home Assistant lights… B...
Traefik Labs Community Forum
You can use Host(`1.2.3.4`) for http routers. At least browsers send the IP in the HTTP Host header, so it can be matched by Traefik.

@hendriksen-mark
Copy link
Member

you can change the port of diyhue with docker environment variable HTTP_PORT and HTTPS_PORT or commandline argument --http-port and --https-port

@RowMax03
Copy link
Author

Can I choose any port or just 80/443 and 8080/8443?

@hendriksen-mark
Copy link
Member

you can use any port except 1900 and 2100, the hue app needs 80 and 443 its not possible to change that.

@eckynde
Copy link

eckynde commented Dec 20, 2024

I've gotten around to it now and as promised - this is my working setup:

Brief Overview

Traefik listens on 80 and 443 for http/https requests. If the requests go to a subdomain etc., forward it to those services as usual. If they go to the IP directly, we let diyHue answer the request instead - it might be the Hue app.

The TLS encryption is handled by traefik (SSL offloaded) using the certificate generated and provided by diyHue. Ports 1900, 1982 and 2100 are handled directly by diyHue.

For more on the concept, see my previous post.

diyHue docker-compose.yml

In my docker-compose.yml (based on the examples in the repo), I made the following changes:

  • put the diyhue container on the traefik docker network (if you also have it in a separate docker-compose.yml)
  • dropped privileged: true, it doesn't seem to be necessary for my setup and removing it is good for security
  • dropped network_mode: host and published udp ports 1900, 1982 and 2100
    (ports 80 and 443 do not get published, they are still reachable from within the traefik network, they just don't get mapped onto the host machine. Because of this we also do not need to change diyHues http/https ports, there won't be any conflict with traefik)
  • set the IP and MAC environment variables
  • add the usual traefik labels
    - "traefik.enable=true"
    - "traefik.http.services.diyhue-service.loadbalancer.server.port=80"
    - "traefik.http.routers.diyhue-route.service=diyhue-service"
  • special rule, make sure to fill in your IP
    - "traefik.http.routers.diyhue-route.rule=Host(`192.168.XXX.XXX`)"
    (if you wanted, you could get more specific with the rule as discussed in this comment above and here or if you want to make diyhue accessible on a subdomain additionally, use Host(`192.168.XXX.XXX\`) || Host(`diyhue.example.com`) )

Afterwards, the docker compose file might look something like this:

# docker-compose.yml
services:
  diyhue:
    container_name: diyhue
    image: diyhue/core:latest
    volumes:
      - ./diyHue:/opt/hue-emulator/config
    restart: unless-stopped
    ports:
      - "1900:1900/udp"
      - "1982:1982/udp"
      - "2100:2100/udp"
    environment:
      - DEBUG=false
      - MAC=dc:a6:32:fe:XX:XX
      - IP=192.168.XXX.XXX
      - TZ=Europe/Berlin
    # special config for traefik
    labels:
      - "traefik.enable=true"
      - "traefik.http.services.diyhue-service.loadbalancer.server.port=80"
      - "traefik.http.routers.diyhue-route.service=diyhue-service"
      - "traefik.http.routers.diyhue-route.rule=Host(`192.168.XXX.XXX`)"
      - "traefik.http.routers.diyhue-route.entrypoints=web, websecure"
    networks:
      - "proxy"

# declare external traefik network
networks:
  proxy:
    external: true

Certificate

In order to get the official Hue app to work, the correct TLS certificate is needed. diyHue generates one and puts it in the same directory as the config files (./diyHue/cert.pem). We just need to use it.

To achieve this I simply replaced the default certificate (see documentation). ACME certificates are still prioritized if available so it only really applies for requests to the IP directly.
Add the following dynamic configuration to traefik (and reference or copy over the diyHue cert).

# config.yml
# put this in the dynamic config, not in the static config in traefik.yml
tls:
  stores:
    default:
      defaultCertificate:
        certFile: /path/to/cert.pem
        keyFile: /path/to/cert.pem

You can check if it's working using this method from the diyHue docs.

Disabling diyHue serving https

We don't actually need diyHue to listen for https requests anymore because traefik has that job now. There is a parameter --no-serve-https true which is not yet available as an environment variable it seems. It's not a problem though, it just won't get any traffic.

@hendriksen-mark If you want me to create a pull request somewhere (like the examples folder or readthedocs), just let me know what and where to put it. Also, can you verify that the --no-serve-https option is not available as an environment variable or through the diyHue config file? Maybe it's worth doing a pr for that as well.

@Nickk888SAMP
Copy link

Nickk888SAMP commented Jan 8, 2025

@eckynde Could you provide an instruction on how to add the dynamic configurations in Traefik? The documentations doesn't help me much, diyHue works, though it's showing

{"name": "DiyHue Bridge", "datastoreversion": "126", "swversion": "1968096020", "apiversion": "1.68.0", "mac": "c0:74:2b:xx:xx:xx", "bridgeid": "C0742BFFFEXXXXXX", "factorynew": false, "replacesbridgeid": null, "modelid": "BSB002", "starterkitid": ""}

So the certs doesn't seem to work or isn't picked up by Traefik.

@eckynde
Copy link

eckynde commented Jan 8, 2025

@eckynde Could you provide an instruction on how to add the dynamic configurations in Traefik?

@Nickk888SAMP Sure! (By the way, if you want to properly censor your MAC address, you also need to redact the bridgeid.)

Conceptually:

  • In order for traefik to pick up a dynamic configuration file, it has to know that it exists. This is done by adding a file provider like described here in the traefik docs.
  • Unlike for the static configuration (aka startup configuration aka traefik.yml), traefik will monitor this configuration for changes and automatically reload it without having to restart traefik. Not only files can be used for dynamic configuration: For example, Docker labels are dynamic configuration (from the docker provider). You can learn about the differences between static and dynamic config and the kinds of providers in this introduction.
  • In this new dynamic configuration file, we instruct traefik to use a different default certificate like described here in the docs. Because the default certificate configuration is limited to the file provider only, we cannot use docker labels for this unfortunately.
  • Of course, we also need to make sure that the traefik docker container can actually read both the new config file and the certificate we specified. This involves creating entries in the volumes: section of the docker-compose.yml file (see compose file reference).

More practically speaking, do this:

Step 1 - Let traefik know where to look

If you use command line arguments in your traefik docker-compose.yml file like the Docker Quick Start in the official traefik documentation, add the argument --providers.file.filename=/config.yml

# docker-compose.yml
services:
  traefik:
    command: --api.insecure=true --providers.docker --providers.file.filename=/config.yml
    # ...

If, in your traefik docker-compose.yml file, you mount /traefik.yml instead, like you might find on the web, you can just add this in the traefik.yml (aka static configuration) instead:

# traefik.yml / static config
providers:
  file:
    filename: /config.yml

(For extra neat config management: The file provider also supports specifying a directory instead of a single file. See docs)

Step 2 - Mount files

We've just told traefik that it should expect to find a configuration file in /config.yml.
Now we need to make the file available inside the docker container.

To do that, we mount it. We do the same for the certificate file that diyhue generated:

# docker-compose.yml
services:
  traefik:
    volumes:
      - ./config.yml:/config.yml:ro
      - ./cert.pem:/cert.pem:ro
      # ...

(The left part is the path on the host system, the right part is the path inside the docker container and the ro makes it read only.)

Step 3 - Create files

We also need to actually put those files there. So create config.yml in the same directory as the traefik docker-compose.yml:

# config.yml / dynamic config
tls:
  stores:
    default:
      defaultCertificate:
        certFile: /cert.pem
        keyFile: /cert.pem

Next, copy over the certificate that diyhue generated. Make sure you have put the correct MAC address in the diyhue config or the app won't pair. The certificate doesn't expire until 2037, so you should be fine for a while.

If you want to get fancy, instead of copying, you could also change your traefik docker-compose.yml to reference the file directly:

# docker-compose.yml
      # replacing the line
      # - ./cert.pem:/cert.pem:ro
      # with (adjust path)
      - /srv/compose/diyhue/diyHue/cert.pem:/cert.pem:ro

Finishing up

To apply your changes and watch the logs as it starts up, you can run this and wait:

sudo docker compose up -d && sudo docker compose logs -f

To check everything is working, use this method from the diyhue docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants