From b6a27616c1b52ed4b4a41ed888f89a1418a47d82 Mon Sep 17 00:00:00 2001 From: Christoph Haas Date: Thu, 11 Dec 2025 18:38:26 +0100 Subject: [PATCH] allow setting a base-path for the web UI and API (#583) --- cmd/wg-portal/main.go | 2 +- config.yml.sample | 9 +- docs/documentation/configuration/overview.md | 10 +- .../getting-started/reverse-proxy.md | 10 ++ frontend/index.html | 1 + frontend/src/App.vue | 3 +- frontend/src/views/SettingsView.vue | 4 +- .../api/core/assets/img/header-logo-small.png | Bin 7713 -> 709 bytes internal/app/api/core/assets/tpl/index.gohtml | 20 +-- .../app/api/core/assets/tpl/prt_nav.gohtml | 2 +- .../app/api/core/assets/tpl/rapidoc.gohtml | 2 +- internal/app/api/core/server.go | 132 +++++++++++++++--- .../app/api/v0/handlers/endpoint_config.go | 8 +- .../api/v0/handlers/frontend_config.js.gotpl | 1 + internal/app/api/v0/handlers/web_session.go | 6 +- internal/app/auth/auth.go | 4 +- internal/config/config.go | 1 + internal/config/web.go | 12 ++ 18 files changed, 177 insertions(+), 50 deletions(-) diff --git a/cmd/wg-portal/main.go b/cmd/wg-portal/main.go index cd5fd7e..da1b06c 100644 --- a/cmd/wg-portal/main.go +++ b/cmd/wg-portal/main.go @@ -84,7 +84,7 @@ func main() { internal.AssertNoError(err) userManager.StartBackgroundJobs(ctx) - authenticator, err := auth.NewAuthenticator(&cfg.Auth, cfg.Web.ExternalUrl, eventBus, userManager) + authenticator, err := auth.NewAuthenticator(&cfg.Auth, cfg.Web.ExternalUrl, cfg.Web.BasePath, eventBus, userManager) internal.AssertNoError(err) authenticator.StartBackgroundJobs(ctx) diff --git a/config.yml.sample b/config.yml.sample index 9e5ef5d..5d4c594 100644 --- a/config.yml.sample +++ b/config.yml.sample @@ -11,18 +11,11 @@ core: web: external_url: http://localhost:8888 + base_path: "" request_logging: true - # Optional path where custom frontend files are stored. - # If this folder contains at least one file, it will override the embedded frontend. - # If the folder is empty or does not exist on startup, the embedded frontend will be - # written into it. Leave empty to use the embedded frontend only. frontend_filepath: "" mail: - # Path where custom email templates (.gotpl and .gohtml) are stored. - # If the directory is empty on startup, the default embedded templates - # will be written there so you can modify them. - # Leave empty to use embedded templates only. templates_path: "" webhook: diff --git a/docs/documentation/configuration/overview.md b/docs/documentation/configuration/overview.md index b926ddd..ded802b 100644 --- a/docs/documentation/configuration/overview.md +++ b/docs/documentation/configuration/overview.md @@ -88,6 +88,7 @@ auth: web: listening_address: :8888 external_url: http://localhost:8888 + base_path: "" site_company_name: WireGuard Portal site_title: WireGuard Portal session_identifier: wgPortalSession @@ -800,9 +801,16 @@ Without a valid `external_url`, the login process may fail due to CSRF protectio ### `external_url` - **Default:** `http://localhost:8888` - **Environment Variable:** `WG_PORTAL_WEB_EXTERNAL_URL` -- **Description:** The URL where a client can access WireGuard Portal. This URL is used for generating links in emails and for performing OAUTH redirects. +- **Description:** The URL where a client can access WireGuard Portal. This URL is used for generating links in emails and for performing OAUTH redirects. + The external URL must not contain a path component or trailing slash. If you want to serve WireGuard Portal on a subpath, use the `base_path` setting. **Important:** If you are using a reverse proxy, set this to the external URL of the reverse proxy, otherwise login will fail. If you access the portal via IP address, set this to the IP address of the server. +### `base_path` +- **Default:** *(empty)* +- **Environment Variable:** `WG_PORTAL_WEB_BASE_PATH` +- **Description:** The base path for the web server (e.g., `/wgportal`). + By default (meaning an empty value), the portal will be served from the root path `/`. + ### `site_company_name` - **Default:** `WireGuard Portal` - **Environment Variable:** `WG_PORTAL_WEB_SITE_COMPANY_NAME` diff --git a/docs/documentation/getting-started/reverse-proxy.md b/docs/documentation/getting-started/reverse-proxy.md index e1fad58..4bf07ae 100644 --- a/docs/documentation/getting-started/reverse-proxy.md +++ b/docs/documentation/getting-started/reverse-proxy.md @@ -84,6 +84,16 @@ web: external_url: https://wg.domain.com ``` +If you want to serve the web interface on a different base-path, you can also set the `web.base_path` option: + +```yaml +web: + external_url: https://wg.domain.com + base_path: /subpath +``` + +The WireGuard Portal will then be available at `https://wg.domain.com/subpath`. + ### Built-in TLS If you prefer to let WireGuard Portal handle TLS itself, you can use the built-in TLS support. diff --git a/frontend/index.html b/frontend/index.html index 287ef99..8aed737 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -9,6 +9,7 @@ - - - + + + + \ No newline at end of file diff --git a/internal/app/api/core/assets/tpl/prt_nav.gohtml b/internal/app/api/core/assets/tpl/prt_nav.gohtml index 9337daf..2ebd535 100644 --- a/internal/app/api/core/assets/tpl/prt_nav.gohtml +++ b/internal/app/api/core/assets/tpl/prt_nav.gohtml @@ -3,7 +3,7 @@ - Prolicht + Prolicht