Separate API and UI Hosting¶
This page covers the split-host setup where qbtmud is served from one origin and the qBittorrent API is served from another.
If a same-origin reverse proxy is possible, see Reverse proxy hosting.
Why this setup is harder¶
In the normal qBittorrent alternative WebUI model, the browser reaches the UI and API together.
In a split-host model, the browser must cross an origin boundary to reach the API. That introduces extra requirements around:
- the API URL
- CORS
- credentials and cookies
- route handling on the UI host
qbtmud includes credentials with API requests. If the API host does not allow that cross-origin flow, the deployment fails.
Basic setup flow¶
- Deploy the qbtmud
publicdirectory to the UI host. - Identify the public absolute URL for the qBittorrent API host.
- Edit the deployed
public/appsettings.json. - Set
Api.BaseUrlto an absolutehttporhttpsURL. - If the UI host serves qbtmud under a subpath, rewrite
<base href="/">in the HTML response. - Keep
Routing.Modeon"Hash"unless the UI host also supports proper path-route fallback.
Example:
{
"Api": {
"BaseUrl": "https://qbt.example.com/"
},
"Routing": {
"Mode": "Hash"
}
}
qbtmud appends api/v2/ automatically if the configured absolute URL does not already include it.
Choosing Api.BaseUrl¶
Split-host examples:
"https://qbt.example.com/""https://qbt.example.com/qbt/""https://qbt.example.com/api/v2/"
Configure qBittorrent for CORS¶
If the browser is calling the qBittorrent API directly from another origin, qBittorrent must return CORS headers on its WebUI responses.
Because qbtmud sends credentialed browser requests, the API response must:
- allow the exact qbtmud UI origin
- allow credentials
- not use
*as the allowed origin
Minimum header set¶
For a qbtmud UI hosted at https://ui.example.com:
Access-Control-Allow-Origin: https://ui.example.com
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Content-Type
Do not use:
Access-Control-Allow-Origin: *
That is not valid for credentialed browser requests.
Configure the headers in qBittorrent¶
In qBittorrent:
- Open the Web UI settings.
- Enable custom HTTP headers.
- Add one header per line using the values above.
If you edit qBittorrent.conf directly instead, use:
[Preferences]
WebUI\CustomHTTPHeadersEnabled=true
WebUI\CustomHTTPHeaders=Access-Control-Allow-Origin: https://ui.example.com\Access-Control-Allow-Credentials: true\Access-Control-Allow-Methods: GET, POST, OPTIONS\Access-Control-Allow-Headers: Content-Type
In qBittorrent.conf, the custom headers are separated by \.
qBittorrent limitations¶
qBittorrent's custom headers are static.
They are a poor fit when:
- you need multiple allowed origins
- you need origin-specific logic
- you want more advanced CORS behaviour than fixed headers
In those cases, a same-origin proxy design is usually a better fit.
Other requirements¶
Requirements:
- The browser can reach the API URL from the UI origin.
- The API host accepts credentialed requests from that UI origin.
- Any cookies or session state required for qBittorrent authentication are actually sent and accepted.
- The UI host serves the qbtmud entry point correctly for the routing mode you selected.
- If the UI is under a subpath, the HTML response rewrites
<base href="/">to that subpath.
Troubleshooting¶
- If the app shell loads but login fails immediately, treat it as an API reachability, cookie, or CORS problem first.
- If the browser says
Access-Control-Allow-Originis missing or invalid, fix the qBittorrent custom headers before changing qbtmud. - If the browser says credentials are not allowed, add
Access-Control-Allow-Credentials: trueand replace any wildcard origin with the exact qbtmud UI origin. - If requests are going to the wrong origin, correct
Api.BaseUrlin the deployedpublic/appsettings.json. - If the app shell fails under a subpath, fix the HTML
<base href="...">rewrite on the UI host before changing API settings again. - If refreshes fail on the UI host, stay on
Hashor add path-route fallback before tryingPath.