Skip to content

Support runtime BASE_URL via environment variable (no image rebuild required) #403

@SimonLou-Dev

Description

@SimonLou-Dev

What type of request is this?

Self-hosting improvement

Clear and concise description of the feature you are proposing

Clear and concise description of the feature you are proposing

Currently, BASE_URL is a build argument (ARG BASE_URL) in the Dockerfile. This means the subpath is baked into the static assets at image build time, users who want to deploy IT-Tools under a subpath (e.g. /it-tools/) must rebuild the Docker image themselves. Pulling the official image from GHCR and setting a runtime environment variable does not work.

The goal is to make BASE_URL a runtime environment variable so that the official image can be deployed under any subpath without rebuilding:

# docker-compose.yml
services:
  it-tools:
    image: ghcr.io/sharevb/it-tools:latest
    environment:
      BASE_URL: /it-tools/  # no rebuild needed

There are two blockers preventing this today:

1. BASE_URL is a Vite build arg — assets paths are hardcoded at build time

Vite uses BASE_URL to generate absolute asset paths in the bundle:

<script src="/it-tools/assets/index-abc123.js"></script>

These paths cannot be changed after the build without a rebuild.

The fix is to build Vite with base: "./" (relative paths) so assets resolve correctly regardless of the subpath at runtime:

// vite.config.ts
const baseUrl = process.env.BASE_URL || './';
base: baseUrl,

Since Vue Router already uses createWebHistory(config.app.baseUrl) and config.app.baseUrl reads from import.meta.env.BASE_URL, the router will continue to work correctly with this change.

2. nginx.conf has a hardcoded rewrite for /it-tools/

The current nginx.conf contains:

location / {
    rewrite ^/it-tools/(.*) /$1 break;
    try_files $uri $uri/ /index.html;
}

This rewrite is hardcoded and only works for /it-tools/. It should be replaced with a dynamic location block using ${BASE_URL} via envsubst (already supported by nginxinc/nginx-unprivileged through the /etc/nginx/templates/ mechanism):

# nginx.conf — default.conf.template
server {
    listen ${PORT};
    listen [::]:${PORT};
    server_name _;
    root /usr/share/nginx/html;
    index index.html;

    include /etc/nginx/mime.types;
    types {
        application/javascript js mjs;
    }

    location ${BASE_URL} {
        try_files $uri $uri/ /index.html;
    }
}

With BASE_URL defaulting to /, behavior is identical to today for existing deployments, no regression.

Is there example of this tool in the wild?

This pattern is used by several self-hosted tools:

  • Gitea: ROOT_URL env var controls the subpath at runtime
  • Grafana: GF_SERVER_ROOT_URL env var, no rebuild needed

Additional context

Source inspection confirms nginx.conf is already a template processed by envsubst (via default.conf.template), only the hardcoded /it-tools/ rewrite and the Vite base option need updating
Default behavior (BASE_URL unset) must remain identical to today, this is a purely additive change

Validations

  • Check the feature is not already implemented in the project.
  • Check that there isn't already an issue that request the same feature to avoid creating a duplicate.
  • Check that the feature can be implemented in a client side only app (IT-Tools is client side only, no server).
  • Everything is written in PLAIN ENGLISH

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions