[PR #1451] feat: add support for custom URL paths via BASE_URL configuration #1302

Open
opened 2026-02-04 22:02:31 +03:00 by OVERLORD · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/plankanban/planka/pull/1451
Author: @roberfi
Created: 12/7/2025
Status: 🔄 Open

Base: masterHead: support-url-paths


📝 Commits (1)

  • 2d61502 feat: add support for custom URL paths via BASE_URL configuration

📊 Changes

14 files changed (+76 additions, -18 deletions)

View changed files

📝 Dockerfile (+5 -1)
📝 client/src/api/http.js (+1 -1)
📝 client/src/api/socket.js (+1 -1)
📝 client/src/constants/Config.js (+6 -3)
📝 client/src/constants/Paths.js (+8 -6)
📝 client/src/utils/access-token-storage.js (+4 -2)
📝 client/vite.config.js (+1 -0)
server/api/controllers/index/show.js (+19 -0)
📝 server/api/helpers/utils/set-http-only-token-cookie.js (+1 -1)
📝 server/config/custom.js (+1 -1)
📝 server/config/policies.js (+1 -0)
📝 server/config/routes.js (+1 -1)
📝 server/config/views.js (+1 -1)
server/inject-config-template.sh (+26 -0)

📄 Description

Summary

Fixes #1156 and #1323

This PR adds support for deploying Planka under custom URL paths by extracting the path from the BASE_URL environment variable and injecting it into the client at runtime.

Problem

Previously, Planka could only be deployed at the root path (/). Users wanting to deploy it under a subpath (e.g., /planka) behind a reverse proxy had to rebuild the Docker image with build-time environment variables, which is not feasible for users pulling pre-built images.

Solution

Architecture Changes

  1. Runtime Configuration Injection

    • Created a bash script (inject-config-template.sh) that converts the Vite-built index.html into an EJS template
    • Added a new controller (index/show) that injects baseUrlPath from server config into the template
    • Client reads configuration from window.PLANKA_CONFIG at runtime
  2. Path Handling

    • Replaced build-time SERVER_BASE_URL with runtime BASE_PATH throughout the client
    • Updated all route definitions (Paths.js) to use the dynamic base path
    • Modified API and WebSocket paths to include the base path prefix
  3. Cookie Path Fix

    • Fixed authentication cookie paths to handle both root (/) and subpath deployments
    • Added fallback to '/' when baseUrlPath is empty to ensure valid cookie paths
    • Applied fix to both server-side (httpOnlyToken) and client-side (accessToken) cookies

Technical Details

Server changes:

  • server/config/custom.js: Extract and strip trailing slash from BASE_URL pathname
  • server/inject-config-template.sh: AWK script to inject EJS template into HTML (new file)
  • server/api/controllers/index/show.js: Controller that passes baseUrlPath to the view (new file)
  • server/config/routes.js: Changed index from direct view rendering to controller action
  • server/config/views.js: Changed extension from .html to .ejs
  • server/config/policies.js: Added public access policy for index/show controller
  • server/api/helpers/utils/set-http-only-token-cookie.js: Added || '/' fallback for cookie path

Client changes:

  • client/src/constants/Config.js: Read BASE_PATH from window.PLANKA_CONFIG.baseUrlPath at runtime
  • client/src/constants/Paths.js: Prepend BASE_PATH to all route definitions
  • client/src/api/http.js: Use BASE_PATH instead of SERVER_BASE_URL for API calls
  • client/src/api/socket.js: Configure Socket.IO path with BASE_PATH prefix
  • client/src/utils/access-token-storage.js: Set proper cookie paths with fallback to '/'
  • client/vite.config.js: Set base: './' for relative asset paths

Build changes:

  • Dockerfile: Transform index.html to index.ejs template during image build

Testing

Tested with the following nginx configuration:

server {
    listen      80;
    server_name localhost;

    location /planka/ {
        rewrite ^/planka(.*)$ $1 break;
        proxy_pass http://127.0.0.1:3000/;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Prefix /planka;
    }
}

And this BASE_URL environment variable in docker-compose.yml:

environment:
  - BASE_URL=http://localhost/planka  # or any custom path

Breaking Changes

None. Existing deployments at root path continue to work without any configuration changes.

Additional note

This is my first contribution to the project. If something is wrong, missing or anyone has a better idea to implement this, please let me know and I'll adapt my changes to your needs.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/plankanban/planka/pull/1451 **Author:** [@roberfi](https://github.com/roberfi) **Created:** 12/7/2025 **Status:** 🔄 Open **Base:** `master` ← **Head:** `support-url-paths` --- ### 📝 Commits (1) - [`2d61502`](https://github.com/plankanban/planka/commit/2d6150204752dbd29de956c84ab6b3f490c4889f) feat: add support for custom URL paths via BASE_URL configuration ### 📊 Changes **14 files changed** (+76 additions, -18 deletions) <details> <summary>View changed files</summary> 📝 `Dockerfile` (+5 -1) 📝 `client/src/api/http.js` (+1 -1) 📝 `client/src/api/socket.js` (+1 -1) 📝 `client/src/constants/Config.js` (+6 -3) 📝 `client/src/constants/Paths.js` (+8 -6) 📝 `client/src/utils/access-token-storage.js` (+4 -2) 📝 `client/vite.config.js` (+1 -0) ➕ `server/api/controllers/index/show.js` (+19 -0) 📝 `server/api/helpers/utils/set-http-only-token-cookie.js` (+1 -1) 📝 `server/config/custom.js` (+1 -1) 📝 `server/config/policies.js` (+1 -0) 📝 `server/config/routes.js` (+1 -1) 📝 `server/config/views.js` (+1 -1) ➕ `server/inject-config-template.sh` (+26 -0) </details> ### 📄 Description ## Summary Fixes #1156 and #1323 This PR adds support for deploying Planka under custom URL paths by extracting the path from the `BASE_URL` environment variable and injecting it into the client at runtime. ## Problem Previously, Planka could only be deployed at the root path (`/`). Users wanting to deploy it under a subpath (e.g., `/planka`) behind a reverse proxy had to rebuild the Docker image with build-time environment variables, which is not feasible for users pulling pre-built images. ## Solution ### Architecture Changes 1. **Runtime Configuration Injection** - Created a bash script (`inject-config-template.sh`) that converts the Vite-built `index.html` into an EJS template - Added a new controller (`index/show`) that injects `baseUrlPath` from server config into the template - Client reads configuration from `window.PLANKA_CONFIG` at runtime 2. **Path Handling** - Replaced build-time `SERVER_BASE_URL` with runtime `BASE_PATH` throughout the client - Updated all route definitions (`Paths.js`) to use the dynamic base path - Modified API and WebSocket paths to include the base path prefix 3. **Cookie Path Fix** - Fixed authentication cookie paths to handle both root (`/`) and subpath deployments - Added fallback to `'/'` when `baseUrlPath` is empty to ensure valid cookie paths - Applied fix to both server-side (`httpOnlyToken`) and client-side (`accessToken`) cookies ### Technical Details **Server changes:** - `server/config/custom.js`: Extract and strip trailing slash from `BASE_URL` pathname - `server/inject-config-template.sh`: AWK script to inject EJS template into HTML (new file) - `server/api/controllers/index/show.js`: Controller that passes `baseUrlPath` to the view (new file) - `server/config/routes.js`: Changed `index` from direct view rendering to controller action - `server/config/views.js`: Changed extension from `.html` to `.ejs` - `server/config/policies.js`: Added public access policy for `index/show` controller - `server/api/helpers/utils/set-http-only-token-cookie.js`: Added `|| '/'` fallback for cookie path **Client changes:** - `client/src/constants/Config.js`: Read `BASE_PATH` from `window.PLANKA_CONFIG.baseUrlPath` at runtime - `client/src/constants/Paths.js`: Prepend `BASE_PATH` to all route definitions - `client/src/api/http.js`: Use `BASE_PATH` instead of `SERVER_BASE_URL` for API calls - `client/src/api/socket.js`: Configure `Socket.IO` path with `BASE_PATH` prefix - `client/src/utils/access-token-storage.js`: Set proper cookie paths with fallback to `'/'` - `client/vite.config.js`: Set `base: './'` for relative asset paths **Build changes:** - `Dockerfile`: Transform `index.html` to `index.ejs` template during image build ## Testing Tested with the following `nginx` configuration: ``` server { listen 80; server_name localhost; location /planka/ { rewrite ^/planka(.*)$ $1 break; proxy_pass http://127.0.0.1:3000/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Prefix /planka; } } ``` And this `BASE_URL` environment variable in `docker-compose.yml`: ```yaml environment: - BASE_URL=http://localhost/planka # or any custom path ``` ## Breaking Changes None. Existing deployments at root path continue to work without any configuration changes. ## Additional note This is my first contribution to the project. If something is wrong, missing or anyone has a better idea to implement this, please let me know and I'll adapt my changes to your needs. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
OVERLORD added the pull-request label 2026-02-04 22:02:31 +03:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/planka#1302