Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 4 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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 changes: 43 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,也可以直接拉取并运行镜像:
Expand All @@ -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

通过环境变量指定数据库连接字符串:
Expand Down Expand Up @@ -335,7 +374,7 @@ docker-compose up -d

### 配置说明

**端口映射**:默认 `15555` 端口,可在 `docker-compose.yml` 中修改
**端口映射**:默认 `15555` 端口,修改 `docker-compose.yml` 顶部的 `x-webui-port` 即可

**数据持久化**:
```yaml
Expand All @@ -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
```

### 常用命令
Expand Down
22 changes: 12 additions & 10 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -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
Expand Down
25 changes: 22 additions & 3 deletions src/config/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 相关常量
Expand All @@ -57,7 +76,7 @@ class EmailServiceType(str, Enum):
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)
Expand Down Expand Up @@ -280,8 +299,8 @@ def generate_random_user_info() -> dict:
("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"),
]

Expand Down
18 changes: 10 additions & 8 deletions src/config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
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):
"""设置分类"""
Expand Down Expand Up @@ -42,13 +44,13 @@ class 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="应用版本"
),
Expand All @@ -70,13 +72,13 @@ class 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 监听端口"
),
Expand Down Expand Up @@ -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

# 数据库配置
Expand All @@ -608,8 +610,8 @@ def validate_database_url(cls, v):
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")

Expand Down
2 changes: 1 addition & 1 deletion src/core/openai/payment.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ def generate_team_link(
"&elements_session_client[is_aggregation_expected]=false"
"&client_attribution_metadata[merchant_integration_additional_elements][0]=payment"
"&client_attribution_metadata[merchant_integration_additional_elements][1]=address"
f"&key={data["publishable_key"]}"
f"&key={data['publishable_key']}"
,
proxies=_build_proxies(proxy),
timeout=30,
Expand Down
6 changes: 4 additions & 2 deletions tests/e2e/runtime_functionality_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import httpx
import websockets

from src.config.constants import DEFAULT_WEBUI_BASE_URL, DEFAULT_WEBUI_WS_BASE_URL


STALE_ERROR = "服务启动时检测到未完成的历史任务,已标记失败,请重新发起。"

Expand Down Expand Up @@ -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")
Expand Down
19 changes: 19 additions & 0 deletions tests/test_default_webui_port_config.py
Original file line number Diff line number Diff line change
@@ -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"
Loading