Repository: promptfoo/promptfoo
Issue: Self-host at a custom subpath
Root cause: Configuration Error

**Is your feature request related to a problem? Please describe.**
I would like to self-host promptfoo at a subpath instead of at the root url.

**Describe the solution you'd like**
I would like to be able to specify a subpath as a build arg to the Dockerfile so that I can self host at that subpath.

**Describe alternatives you've considered**
I've tried modifying my cluster so that we can serve promptfoo at root but that is not preferable.

**Additional context**
I've already made changes in [my fork](https://github.com/bennibbelink/promptfoo/tree/url-prefix) that allows me to do this, but I'm wondering if there is an easier way to do this.  I'm happy to submit a PR, but am curious to hear feedback from those more familiar with the codebase.


Hi @bennibbelink! Thanks for dropping in an issue. I'm working on a change that'll I believe will make this a moot point. We're getting rid of the NextJS api server and going to be serving everything out of express.

The PR isn't quite ready yet https://github.com/promptfoo/promptfoo/pull/1599 but should land today or early next week.




Thanks for the quick reply @sklein12! I will keep an eye on #1599

Hey @bennibbelink, just wanted to let you know that the ability to self-host Promptfoo at a custom subpath has been deployed in [v0.86.0](https://github.com/promptfoo/promptfoo/releases/tag/0.86.0). I'll go ahead and close this issue, but feel free to reach out if you run into any further issues or have feedback. Thanks again for filing this and helping make Promptfoo better!

@mldangelo I just got around to checking this out, sorry for the delayed response.  How is the subpath configurable? I'm having trouble finding a build-time or run-time setting for this

@bennibbelink there is no configuration needed, the path is determined by the address/path of the docker container

Steps I took to test this locally:

1. Run the promptfoo server: `docker run -it -p 3000:3000 --name promptfoo ghcr.io/promptfoo/promptfoo`
2. Build custom nginx container:

nginx.conf:
```nginx
server {
    listen 80;

    location /pfoosubpath/ {
        proxy_pass http://promptfoo:3000/;
        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;
    }
}
```
Dockerfile:
```Dockerfile
FROM nginx:latest
COPY nginx.conf /etc/nginx/conf.d/default.conf
```
3. Run custom nginx container:  `docker run --link promptfoo:promptfoo -p 80:80 my-nginx`


-----------------------------------------------------------
I can access the api fine - `localhost/pfoosubpath/health` returns 
```json
{
    "status": "OK",
    "version": "0.92.0"
}
```

However, when I access the UI at `localhost/pfoosubpath` I get `index.html` fine but the following calls return 404.  It looks like the UI is not configured to use relative paths (I think the call should be to `localhost/pfoosubpath/assets/...`, right?).

<img width="674" alt="image" src="https://github.com/user-attachments/assets/3e65af7f-350a-4fad-8d48-2508802a0d94">



@bennibbelink I believe everything this is using relative paths, this is the source of `index.html`

![image](https://github.com/user-attachments/assets/cb16ad45-713d-4627-b447-68b5ebb59d27)



I rebuilt the image after adding the line `base: './'` to `src/app/vite.config.ts` (see [vite docs](https://vite.dev/config/shared-options.html#base)) so that it does use relative paths.  Now the requests look correct and I'm getting 200 with valid js/css back, but the page shows 404(?).  Any idea whats going on here @sklein12?

<img width="863" alt="image" src="https://github.com/user-attachments/assets/47696f16-1af5-4865-8027-d58fcffcaada">


@bennibbelink thanks for finding that. We can update it in the repo. 

Are there any errors in the console?

Nope, nothing in the console

@bennibbelink want to hop on a zoom real quick?

Sure!

@bennibbelink cool, book some time here, whatever works for you https://cal.com/steve-klein-10xzxs/30min