From 3bb459143768eeccc53f6f580a50a41ff706a35c Mon Sep 17 00:00:00 2001 From: Parsa Yazdani Date: Sat, 30 Aug 2025 22:40:27 +1000 Subject: [PATCH] Add custom hostname option (#929) ## Description Add `--host` / `-H` CLI argument to allow users to specify the host address the UI should bind to. This allows for more flexibility so people can bind only to `127.0.0.1` for example instead of the default of `0.0.0.0` which exposes all interfaces. Fixes # N/A ## Type of change - [x] New feature (non-breaking change which adds functionality) - [x] This change requires a documentation update ## Checklist: - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my own code - [ ] (N/A) I have commented my code, particularly in hard-to-understand areas - [ ] (N/A) I have added or updated the docstring for new or existing methods - [x] I have modified this PR to merge to the develop branch --------- Co-authored-by: bobokun <12660469+bobokun@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- docs/Commands.md | 1 + docs/Web-API.md | 5 +++-- qbit_manage.py | 24 ++++++++++++++++++------ 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/docs/Commands.md b/docs/Commands.md index 1c15c02..0ba2708 100644 --- a/docs/Commands.md +++ b/docs/Commands.md @@ -3,6 +3,7 @@ | **Shell Command** | **Docker Environment Variable** | **Config Command** | **Description** | **Default Value** | |:---------------------------------------:|:-------------------------------:|:---------------------:|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------------:| | `-ws` or `--web-server` | QBT_WEB_SERVER | N/A | Start the webUI server to handle command requests via HTTP API. | False | +| `-H` or `--host` | QBT_HOST | N/A | Hostname for the web server (default: 0.0.0.0). | 8080 | | `-p` or `--port` | QBT_PORT | N/A | Port number for the web server (default: 8080). | 8080 | | `-b` or `--base-url` | QBT_BASE_URL | N/A | Base URL path for the web UI (e.g., '/qbit-manage'). Default is empty (root). | "" | | `-r` or`--run` | QBT_RUN | N/A | Run without the scheduler. Script will exit after completion. | False | diff --git a/docs/Web-API.md b/docs/Web-API.md index 1719593..1fe6966 100644 --- a/docs/Web-API.md +++ b/docs/Web-API.md @@ -2,14 +2,14 @@ ## Overview -qBit Manage provides a REST API that allows you to trigger commands via HTTP requests. The API server runs on port 8080 by default and can be configured using the `--port` option or `QBT_PORT` environment variable. +qBit Manage provides a REST API that allows you to trigger commands via HTTP requests. The API server runs at 8080, listening to all hostnames, by default and can be configured using the `--host` and `--port` options or `QBT_HOST` and `QBT_PORT` environment variables. ## Running the Web Server ### Command Line ```bash -python qbit_manage.py --web-server --port 8080 +python qbit_manage.py --web-server --host 0.0.0.0 --port 8080 ``` ### Docker @@ -22,6 +22,7 @@ services: container_name: qbit_manage environment: - QBT_WEB_SERVER=true # Enable web server + - QBT_HOST=0.0.0.0 # Set web server host - QBT_PORT=8080 # Set web server port ports: - "8080:8080" # Map container port to host diff --git a/qbit_manage.py b/qbit_manage.py index d0d3d16..c5974b4 100755 --- a/qbit_manage.py +++ b/qbit_manage.py @@ -56,6 +56,14 @@ parser.add_argument( help="Start the webUI server to handle command requests via HTTP API. " "Default: enabled on desktop (non-Docker) runs; disabled in Docker.", ) +parser.add_argument( + "-H", + "--host", + dest="host", + type=str, + default="0.0.0.0", + help="Hostname for the web server (default: 0.0.0.0).", +) parser.add_argument( "-p", "--port", @@ -268,6 +276,7 @@ web_server = get_arg("QBT_WEB_SERVER", args.web_server, arg_bool=True) # Auto-enable web server by default on non-Docker if not explicitly set via env/flag if web_server is None and not is_docker: web_server = True +host = get_arg("QBT_HOST", args.host, arg_int=True) port = get_arg("QBT_PORT", args.port, arg_int=True) base_url = get_arg("QBT_BASE_URL", args.base_url) run = get_arg("QBT_RUN", args.run, arg_bool=True) @@ -338,6 +347,7 @@ for v in [ "debug", "trace", "web_server", + "host", "port", "base_url", ]: @@ -611,6 +621,7 @@ def end(): # Define the web server target at module level (required for Windows spawn/frozen PyInstaller) def run_web_server( + host, port, process_args, is_running, @@ -642,7 +653,7 @@ def run_web_server( # Configure and run uvicorn import uvicorn as _uvicorn - config = _uvicorn.Config(app, host="0.0.0.0", port=port, log_level="info", access_log=False) + config = _uvicorn.Config(app, host=host, port=port, log_level="info", access_log=False) server = _uvicorn.Server(config) server.run() except KeyboardInterrupt: @@ -751,12 +762,12 @@ def main(): logger.debug(f"Unknown CLI arguments ignored: {_unknown_cli}") logger.separator("Starting Web Server") - logger.info(f"Web API server running on http://0.0.0.0:{port}") + logger.info(f"Web API server running on http://{host}:{port}") if base_url: - logger.info(f"Access the WebUI at http://localhost:{port}/{base_url.lstrip('/')}") - logger.info(f"Root path http://localhost:{port}/ will redirect to the WebUI") + logger.info(f"Access the WebUI at http://{host}:{port}/{base_url.lstrip('/')}") + logger.info(f"Root path http://{host}:{port}/ will redirect to the WebUI") else: - logger.info(f"Access the WebUI at http://localhost:{port}") + logger.info(f"Access the WebUI at http://{host}:{port}") # Create a copy of args to pass to the web server process process_args = args.copy() @@ -765,6 +776,7 @@ def main(): web_process = multiprocessing.Process( target=run_web_server, args=( + host, port, process_args, is_running, @@ -781,7 +793,7 @@ def main(): is_desktop_app = os.getenv("QBT_DESKTOP_APP", "").lower() == "true" if not is_docker and not is_desktop_app: try: - ui_url = f"http://127.0.0.1:{port}" + ui_url = f"http://{'127.0.0.1' if host == '0.0.0.0' else host}:{port}" if base_url: ui_url = f"{ui_url}/{base_url.lstrip('/')}" threading.Thread(target=_open_browser_when_ready, args=(ui_url, logger), daemon=True).start()