From 3b54c3ea33985a6f0c35cd9bdd734d3ec1897b02 Mon Sep 17 00:00:00 2001 From: Simon Fischer Date: Sun, 7 Jun 2026 12:35:08 +0200 Subject: [PATCH] extend reverse proxy documentation --- README.md | 92 +------------------------ REVERSE_PROXY.md | 147 ++++++++++++++++++++++++++++++++++++++++ assets/revproxy_web.png | Bin 0 -> 30099 bytes 3 files changed, 148 insertions(+), 91 deletions(-) create mode 100644 REVERSE_PROXY.md create mode 100644 assets/revproxy_web.png diff --git a/README.md b/README.md index ca79b2e64..514311171 100644 --- a/README.md +++ b/README.md @@ -54,97 +54,7 @@ If this option is disabled, the simple configuration page could be accessed unde ## Reverse proxy -Please be sure that you forward not only the http/https requests, but the web-socket traffic too. It is essential for communication. - -From version 6.1.0 you have the possibility to tune intro page for usage with reverse proxy. - -### Example - -Your `ioBroker.admin` runs on port 8081 behind reverse proxy with domain `iobroker.mydomain.com` under path `/ioBrokerAdmin/`. -And you set up e.g., nginx to forward the requests to the `http://local-iobroker.IP:8081`. - -The same is with your web instance: `https://iobroker.mydomain.com/ioBrokerWeb/ => http://local-iobroker.IP:8082`. -And with rest-api instance: `https://iobroker.mydomain.com/ioBrokerAPI/ => http://local-iobroker.IP:8093`. - -You can add the following lines into Reverse Proxy tab to let Intro tab run behind reverse proxy properly: - -| Global path | Instance | Instance path behind proxy | -|-------------------|---------------|----------------------------| -| `/ioBrokerAdmin/` | `web.0` | `/ioBrokerWeb/` | -| | `rest-api.0` | `/ioBrokerAPI/` | -| | `admin.0` | `/ioBrokerAdmin/` | -| | `eventlist.0` | `/ioBrokerWeb/eventlist/` | - -So all links of instances that use web server, like `eventlist`, `vis`, `material` and so on will use `https://iobroker.mydomain.com/ioBrokerWeb/` path - -### Extended reverse proxy example (with screenshots) - -Below is a more complete example showing how a reverse proxy (e.g. Nginx Proxy Manager) can be configured and how the Admin UI resolves links after mapping. - -> NOTE: At the moment the admin UI itself still needs to be effectively served from the web root `/` of the host. login and other hardcoded urls do not yet respect another base path (see limitation discussion here: https://github.com/ioBroker/ioBroker.admin/issues/1660#issuecomment-2360056439). - -#### 1. Base host / root mapping - -Map the public root (or a dedicated host like `https://iobroker.example.com/`) directly to your Admin instance (default port 8081): - -Nginx Proxy Manager: root mapping to admin - -#### 2. Custom locations for other services - -Add additional custom locations for web / REST / other adapter frontends. Each location forwards to the respective local port (e.g. web.0 on 8082, rest-api.0 on 8093): - -Nginx Proxy Manager: custom locations - -Example custom locations (Nginx style): -``` -/location /web/ => http://LOCAL_IOBROKER_IP:8082/ -/location /welcome/ => http://LOCAL_IOBROKER_IP:1234/ -/location /esphome/ => http://LOCAL_IOBROKER_IP:6052/ -``` -(Adjust paths/ports for your environment.) - -#### 3. Configure mappings in Admin Reverse Proxy tab - -Enter the same paths so that Intro / Instances pages rewrite adapter links correctly: - -| Global path | Instance | Instance path behind proxy | -|-------------|--------------|----------------------------| -| `/` | `web.0` | `/web/` | -| | `rest-api.0` | `/api/` | -| | `esphome.0` | `/esphome/` | - -> If you keep Admin on `/` you usually do not need to list `admin.0`, but adding it does not hurt and can make intent explicit. - -After saving, the Intro screen rewrites links so that all web‑served adapters open under the correct prefixed paths: - -Admin Intro page after reverse proxy mapping - -#### 4. Limitations & compatibility - -* Admin root requirement: As stated above, full relocation of Admin itself under a sub‑path (e.g. `/admin/`) is not yet supported. -* Adapter path awareness: Not every adapter UI is currently path‑aware. While generic `localLink` rewriting covers many cases, some UIs still assume they are hosted at the domain root. Known examples: - * `vis` (classic) – NOT fully working behind a sub‑path today. - * `vis-2` – generally more path tolerant, but custom widgets or legacy resources may still use absolute paths. - * Any adapter serving hard‑coded absolute URLs (starting with `/`) may need manual fixes until updated upstream. -* Mixed content: If you terminate TLS at the proxy (HTTPS) but contact adapters over HTTP internally, make sure all external links are rewritten to HTTPS to avoid browser mixed-content blocks. -* WebSocket forwarding: Ensure `Upgrade` and `Connection` headers are passed through. In Nginx, this typically means adding: -``` -proxy_set_header Upgrade $http_upgrade; -proxy_set_header Connection "upgrade"; -``` -(old checking the websocket support box, if using proxy manager) -* Trailing slashes: Always keep a trailing slash in the mapped path (e.g. `/web/`) and location, so nginx does path rewriting. -This makes simple cases like the welcome adapter above work, because it only sees a / path -> correctly serves its index.html. - -#### 5. Quick troubleshooting checklist - -| Symptom | Likely cause | Action | -|------------------------------------|--------------------------------------|-------------------------------------------------------| -| Blank or partial Admin UI | Admin mounted under sub‑path only | Keep Admin at `/` (see limitation) | -| Adapter link opens wrong host/port | Missing entry in Reverse Proxy tab | Add mapping row and save | -| 404 for adapter JS/CSS | Missing trailing slash in location | Add trailing slash to location and mapping | -| WebSocket errors in console | Proxy not forwarding upgrade headers | Add `proxy_set_header Upgrade` / `Connection` headers | -| vis UI broken | Adapter not path‑aware | Keep on root or wait for adapter update | +The reverse proxy documentation can be found at [Reverse proxy](REVERSE_PROXY.md). ## Used icons diff --git a/REVERSE_PROXY.md b/REVERSE_PROXY.md new file mode 100644 index 000000000..6a15fb430 --- /dev/null +++ b/REVERSE_PROXY.md @@ -0,0 +1,147 @@ +# Reverse proxy + +Please be sure that you forward not only the http/https requests, but the web-socket traffic too. It is essential for communication. + +From version 6.1.0 you have the possibility to tune intro page for usage with reverse proxy. + +## Example + +Your `ioBroker.admin` runs on port 8081 behind reverse proxy with domain `iobroker.mydomain.com` under path `/ioBrokerAdmin/`. +And you set up e.g., nginx to forward the requests to the `http://local-iobroker.IP:8081`. + +The same is with your web instance: `https://iobroker.mydomain.com/ioBrokerWeb/ => http://local-iobroker.IP:8082`. +And with rest-api instance: `https://iobroker.mydomain.com/ioBrokerAPI/ => http://local-iobroker.IP:8093`. + +You can add the following lines into Reverse Proxy tab to let Intro tab run behind reverse proxy properly: + +| Global path | Instance | Instance path behind proxy | +|-------------------|---------------|----------------------------| +| `/ioBrokerAdmin/` | `web.0` | `/ioBrokerWeb/` | +| | `rest-api.0` | `/ioBrokerAPI/` | +| | `admin.0` | `/ioBrokerAdmin/` | +| | `eventlist.0` | `/ioBrokerWeb/eventlist/` | + +So all links of instances that use web server, like `eventlist`, `vis`, `material` and so on will use `https://iobroker.mydomain.com/ioBrokerWeb/` path + +## Extended reverse proxy example (with screenshots) + +Below is a more complete example showing how a reverse proxy (e.g. Nginx Proxy Manager) can be configured and how the Admin UI resolves links after mapping. + +> NOTE: At the moment the admin UI itself still needs to be effectively served from the web root `/` of the host. login and other hardcoded urls do not yet respect another base path (see limitation discussion here: https://github.com/ioBroker/ioBroker.admin/issues/1660#issuecomment-2360056439). + +### 1. Base host / root mapping + +Map the public root (or a dedicated host like `https://iobroker.example.com/`) directly to your Admin instance (default port 8081): + +Nginx Proxy Manager: root mapping to admin + +### 2. Custom locations for other services + +Add additional custom locations for web / REST / other adapter frontends. Each location forwards to the respective local port (e.g. web.0 on 8082, rest-api.0 on 8093): + +Nginx Proxy Manager: custom locations + +Example custom locations (Nginx style): +``` +location /welcome/ => http://LOCAL_IOBROKER_IP:1234/ +location /esphome/ => http://LOCAL_IOBROKER_IP:6052/ +``` +(Adjust paths/ports for your environment.) + +Configuring the location for web is a bit more complicated, as it also needs websocket support. To do this in nginx proxy manager, you need to add the following custom nginx configuration. +``` +location /web/ { + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $http_connection; + proxy_http_version 1.1; + + proxy_pass http://LOCAL_IOBROKER_IP:8082/; +} +``` +![revproxy_web.png](assets/revproxy_web.png) + +### 3. Configure mappings in Admin Reverse Proxy tab + +Enter the same paths so that Intro / Instances pages rewrite adapter links correctly: + +| Global path | Instance | Instance path behind proxy | +|-------------|--------------|----------------------------| +| `/` | `web.0` | `/web/` | +| | `welcome.0` | `/welcome/` | +| | `esphome.0` | `/esphome/` | +| | `rest-api.0` | `/web/rest-api/api-doc/` | + +> If you keep Admin on `/` you usually do not need to list `admin.0`, but adding it does not hurt and can make intent explicit. + +After saving, the Intro screen rewrites links so that all web‑served adapters open under the correct prefixed paths: + +Admin Intro page after reverse proxy mapping + +### 4. Limitations & compatibility + +* Admin root requirement: As stated above, full relocation of Admin itself under a sub‑path (e.g. `/admin/`) is not yet supported. +* Adapter path awareness: Not every adapter UI is currently path‑aware. While generic `localLink` rewriting covers many cases, some UIs still assume they are hosted at the domain root. See the [Tested adapters](#tested-adapters) table below. Any adapter serving hard‑coded absolute URLs (starting with `/`) may need manual fixes until updated upstream. + +#### Tested adapters + +The following adapters have been tested behind a path‑prefixed reverse proxy (Admin at host root `/`, other services under sub‑paths such as `/web/`). Not being listed here does not necessarily mean an adapter is incompatible, just that it has not been explicitly tested yet. At least everything running as a web extension and using standard iobroker tooling - but also others - should mostly just work. + +Contributions welcome via PR. + +✅ works · ⚠️ partial / with limitations · ❌ does not work + +| Adapter | Works | Minimum versions | Notes | +|---------------------------------------------------------|:-----:|------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [admin](https://github.com/ioBroker/ioBroker.admin) | ⚠️ | admin ≥ 7.7.18 | Only when served at host root `/`; sub‑path relocation (e.g. `/admin/`) not supported | +| [echarts](https://github.com/ioBroker/ioBroker.echarts) | ✅ | web ≥ 8.3.0, echarts ≥ 3.2.0 | | +| [esphome](https://github.com/DrozmotiX/ioBroker.esphome) | ✅ | — | Shown in extended example; dedicated proxy path (e.g. `/esphome/`) | +| [rest-api](https://github.com/ioBroker/ioBroker.rest-api) | ⚠️ | — | Swagger UI 'Try it out' does not respect sub-path / tries to call root \/rest-api/... Manual call to correct \/web/rest-api/... url works fine. | +| [vis](https://github.com/ioBroker/ioBroker.vis) | ❌ | — | Not path‑aware; UI broken behind a sub‑path | +| [vis-2](https://github.com/ioBroker/ioBroker.vis-2) | ⚠️ | — | Generally path tolerant; custom widgets or legacy resources may use absolute paths. Also see *1 | +| [web](https://github.com/ioBroker/ioBroker.web) | ✅ | — | Base for web‑hosted adapter UIs; proxy under e.g. `/web/`. Important: Also requires correct configuration of web adapter: see bellow "6. Configuring Web Adapter" | +| [welcome](https://github.com/ioBroker/ioBroker.welcome) | ✅ | — | | +* Mixed content: If you terminate TLS at the proxy (HTTPS) but contact adapters over HTTP internally, make sure all external links are rewritten to HTTPS to avoid browser mixed-content blocks. +* WebSocket forwarding: Ensure `Upgrade` and `Connection` headers are passed through. In Nginx, this typically means adding (also for custom locations like `/web/` !): +``` +proxy_set_header Upgrade $http_upgrade; +proxy_set_header Connection "upgrade"; +``` +(or checking the websocket support box, if using proxy manager) +* Trailing slashes: Most of the time keep a trailing slash in the mapped path (e.g. `/web/`) and location, so nginx does path rewriting. +This makes simple cases like the welcome adapter above work, because it only sees a / path -> correctly serves its index.html. + +#### *1 Vis quirks +Some known quirks / workarounds with vis-2 (widgets). Especially if views got imported from old vis-1.x. +Probably a good idea to also configure those paths in the reverse proxy (NOTE: no trailing slashes here): +``` +location /vis.0 => http://LOCAL_IOBROKER_IP:8082 +location /vis/widgets => http://LOCAL_IOBROKER_IP:8082 +location /vis-2/widgets => http://LOCAL_IOBROKER_IP:8082 +location /icons-mfd-svg => http://LOCAL_IOBROKER_IP:8082 +location /icons-material-png => http://LOCAL_IOBROKER_IP:8082 +``` + +### 5. Quick troubleshooting checklist + +| Symptom | Likely cause | Action | +|------------------------------------|--------------------------------------|-------------------------------------------------------| +| Blank or partial Admin UI | Admin mounted under sub‑path only | Keep Admin at `/` (see limitation) | +| Adapter link opens wrong host/port | Missing entry in Reverse Proxy tab | Add mapping row and save | +| 404 for adapter JS/CSS | Missing trailing slash in location | Add trailing slash to location and mapping | +| WebSocket errors in console | Proxy not forwarding upgrade headers | Add `proxy_set_header Upgrade` / `Connection` headers | +| vis UI broken | Adapter not path‑aware | Keep on root or wait for adapter update | + +### 6. Configuring Web Adapter +You also need to put the web adapters root path (what you configured in reverse proxy) into web adapter Instance settings: Tab "Advanced" - field "Root path +". So in the example above it would be `/web/`. + +Also enable the `Use pure web-sockets (iobroker.ws)` option in the `Main Settings` tab of web adapter instance settings. All the tests above were done with this option enabled. If not using this options you likely get different results (f.e. required to use url workarounds like `http://iobroker-test.revproxy.home.arpa/web//echarts/index.html?preset=echarts.0.preset_1` - note the double slash after web). As the web adapter recommends to enable this option anyway, just enable it if you don't see any other issues. It will likely safe you some headaches and weird issues. + +#### Technical details (only relevant for devs) +Technical details about what this option does in web / why it's required. + +When visiting a page served by the web adapter, your browser first requests `_socket/info.js` (dynamically generated and served by web adapter). The `var socketUrl` in there actually only supports host:port (no path), so (to not break existing setups), https://github.com/ioBroker/socket-client/pull/60 and https://github.com/ioBroker/ioBroker.web/pull/681 introduced a dedicated `var socketPath = "/web/";` (filled from the root path set in adapter configuration). +The socket client will then correctly try to connect to e.g. `http://iobroker-test.revproxy.home.arpa/web/socket.io/?ws=true&EIO=3&transport=polling&t=PwXUr0T&sid=0AHBuqNcP4EqMPaNAACR` or `ws://iobroker-test.revproxy.home.arpa/web/?sid=1780827297411&name=echarts-show`. + +Why not just use the root (admins) socket (e.g. `ws://iobroker-test.revproxy.home.arpa/?sid=1780827297411&name=echarts-show`)?: +Admin needs authentication and web usually not, so you would have to be logged in to admin for your views (served by web!) to load. Also, when not using a proxy setup, it would also use the web adapters socket (request to :8082/?sid=...) - so also using the web adapters socket for reverse proxy setup is the correct approach. diff --git a/assets/revproxy_web.png b/assets/revproxy_web.png new file mode 100644 index 0000000000000000000000000000000000000000..c50df73e049a3f207a337712e09cae387354235f GIT binary patch literal 30099 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 literal 0 HcmV?d00001