Feature: Support subpath deployment for Go web UI

Add optional YAMA_WEB_BASE_PATH to mount the whole web UI (index, manifest,
static assets, /health, /api/devices, /ws) under a URL prefix such as
/remoter behind a reverse proxy. index.html now uses a __BASE_PATH__
placeholder substituted at serve time, the PWA manifest start_url is rooted
at the base path, and a mount wrapper redirects the bare prefix to prefix/
and strips it before routing. Include nginx, systemd, and env-file deployment
examples for the subpath setup.

The shared placeholder is also handled by the MFC server, which serves from
the domain root and strips __BASE_PATH__ (to "") so its web remote desktop
URLs stay rooted.

Co-Authored-By: deepseek-v4-pro
This commit is contained in:
yuanyuanxianganddeepseek-v4-pro committed 2026-09-11 12:48:21 +02:00
1 parent 32cc7af371
commit 42df128f62
7 files changed
+254 -12

No files matched your search

+18
View File
@@ -661,6 +661,19 @@ func splitCSV(s string) []string {
return out
}
// normalizeBasePath turns a YAMA_WEB_BASE_PATH value into a leading-slash,
// no-trailing-slash prefix ("" for root). "" (or "/") means the web UI is
// served at the domain root (方案A); "/remoter" means it is served under that
// prefix (方案B), with a reverse proxy routing the subpath to this process.
func normalizeBasePath(s string) string {
s = strings.TrimSpace(s)
s = strings.Trim(s, "/")
if s == "" {
return ""
}
return "/" + s
}
// runIssueToken handles the "issue-token" subcommand. It mints a customer JWT
// signed with the operator's RSA private key and prints it to stdout.
//
@@ -918,11 +931,16 @@ func main() {
if trustProxy {
log.Info("Trusting X-Forwarded-For for client IP — make sure a reverse proxy is in front")
}
basePath := normalizeBasePath(os.Getenv("YAMA_WEB_BASE_PATH"))
if basePath != "" {
log.Info("Serving web UI under base path %q (subpath deployment)", basePath)
}
webCfg := web.Config{
AllowedOrigins: allowedOrigins,
LoginIPLimit: wsauth.NewRateLimiter(10, time.Minute),
LoginUserLimit: wsauth.NewRateLimiter(5, 15*time.Minute),
TrustForwardedFor: trustProxy,
BasePath: basePath,
}
// Start HTTP server for web UI. Hub gives it read-only access to the