From a493949c2a9ab2221ef5fda79f3a3bb29e4933df Mon Sep 17 00:00:00 2001
From: Federico Jaramillo Martinez
+ The deployment path is not a PI WEB config-file key or environment setting. The published client is
+ portable: one build works at / and at canonical trailing-slash prefixes such as
+ /ai/ or /test/ai/.
+
+ For a nested deployment, redirect the slashless prefix to the trailing-slash URL, strip the prefix + before forwarding to PI WEB, and proxy authenticated HTTP and WebSocket traffic through the same + location. Relative browser and PWA URLs then stay within that prefix. See the + reverse proxy deployment example for complete Nginx + configuration. +
+Machine-global runtime values are resolved in this order:
diff --git a/docs/config.md b/docs/config.md index 1d8dfee..6682757 100644 --- a/docs/config.md +++ b/docs/config.md @@ -17,6 +17,12 @@ Pi package settings are separate from PI WEB config. They live in Pi's package-m If you installed services with a custom config path, rerun `pi-web install --config /path/to/config.json` after changing that path or after upgrading from a version that only applied the custom path to the web service. This regenerates service files so the web/API and session daemon use the same `PI_WEB_CONFIG`. +## Reverse-proxy deployment paths + +The deployment path is not a PI WEB config-file key or environment setting. The published client is portable: one build works at `/` and at canonical trailing-slash prefixes such as `/ai/` or `/test/ai/`. + +For a nested deployment, redirect the slashless prefix to the trailing-slash URL, strip the prefix before forwarding to PI WEB, and proxy authenticated HTTP and WebSocket traffic through the same location. Relative browser and PWA URLs then stay within that prefix. See [Reverse proxy deployments](https://github.com/jmfederico/pi-web#reverse-proxy-deployments) for a complete Nginx example. + ## Precedence and reloads Machine-global runtime values are resolved as: diff --git a/docs/install.html b/docs/install.html index 9f20d7f..0d224d8 100644 --- a/docs/install.html +++ b/docs/install.html @@ -95,6 +95,7 @@ Install through Pi WSL / manual run Remote access + Reverse proxy prefixes Federated machines Manage services Configure @@ -220,6 +221,79 @@
+ The published PI WEB client is deployment-independent. The same package works at the origin root
+ (/) or at canonical nested prefixes such as /ai/ and /test/ai/;
+ no prefix-specific rebuild or PI WEB configuration is needed.
+
+ For a root deployment, proxy / directly to http://127.0.0.1:8504 without
+ rewriting the path. For a nested deployment:
+
/ai, to /ai/. The browser uses the trailing-slash document URL as the application base./ai/ application and preserve required authentication headers and cookies.# http context
+map $http_upgrade $connection_upgrade {
+ default upgrade;
+ '' close;
+}
+
+server {
+ listen 443 ssl;
+ server_name pi.example.com;
+
+ ssl_certificate /etc/letsencrypt/live/pi.example.com/fullchain.pem;
+ ssl_certificate_key /etc/letsencrypt/live/pi.example.com/privkey.pem;
+
+ auth_basic "PI WEB";
+ auth_basic_user_file /etc/nginx/pi-web.htpasswd;
+
+ location = /ai {
+ return 308 /ai/$is_args$args;
+ }
+
+ location ^~ /ai/ {
+ # The trailing slash strips /ai/ before forwarding.
+ proxy_pass http://127.0.0.1:8504/;
+ proxy_http_version 1.1;
+
+ proxy_set_header Host $host;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header Authorization $http_authorization;
+ proxy_set_header Cookie $http_cookie;
+
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection $connection_upgrade;
+ proxy_read_timeout 1h;
+ }
+}
+
+ Use the same pattern for /test/ai/ by changing both Nginx locations. If your proxy uses
+ bearer tokens, SSO, or another authentication mechanism, keep that policy on the prefixed application
+ location and continue forwarding the headers or cookies it requires; the slashless redirect serves no
+ PI WEB content. Do not create unprotected exceptions for /api/ or
+ /pi-web-plugins/.
+
+ Once the proxy follows this contract, relative client assets, images, PWA assets, API calls, local and
+ federated plugins, and WebSocket URLs stay inside the prefix. Installed PWA start_url and
+ scope stay inside it as well.
+
diff --git a/docs/machines.html b/docs/machines.html index 38099c1..cf10fa5 100644 --- a/docs/machines.html +++ b/docs/machines.html @@ -174,7 +174,9 @@ PI WEB gateway you opened
Prefer a private path such as NetBird, Tailscale, WireGuard, private LAN, SSH tunnel, or an authenticated reverse
proxy. If the remote is behind a path prefix, include that prefix in the machine URL, for example
- https://devbox.example.test/pi-web.
+ https://devbox.example.test/pi-web. The machine registry normalizes the trailing slash; when
+ opening that deployment directly in a browser, use its canonical https://devbox.example.test/pi-web/
+ URL and configure the proxy to redirect the slashless form.
+ Current PI WEB manifests publish module references relative to the fetched manifest, so local and + federated plugin modules follow root or nested reverse-proxy deployments without a prefix-specific + build. The browser and federated gateway also accept leading-root module references emitted by existing + PI WEB releases and keep them inside the current application base. +
For portable plugin assets, prefer URLs relative to the plugin module, such as
new URL("./asset.json", import.meta.url). If a remote plugin constructs absolute asset URLs,
diff --git a/docs/plugins.md b/docs/plugins.md
index 9a353df..bfea440 100644
--- a/docs/plugins.md
+++ b/docs/plugins.md
@@ -325,14 +325,14 @@ Rules:
### Manifest and assets
-The manifest contains each discovered plugin module:
+The manifest contains each discovered plugin module. Current PI WEB releases emit `module` relative to the fetched manifest so the same manifest works at the origin root or under a reverse-proxy path prefix:
```json
{
"plugins": [
{
"id": "my-plugin",
- "module": "/pi-web-plugins/my-plugin/pi-web-plugin.js?v=1234567890",
+ "module": "./my-plugin/pi-web-plugin.js?v=1234567890",
"source": "local",
"scope": "local",
"machineSpecific": false
@@ -341,9 +341,11 @@ The manifest contains each discovered plugin module:
}
```
+The browser resolves manifest-relative module references against the manifest URL. For backward compatibility, it also treats leading-root references such as `/pi-web-plugins/my-plugin/pi-web-plugin.js` from existing PI WEB releases as application-root input, not origin-root input. Federated gateways accept both forms from remote machines and rewrite them to deployment-portable, gateway-relative references.
+
`source` describes where the plugin came from (`bundled`, `local`, or the Pi package source). `scope` is `bundled`, `local`, `user`, or `project`. `machineSpecific` controls whether the gateway copy is valid for remote machines or only each selected machine's own copy can appear.
-A plugin can fetch its own static assets with URLs under:
+At an origin-root deployment, a plugin's static assets are available under:
```text
/pi-web-plugins/