mirror of
https://github.com/cnlimiter/codex-register.git
synced 2026-05-06 20:02:51 +08:00
refactor: centralize default webui port config
This commit is contained in:
@@ -5,8 +5,8 @@
|
||||
# 监听主机(默认 0.0.0.0)
|
||||
# APP_HOST=0.0.0.0
|
||||
|
||||
# 监听端口(默认 8000)
|
||||
# APP_PORT=8000
|
||||
# 监听端口(默认 15555)
|
||||
# APP_PORT=15555
|
||||
|
||||
# Web UI 访问密钥(默认 admin123,强烈建议修改)
|
||||
# APP_ACCESS_PASSWORD=your_secret_password
|
||||
|
||||
@@ -4,12 +4,14 @@ FROM python:3.11-slim
|
||||
# 设置工作目录
|
||||
WORKDIR /app
|
||||
|
||||
ARG DEFAULT_WEBUI_PORT=15555
|
||||
|
||||
# 设置环境变量
|
||||
ENV PYTHONDONTWRITEBYTECODE=1 \
|
||||
PYTHONUNBUFFERED=1 \
|
||||
# WebUI 默认配置
|
||||
WEBUI_HOST=0.0.0.0 \
|
||||
WEBUI_PORT=15555 \
|
||||
WEBUI_PORT=${DEFAULT_WEBUI_PORT} \
|
||||
LOG_LEVEL=info \
|
||||
DEBUG=0
|
||||
|
||||
@@ -30,7 +32,7 @@ RUN pip install --no-cache-dir --upgrade pip \
|
||||
COPY . .
|
||||
|
||||
# 暴露端口
|
||||
EXPOSE 15555
|
||||
EXPOSE ${DEFAULT_WEBUI_PORT}
|
||||
|
||||
# 启动 WebUI
|
||||
CMD ["python", "webui.py"]
|
||||
|
||||
47
README.md
47
README.md
@@ -104,6 +104,20 @@ cp .env.example .env
|
||||
|
||||
> 优先级:命令行参数 > 环境变量(`.env`)> 数据库设置 > 默认值
|
||||
|
||||
### 修改端口
|
||||
|
||||
默认端口是 `15555`。现在已经收敛到少数几个固定入口:
|
||||
|
||||
- 本地临时启动改端口:直接用 `python webui.py --port 18080`
|
||||
- 本地通过 `.env` 改端口:设置 `APP_PORT=18080`
|
||||
- 源码里的默认端口:修改 `src/config/constants.py` 里的 `DEFAULT_WEBUI_PORT`
|
||||
- Docker Compose 默认端口:修改 `docker-compose.yml` 顶部的 `x-webui-port`
|
||||
- Docker 镜像构建默认端口:修改 `Dockerfile` 里的 `ARG DEFAULT_WEBUI_PORT`
|
||||
|
||||
补充说明:
|
||||
- `src/config/constants.py` 的 `DEFAULT_WEBUI_PORT` 会同时影响默认 Web UI 端口、默认回调地址和 e2e 脚本默认地址。
|
||||
- `docker-compose.yml` 里已经把端口映射、容器内 `WEBUI_PORT` 和健康检查统一绑到同一个 `x-webui-port`,改一处就够。
|
||||
|
||||
### 启动 Web UI
|
||||
|
||||
```bash
|
||||
@@ -141,6 +155,18 @@ docker-compose up -d
|
||||
```
|
||||
你可以在 `docker-compose.yml` 中修改相关的环境变量,例如配置端口或者设置 `WEBUI_ACCESS_PASSWORD` 访问密码。
|
||||
|
||||
如果要修改 Docker Compose 对外端口,直接改文件顶部这一行即可:
|
||||
|
||||
```yaml
|
||||
x-webui-port: &webui-port 15555
|
||||
```
|
||||
|
||||
这一个值会同时同步到:
|
||||
|
||||
- 宿主机端口映射
|
||||
- 容器内 `WEBUI_PORT`
|
||||
- 健康检查访问地址
|
||||
|
||||
#### 直接使用 docker run
|
||||
|
||||
如果你不想使用 docker-compose,也可以直接拉取并运行镜像:
|
||||
@@ -165,6 +191,19 @@ docker run -d \
|
||||
|
||||
> **注意**:`-v $(pwd)/data:/app/data` 挂载参数非常重要,它确保了你的数据库文件和账户信息在容器重启或更新后不会丢失。
|
||||
|
||||
如果你要把容器端口改成 `18080`,`-p` 和 `WEBUI_PORT` 需要一起改:
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
-p 18080:18080 \
|
||||
-e WEBUI_HOST=0.0.0.0 \
|
||||
-e WEBUI_PORT=18080 \
|
||||
-e WEBUI_ACCESS_PASSWORD=your_secure_password \
|
||||
-v $(pwd)/data:/app/data \
|
||||
--name codex-register \
|
||||
ghcr.io/yunxilyf/codex-register:latest
|
||||
```
|
||||
|
||||
### 使用远程 PostgreSQL
|
||||
|
||||
通过环境变量指定数据库连接字符串:
|
||||
@@ -335,7 +374,7 @@ docker-compose up -d
|
||||
|
||||
### 配置说明
|
||||
|
||||
**端口映射**:默认 `15555` 端口,可在 `docker-compose.yml` 中修改。
|
||||
**端口映射**:默认 `15555` 端口,修改 `docker-compose.yml` 顶部的 `x-webui-port` 即可。
|
||||
|
||||
**数据持久化**:
|
||||
```yaml
|
||||
@@ -347,9 +386,9 @@ volumes:
|
||||
**环境变量配置**:
|
||||
```yaml
|
||||
environment:
|
||||
- APP_ACCESS_PASSWORD=mypassword
|
||||
- APP_HOST=0.0.0.0
|
||||
- APP_PORT=15555
|
||||
WEBUI_ACCESS_PASSWORD: mypassword
|
||||
WEBUI_HOST: 0.0.0.0
|
||||
WEBUI_PORT: 15555
|
||||
```
|
||||
|
||||
### 常用命令
|
||||
|
||||
@@ -1,24 +1,26 @@
|
||||
x-webui-port: &webui-port 15555
|
||||
|
||||
services:
|
||||
webui:
|
||||
build: .
|
||||
ports:
|
||||
- "15555:15555"
|
||||
- target: *webui-port
|
||||
published: *webui-port
|
||||
protocol: tcp
|
||||
environment:
|
||||
- WEBUI_HOST=0.0.0.0
|
||||
- WEBUI_PORT=15555
|
||||
- WEBUI_ACCESS_PASSWORD=admin123
|
||||
- DEBUG=0
|
||||
- LOG_LEVEL=info
|
||||
WEBUI_HOST: 0.0.0.0
|
||||
WEBUI_PORT: *webui-port
|
||||
WEBUI_ACCESS_PASSWORD: admin123
|
||||
DEBUG: 0
|
||||
LOG_LEVEL: info
|
||||
volumes:
|
||||
# 挂载数据目录以持久化数据库和日志
|
||||
- ./data:/app/data
|
||||
- ./logs:/app/logs
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
- python
|
||||
- -c
|
||||
- import urllib.request; urllib.request.urlopen('http://127.0.0.1:15555/', timeout=5).read()
|
||||
- CMD-SHELL
|
||||
- python -c "import os, urllib.request; urllib.request.urlopen('http://127.0.0.1:' + os.environ['WEBUI_PORT'] + '/', timeout=5).read()"
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
@@ -48,6 +48,25 @@ class EmailServiceType(str, Enum):
|
||||
APP_NAME = "OpenAI/Codex CLI 自动注册系统"
|
||||
APP_VERSION = "2.0.0"
|
||||
APP_DESCRIPTION = "自动注册 OpenAI/Codex CLI 账号的系统"
|
||||
DEFAULT_WEBUI_HOST = "0.0.0.0"
|
||||
DEFAULT_WEBUI_PORT = 15555
|
||||
DEFAULT_WEBUI_LOCAL_HOST = "127.0.0.1"
|
||||
|
||||
|
||||
def build_http_url(host: str, port: int, path: str = "") -> str:
|
||||
"""构造本地 HTTP URL。"""
|
||||
normalized_path = path if not path or path.startswith("/") else f"/{path}"
|
||||
return f"http://{host}:{port}{normalized_path}"
|
||||
|
||||
|
||||
def build_ws_url(host: str, port: int, path: str = "") -> str:
|
||||
"""构造本地 WebSocket URL。"""
|
||||
normalized_path = path if not path or path.startswith("/") else f"/{path}"
|
||||
return f"ws://{host}:{port}{normalized_path}"
|
||||
|
||||
|
||||
DEFAULT_WEBUI_BASE_URL = build_http_url(DEFAULT_WEBUI_LOCAL_HOST, DEFAULT_WEBUI_PORT)
|
||||
DEFAULT_WEBUI_WS_BASE_URL = build_ws_url(DEFAULT_WEBUI_LOCAL_HOST, DEFAULT_WEBUI_PORT)
|
||||
|
||||
# ============================================================================
|
||||
# OpenAI OAuth 相关常量
|
||||
@@ -57,7 +76,7 @@ APP_DESCRIPTION = "自动注册 OpenAI/Codex CLI 账号的系统"
|
||||
OAUTH_CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann"
|
||||
OAUTH_AUTH_URL = "https://auth.openai.com/oauth/authorize"
|
||||
OAUTH_TOKEN_URL = "https://auth.openai.com/oauth/token"
|
||||
OAUTH_REDIRECT_URI = "http://localhost:15555/auth/callback"
|
||||
OAUTH_REDIRECT_URI = build_http_url("localhost", DEFAULT_WEBUI_PORT, "/auth/callback")
|
||||
OAUTH_SCOPE = "openid email profile offline_access"
|
||||
|
||||
# Codex CLI 专用 OAuth 参数(用于生成 Codex 兼容的 auth.json)
|
||||
@@ -280,8 +299,8 @@ DEFAULT_SETTINGS = [
|
||||
("registration.max_retries", "3", "最大重试次数", "registration"),
|
||||
("registration.timeout", "120", "超时时间(秒)", "registration"),
|
||||
("registration.default_password_length", "12", "默认密码长度", "registration"),
|
||||
("webui.host", "0.0.0.0", "Web UI 监听主机", "webui"),
|
||||
("webui.port", "15555", "Web UI 监听端口", "webui"),
|
||||
("webui.host", DEFAULT_WEBUI_HOST, "Web UI 监听主机", "webui"),
|
||||
("webui.port", str(DEFAULT_WEBUI_PORT), "Web UI 监听端口", "webui"),
|
||||
("webui.debug", "true", "调试模式", "webui"),
|
||||
]
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ from pydantic import BaseModel, field_validator
|
||||
from pydantic.types import SecretStr
|
||||
from dataclasses import dataclass
|
||||
|
||||
from .constants import APP_NAME, APP_VERSION, DEFAULT_WEBUI_HOST, DEFAULT_WEBUI_PORT
|
||||
|
||||
|
||||
class SettingCategory(str, Enum):
|
||||
"""设置分类"""
|
||||
@@ -42,13 +44,13 @@ SETTING_DEFINITIONS: Dict[str, SettingDefinition] = {
|
||||
# 应用信息
|
||||
"app_name": SettingDefinition(
|
||||
db_key="app.name",
|
||||
default_value="OpenAI/Codex CLI 自动注册系统",
|
||||
default_value=APP_NAME,
|
||||
category=SettingCategory.GENERAL,
|
||||
description="应用名称"
|
||||
),
|
||||
"app_version": SettingDefinition(
|
||||
db_key="app.version",
|
||||
default_value="2.0.0",
|
||||
default_value=APP_VERSION,
|
||||
category=SettingCategory.GENERAL,
|
||||
description="应用版本"
|
||||
),
|
||||
@@ -70,13 +72,13 @@ SETTING_DEFINITIONS: Dict[str, SettingDefinition] = {
|
||||
# Web UI 配置
|
||||
"webui_host": SettingDefinition(
|
||||
db_key="webui.host",
|
||||
default_value="0.0.0.0",
|
||||
default_value=DEFAULT_WEBUI_HOST,
|
||||
category=SettingCategory.WEBUI,
|
||||
description="Web UI 监听地址"
|
||||
),
|
||||
"webui_port": SettingDefinition(
|
||||
db_key="webui.port",
|
||||
default_value=15555,
|
||||
default_value=DEFAULT_WEBUI_PORT,
|
||||
category=SettingCategory.WEBUI,
|
||||
description="Web UI 监听端口"
|
||||
),
|
||||
@@ -584,8 +586,8 @@ class Settings(BaseModel):
|
||||
"""
|
||||
|
||||
# 应用信息
|
||||
app_name: str = "OpenAI/Codex CLI 自动注册系统"
|
||||
app_version: str = "2.0.0"
|
||||
app_name: str = APP_NAME
|
||||
app_version: str = APP_VERSION
|
||||
debug: bool = False
|
||||
|
||||
# 数据库配置
|
||||
@@ -608,8 +610,8 @@ class Settings(BaseModel):
|
||||
return v
|
||||
|
||||
# Web UI 配置
|
||||
webui_host: str = "0.0.0.0"
|
||||
webui_port: int = 15555
|
||||
webui_host: str = DEFAULT_WEBUI_HOST
|
||||
webui_port: int = DEFAULT_WEBUI_PORT
|
||||
webui_secret_key: SecretStr = SecretStr("your-secret-key-change-in-production")
|
||||
webui_access_password: SecretStr = SecretStr("admin123")
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ from typing import Any, Dict, List
|
||||
import httpx
|
||||
import websockets
|
||||
|
||||
from src.config.constants import DEFAULT_WEBUI_BASE_URL, DEFAULT_WEBUI_WS_BASE_URL
|
||||
|
||||
|
||||
STALE_ERROR = "服务启动时检测到未完成的历史任务,已标记失败,请重新发起。"
|
||||
|
||||
@@ -254,8 +256,8 @@ def run_verify_recovery_mode(base_url: str, db_path: Path, state_path: Path, rep
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(description="真实服务功能可用性验证脚本")
|
||||
parser.add_argument("--mode", choices=["live", "prepare-recovery", "verify-recovery"], required=True)
|
||||
parser.add_argument("--base-url", default="http://127.0.0.1:15555")
|
||||
parser.add_argument("--ws-url", default="ws://127.0.0.1:15555")
|
||||
parser.add_argument("--base-url", default=DEFAULT_WEBUI_BASE_URL)
|
||||
parser.add_argument("--ws-url", default=DEFAULT_WEBUI_WS_BASE_URL)
|
||||
parser.add_argument("--db-path", required=True)
|
||||
parser.add_argument("--report-path", default="tests_runtime/runtime_functionality_report.json")
|
||||
parser.add_argument("--state-path", default="tests_runtime/runtime_recovery_state.json")
|
||||
|
||||
19
tests/test_default_webui_port_config.py
Normal file
19
tests/test_default_webui_port_config.py
Normal file
@@ -0,0 +1,19 @@
|
||||
from src.config.constants import (
|
||||
DEFAULT_SETTINGS,
|
||||
DEFAULT_WEBUI_BASE_URL,
|
||||
DEFAULT_WEBUI_PORT,
|
||||
DEFAULT_WEBUI_WS_BASE_URL,
|
||||
OAUTH_REDIRECT_URI,
|
||||
)
|
||||
from src.config.settings import SETTING_DEFINITIONS, Settings
|
||||
|
||||
|
||||
def test_default_webui_port_is_shared_from_one_constant():
|
||||
default_settings_map = {key: value for key, value, *_ in DEFAULT_SETTINGS}
|
||||
|
||||
assert SETTING_DEFINITIONS["webui_port"].default_value == DEFAULT_WEBUI_PORT
|
||||
assert Settings().webui_port == DEFAULT_WEBUI_PORT
|
||||
assert default_settings_map["webui.port"] == str(DEFAULT_WEBUI_PORT)
|
||||
assert DEFAULT_WEBUI_BASE_URL == f"http://127.0.0.1:{DEFAULT_WEBUI_PORT}"
|
||||
assert DEFAULT_WEBUI_WS_BASE_URL == f"ws://127.0.0.1:{DEFAULT_WEBUI_PORT}"
|
||||
assert OAUTH_REDIRECT_URI == f"http://localhost:{DEFAULT_WEBUI_PORT}/auth/callback"
|
||||
Reference in New Issue
Block a user