From 92b7566faa94af52b751191170fedb4b670230bd Mon Sep 17 00:00:00 2001 From: OAC Core Date: Sat, 3 Oct 2026 13:25:32 +0800 Subject: [PATCH] feat(installer): add allow_insecure_origin setting Write OAC_ALLOW_INSECURE_ORIGIN=1 to the installation .env when install.sh (or install.dev.sh) runs with --allow-insecure-origin, and pass it through to Core in compose.yaml. Core already reads the switch (processconfig) to accept a non-loopback plain-HTTP OAC_PUBLIC_URL; the deployment side owned no way to set it after the Compose refactor. Default stays off: without the flag the variable is absent and Core keeps rejecting a non-loopback HTTP origin with its original message. TLS certificate verification is unchanged. - deploy/compose/compose.yaml: pass OAC_ALLOW_INSECURE_ORIGIN to core only. - deploy/install.sh, deploy/install.dev.sh: --allow-insecure-origin flag, usage text, and .env line. - deploy/compose/test_compose.py, deploy/test_install.py: cover the pass-through and the .env key. - docs/configuration.md, docs/getting-started/install-options.md and their Chinese translations. Co-authored-by: multica-agent --- deploy/compose/compose.yaml | 1 + deploy/compose/test_compose.py | 16 ++++++++++++---- deploy/install.dev.sh | 6 ++++++ deploy/install.sh | 8 ++++++-- deploy/test_install.py | 16 ++++++++++++++++ docs/configuration.md | 7 +++++-- docs/getting-started/install-options.md | 5 ++++- docs/zh/configuration.md | 9 ++++++--- docs/zh/getting-started/install-options.md | 7 +++++-- 9 files changed, 61 insertions(+), 14 deletions(-) diff --git a/deploy/compose/compose.yaml b/deploy/compose/compose.yaml index dbe5cdd0..a640d5f2 100644 --- a/deploy/compose/compose.yaml +++ b/deploy/compose/compose.yaml @@ -59,6 +59,7 @@ services: database: {condition: service_healthy} environment: OAC_PUBLIC_URL: &public-url ${OAC_PUBLIC_URL:-http://localhost:8080} + OAC_ALLOW_INSECURE_ORIGIN: ${OAC_ALLOW_INSECURE_ORIGIN:-} OAC_INSTALLATION_ID_FILE: /run/oac/installation.id OAC_DATABASE_URL: postgres://agents_api@database:5432/agents_api?sslmode=disable OAC_DATABASE_PASSWORD_FILE: /run/database/password diff --git a/deploy/compose/test_compose.py b/deploy/compose/test_compose.py index acefbaaa..103630ca 100644 --- a/deploy/compose/test_compose.py +++ b/deploy/compose/test_compose.py @@ -28,14 +28,16 @@ def rendered_compose(directory): class ComposeTests(unittest.TestCase): @classmethod - def render(cls, public_url=None): + def render(cls, public_url=None, allow_insecure_origin=None): env = dict(os.environ) - env.pop('OAC_PUBLIC_URL', None) - for name in ('OAC_IMAGE_CORE', 'OAC_IMAGE_WEB', 'OAC_IMAGE_INGRESS'): + for name in ('OAC_PUBLIC_URL', 'OAC_ALLOW_INSECURE_ORIGIN', + 'OAC_IMAGE_CORE', 'OAC_IMAGE_WEB', 'OAC_IMAGE_INGRESS'): env.pop(name, None) env['OAC_DATA_DIR'] = '/tmp/oac-compose-fixture' if public_url is not None: env['OAC_PUBLIC_URL'] = public_url + if allow_insecure_origin is not None: + env['OAC_ALLOW_INSECURE_ORIGIN'] = allow_insecure_origin return json.loads(subprocess.check_output( ['docker', 'compose', '--env-file', os.devnull, '-f', str(cls.compose_file), 'config', '--format', 'json'], env=env)) @@ -67,9 +69,15 @@ def test_compose_uses_private_services_and_ordered_initialization(self): self.assertEqual(services['web']['healthcheck']['test'], ['CMD', '/usr/local/bin/oac-web', 'healthcheck']) self.assertNotIn('python3', json.dumps(self.compose)) self.assertEqual(services['init']['environment']['OAC_REVISION'], 'd' * 40) - for name in ('OAC_EXECUTION_CONCURRENCY', 'OAC_DEFAULT_HARNESS', 'OAC_HARNESSES', 'OAC_WRITE_AUDIT_RETENTION', 'OAC_LOG_LEVEL'): + for name in ('OAC_EXECUTION_CONCURRENCY', 'OAC_DEFAULT_HARNESS', 'OAC_HARNESSES', 'OAC_WRITE_AUDIT_RETENTION', 'OAC_LOG_LEVEL', 'OAC_ALLOW_INSECURE_ORIGIN'): self.assertEqual(services['core']['environment'][name], '', name) + def test_allow_insecure_origin_passes_through_to_core_only(self): + configured = self.render(public_url='http://10.0.0.5:8080', allow_insecure_origin='1') + self.assertEqual(configured['services']['core']['environment']['OAC_PUBLIC_URL'], 'http://10.0.0.5:8080') + self.assertEqual(configured['services']['core']['environment']['OAC_ALLOW_INSECURE_ORIGIN'], '1') + self.assertNotIn('OAC_ALLOW_INSECURE_ORIGIN', configured['services']['web']['environment']) + def test_public_url_can_be_configured_after_initial_startup(self): for value in (None, '', 'https://oac.example.test', 'http://localhost:9080'): with self.subTest(public_url=value): diff --git a/deploy/install.dev.sh b/deploy/install.dev.sh index d52433a3..5e8737fe 100755 --- a/deploy/install.dev.sh +++ b/deploy/install.dev.sh @@ -8,6 +8,7 @@ repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" install_dir="${OAC_INSTALL_DIR_DEFAULT:-$HOME/.oac/local}" host_address="127.0.0.1" web_port="8080" +allow_insecure_origin=0 if [[ -x "$HOME/.oac/build/env-docker/docker" ]]; then PATH="$HOME/.oac/build/env-docker:$PATH" @@ -16,9 +17,12 @@ fi usage() { cat <<'EOF' Usage: install.dev.sh [--install-dir DIR] [--host ADDRESS] [--web-port PORT] + [--allow-insecure-origin] Builds Core, Web and the init image from this checkout and starts them. Open http://localhost: and sign in with the printed Core key. +--allow-insecure-origin permits a non-loopback plain-HTTP public URL for +development and testing. EOF } @@ -27,6 +31,7 @@ while [[ $# -gt 0 ]]; do --install-dir) install_dir="${2:?}"; shift 2 ;; --host) host_address="${2:?}"; shift 2 ;; --web-port) web_port="${2:?}"; shift 2 ;; + --allow-insecure-origin) allow_insecure_origin=1; shift ;; -h|--help) usage; exit 0 ;; *) echo "Unknown argument: $1" >&2; usage >&2; exit 1 ;; esac @@ -120,6 +125,7 @@ OAC_IMAGE_CORE=$tag/core:dev OAC_IMAGE_WEB=$tag/web:dev OAC_IMAGE_INGRESS=$tag/ingress:dev EOF +if [[ "$allow_insecure_origin" == 1 ]]; then echo "OAC_ALLOW_INSECURE_ORIGIN=1" >>"$install_dir/.env"; fi ( cd "$install_dir" diff --git a/deploy/install.sh b/deploy/install.sh index 46c207ac..cda44d87 100755 --- a/deploy/install.sh +++ b/deploy/install.sh @@ -8,15 +8,17 @@ install_dir="${OAC_INSTALL_DIR_DEFAULT:-$HOME/.oac/core}" public_url="" host_address="0.0.0.0" web_port="8080" +allow_insecure_origin=0 kept=0 usage() { cat <<'EOF' Usage: install.sh [--version TAG] [--install-dir DIR] [--public-url URL] - [--host ADDRESS] [--web-port PORT] + [--host ADDRESS] [--web-port PORT] [--allow-insecure-origin] Installs Core, Web and PostgreSQL, and publishes Web on --web-port. HTTPS is -terminated by your reverse proxy or hosting platform. +terminated by your reverse proxy or hosting platform. --allow-insecure-origin +permits a non-loopback plain-HTTP --public-url for development and testing. EOF } @@ -27,6 +29,7 @@ while [[ $# -gt 0 ]]; do --public-url) public_url="${2:?}"; shift 2 ;; --host) host_address="${2:?}"; shift 2 ;; --web-port) web_port="${2:?}"; shift 2 ;; + --allow-insecure-origin) allow_insecure_origin=1; shift ;; -h|--help) usage; exit 0 ;; *) echo "Unknown argument: $1" >&2; usage >&2; exit 1 ;; esac @@ -97,6 +100,7 @@ umask 077 echo "OAC_HOST=$host_address" echo "OAC_WEB_PORT=$web_port" if [[ -n "$public_url" ]]; then echo "OAC_PUBLIC_URL=$public_url"; fi + if [[ "$allow_insecure_origin" == 1 ]]; then echo "OAC_ALLOW_INSECURE_ORIGIN=1"; fi } >"$install_dir/.env" ( diff --git a/deploy/test_install.py b/deploy/test_install.py index ba04295a..1ac0319c 100644 --- a/deploy/test_install.py +++ b/deploy/test_install.py @@ -64,8 +64,24 @@ def test_env_holds_only_the_installation_choices(self): def test_help_does_not_need_docker(self): help_text = subprocess.run(["bash", str(INSTALL), "--help"], capture_output=True, text=True, check=True) self.assertIn("--web-port", help_text.stdout) + self.assertIn("--allow-insecure-origin", help_text.stdout) self.assertNotIn("--external-proxy", help_text.stdout) + def test_allow_insecure_origin_is_written_only_when_requested(self): + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + completed, _ = self.install(root, "--public-url", "http://10.0.0.5:8080", "--allow-insecure-origin") + self.assertEqual(completed.returncode, 0, completed.stderr) + env = dict(line.split("=", 1) for line in (root / "oac/.env").read_text().splitlines()) + self.assertEqual(env["OAC_PUBLIC_URL"], "http://10.0.0.5:8080") + self.assertEqual(env["OAC_ALLOW_INSECURE_ORIGIN"], "1") + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + completed, _ = self.install(root) + self.assertEqual(completed.returncode, 0, completed.stderr) + env = dict(line.split("=", 1) for line in (root / "oac/.env").read_text().splitlines()) + self.assertNotIn("OAC_ALLOW_INSECURE_ORIGIN", env) + def write_executable(self, path, text): path.write_text(text) path.chmod(path.stat().st_mode | stat.S_IEXEC) diff --git a/docs/configuration.md b/docs/configuration.md index 1b7ece19..f10f9153 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -6,7 +6,7 @@ Every setting of a Core installation has exactly one home. There are two kinds: | Kind | Examples | Home | Change it with | Takes effect | | --- | --- | --- | --- | --- | -| [Process settings](#process-settings-configjson) | Public URL, ports, logging, harnesses, execution concurrency, audit retention, OAuth origins, Runtime history export | `.env` in the installation directory (default `~/.oac/core`) | Edit `.env`, then run `oac apply` | `oac apply` recreates the services that read the changed settings | +| [Process settings](#process-settings-configjson) | Public URL, ports, logging, harnesses, execution concurrency, audit retention, OAuth origins, allow insecure origin, Runtime history export | `.env` in the installation directory (default `~/.oac/core`) | Edit `.env`, then run `oac apply` | `oac apply` recreates the services that read the changed settings | | [Runtime settings](#runtime-settings-web) | Sandbox backend and size, nodes, Projects and keys, default models, executor credentials | Core's PostgreSQL database | Web, or the Core API (`/core/v1`) with the Core key | Saved without a Core restart; nodes prepare Runtime changes asynchronously | Web's **System** page shows the installation's addresses, the default models, the sandbox configuration and, under **Startup settings**, the process settings Core loaded. Secrets live in [`data/secrets/`](#installation-directory), one copy each. No configuration file defines Projects or API keys. @@ -31,6 +31,8 @@ Installer flags in [installation options](./getting-started/install-options.md) `OAC_PUBLIC_URL` is the one origin that applications, nodes, sandboxes and self-hosted executors use. Core derives the daemon WebSocket URL, the self-hosted `remote_url` and each sandbox's connection address from it. The installation serves Web over HTTP on `OAC_WEB_PORT`; your reverse proxy or hosting platform terminates HTTPS and routes to that port. +A `http://` origin is accepted only for a loopback host. A development or test installation can set `OAC_ALLOW_INSECURE_ORIGIN=1` to accept a non-loopback one; TLS certificate verification stays on. + To change it, point the reverse proxy at the new address first, then edit `OAC_PUBLIC_URL` and run `oac apply`. Afterwards: - Nodes on the old address get no new sandboxes: remove them in Web and add them again. @@ -44,6 +46,7 @@ To change it, point the reverse proxy at the new address first, then edit `OAC_P | Variable | Default | Meaning | | --- | --- | --- | | `OAC_PUBLIC_URL` | `http://localhost:8080` | Origin applications, nodes, sandboxes and self-hosted executors use. Managed domain setup writes the HTTPS origin and recreates Core and Web | +| `OAC_ALLOW_INSECURE_ORIGIN` | unset | `1` permits a non-loopback plain-HTTP `OAC_PUBLIC_URL` for development and testing. TLS certificate verification stays on | | `OAC_HOST` | `127.0.0.1` | Address published by `ports.yaml`. `install.sh` sets `0.0.0.0` | | `OAC_WEB_PORT` | `8080` | Host port of Web | | `COMPOSE_FILE` | `compose.yaml:ports.yaml` | The Compose files. `ports.yaml` publishes Web and Core's loopback admin API; hosting platforms omit it | @@ -150,7 +153,7 @@ Core reads only its environment. Compose interpolates `.env` into the service en | `OAC_CREDENTIAL_KEY_FILE` | `data/secrets/core/credential.key` | | `OAC_CORE_KEY_DIGESTS_FILE` | `data/secrets/core/core-key-digests.json`: a JSON array with the SHA-256 of the Core key | | `OAC_INSTALLATION_ID_FILE` | `data/secrets/core/installation.id`: the installation ID, a canonical UUID. It enables the sandbox deployment and node routes and requires `OAC_PUBLIC_URL` and `OAC_CORE_KEY_DIGESTS_FILE`. Core refuses an ID other than the one its database recorded | -| `OAC_EXECUTION_CONCURRENCY`, `OAC_DEFAULT_HARNESS`, `OAC_HARNESSES`, `OAC_WRITE_AUDIT_RETENTION`, `OAC_OAUTH_TRUSTED_ORIGINS` | The matching [process settings](#settings). `oac-core check-config` validates them without starting Core | +| `OAC_EXECUTION_CONCURRENCY`, `OAC_DEFAULT_HARNESS`, `OAC_HARNESSES`, `OAC_WRITE_AUDIT_RETENTION`, `OAC_OAUTH_TRUSTED_ORIGINS`, `OAC_ALLOW_INSECURE_ORIGIN` | The matching [process settings](#settings). `oac-core check-config` validates them without starting Core | | `OAC_HISTORY_SETTINGS_FILE` | Optional Runtime history file. Sensitive; the installation report says only whether it is set | | `OAC_LOG_LEVEL`, `OAC_LOG_FORMAT`, `OAC_LOG_ADD_SOURCE` | Logging; Web reads the same three | | `OAC_PROVIDER_ROOT` | Absolute adapter artifact root. The Core image sets `/opt/oac`. Each adapter owns its helper paths beneath this root | diff --git a/docs/getting-started/install-options.md b/docs/getting-started/install-options.md index 98820b38..b0d0543f 100644 --- a/docs/getting-started/install-options.md +++ b/docs/getting-started/install-options.md @@ -50,9 +50,12 @@ These flags are written to `.env` once. After installation, edit that file and r | Flag | `.env` variable | | --- | --- | | `--public-url` | `OAC_PUBLIC_URL` | +| `--allow-insecure-origin` | `OAC_ALLOW_INSECURE_ORIGIN` | | `--host` | `OAC_HOST` | | `--web-port` | `OAC_WEB_PORT` | +`--allow-insecure-origin` permits a non-loopback plain-HTTP `--public-url` for development and testing. It is off by default; TLS certificate verification stays on. + ## Installation actions @@ -72,7 +75,7 @@ The installer saves no sandbox backend. After signing in, open **System** → ** The default installation publishes Web on `--web-port` (8080) at `--host 0.0.0.0`. Core's admin API stays on `127.0.0.1:8091`. PostgreSQL stays private. `--host` is an IPv4 or IPv6 address, without a port, scheme or zone. Use a concrete server IP in the browser, not a wildcard. -`--public-url` sets `OAC_PUBLIC_URL`, the origin applications, nodes and executors use. Set it to the HTTPS origin your reverse proxy serves. +`--public-url` sets `OAC_PUBLIC_URL`, the origin applications, nodes and executors use. Set it to the HTTPS origin your reverse proxy serves. A non-loopback `http://` origin needs `--allow-insecure-origin`; a loopback one does not. ### Ports diff --git a/docs/zh/configuration.md b/docs/zh/configuration.md index 3adf643e..ee3091cc 100644 --- a/docs/zh/configuration.md +++ b/docs/zh/configuration.md @@ -1,14 +1,14 @@ --- title: "配置参考" source: docs/configuration.md -source_hash: 610b3a85b453d00b575f9fb4d42c87ec89dc3803bb238fd4c36ef734aba6c7e2 +source_hash: 1dbb0c3af7312e925639e9e0a3c868697ff7cbbd321d7aa387ca6732927a38a3 --- Core 安装的每项设置都恰好只有一个归属位置。共有两类: | 类型 | 示例 | 归属位置 | 修改方式 | 生效方式 | | --- | --- | --- | --- | --- | -| [进程设置](#process-settings-configjson) | 公共 URL、端口、日志、Harness、执行并发度、审计保留期、OAuth 来源、Runtime 历史记录导出 | 安装目录中的 `.env`(默认 `~/.oac/core`) | 编辑 `.env`,然后运行 `oac apply` | `oac apply` 会重新创建读取了这些已更改设置的服务 | +| [进程设置](#process-settings-configjson) | 公共 URL、端口、日志、Harness、执行并发度、审计保留期、OAuth 来源、允许不安全源地址、Runtime 历史记录导出 | 安装目录中的 `.env`(默认 `~/.oac/core`) | 编辑 `.env`,然后运行 `oac apply` | `oac apply` 会重新创建读取了这些已更改设置的服务 | | [运行时设置](#runtime-settings-web) | 沙箱后端和大小、节点、项目和密钥、默认模型、执行器凭据 | Core 的 PostgreSQL 数据库 | 在 Web 中修改,或使用 Core 密钥调用 Core API(`/core/v1`) | 保存时无需重启 Core;节点会异步准备 Runtime 变更 | Web 的 **System** 页面显示该安装的地址、默认模型和沙箱配置,并在 **Startup settings** 下以只读方式显示 Core 加载的进程设置。机密信息存放在 [`data/secrets/`](#installation-directory) 中,每项仅保存一份。没有任何配置文件定义项目或 API 密钥。 @@ -33,6 +33,8 @@ Web 的 **System** 页面显示该安装的地址、默认模型和沙箱配置 `OAC_PUBLIC_URL` 是应用、节点、沙箱和自托管执行器使用的唯一源地址。Core 从中派生守护进程 WebSocket URL、自托管 `remote_url` 和每个沙箱的连接地址。安装通过 `OAC_WEB_PORT` 以 HTTP 提供 Web;反向代理或托管平台终止 HTTPS 并把流量转到该端口。 +`http://` 源地址仅对回环主机被接受。开发或测试安装可以设置 `OAC_ALLOW_INSECURE_ORIGIN=1` 来接受非回环源地址;TLS 证书校验保持不变。 + 要更改它,先把反向代理指向新地址,然后编辑 `OAC_PUBLIC_URL` 并运行 `oac apply`。之后: - 使用旧地址的节点不会再获得新沙箱:请在 Web 中移除这些节点,然后重新添加。 @@ -48,6 +50,7 @@ Web 的 **System** 页面显示该安装的地址、默认模型和沙箱配置 | Variable | Default | Meaning | | --- | --- | --- | | `OAC_PUBLIC_URL` | `http://localhost:8080` | Origin applications, nodes, sandboxes and self-hosted executors use. Managed domain setup writes the HTTPS origin and recreates Core and Web | +| `OAC_ALLOW_INSECURE_ORIGIN` | unset | `1` permits a non-loopback plain-HTTP `OAC_PUBLIC_URL` for development and testing. TLS certificate verification stays on | | `OAC_HOST` | `127.0.0.1` | Address published by `ports.yaml`. `install.sh` sets `0.0.0.0` | | `OAC_WEB_PORT` | `8080` | Host port of Web | | `COMPOSE_FILE` | `compose.yaml:ports.yaml` | The Compose files. `ports.yaml` publishes Web and Core's loopback admin API; hosting platforms omit it | @@ -154,7 +157,7 @@ Core 只读取其环境。Compose 把 `.env` 插值进服务环境。Compose 必 | `OAC_CREDENTIAL_KEY_FILE` | `data/secrets/core/credential.key` | | `OAC_CORE_KEY_DIGESTS_FILE` | `data/secrets/core/core-key-digests.json`:一个包含 Core 密钥 SHA-256 的 JSON 数组 | | `OAC_INSTALLATION_ID_FILE` | `data/secrets/core/installation.id`:安装 ID,采用规范 UUID 格式。它会启用沙箱部署和节点路由,并要求设置 `OAC_PUBLIC_URL` 和 `OAC_CORE_KEY_DIGESTS_FILE`。如果 ID 与数据库记录的 ID 不一致,Core 会拒绝它,因此必须将两者一同保留 | -| `OAC_EXECUTION_CONCURRENCY`、`OAC_DEFAULT_HARNESS`、`OAC_HARNESSES`、`OAC_WRITE_AUDIT_RETENTION`、`OAC_OAUTH_TRUSTED_ORIGINS` | 对应的[进程设置](#settings)。`oac-core check-config` 会在不启动 Core 的情况下校验它们 | +| `OAC_EXECUTION_CONCURRENCY`、`OAC_DEFAULT_HARNESS`、`OAC_HARNESSES`、`OAC_WRITE_AUDIT_RETENTION`、`OAC_OAUTH_TRUSTED_ORIGINS`、`OAC_ALLOW_INSECURE_ORIGIN` | 对应的[进程设置](#settings)。`oac-core check-config` 会在不启动 Core 的情况下校验它们 | | `OAC_HISTORY_SETTINGS_FILE` | 可选的 Runtime 历史文件。敏感;安装报告只说明它是否已设置 | | `OAC_LOG_LEVEL`、`OAC_LOG_FORMAT`、`OAC_LOG_ADD_SOURCE` | `log.*`;Web 也读取这三个设置 | | `OAC_PROVIDER_ROOT` | 适配器构件的绝对根目录。Core 镜像设置为 `/opt/oac`。每个适配器都拥有此根目录下的辅助路径 | diff --git a/docs/zh/getting-started/install-options.md b/docs/zh/getting-started/install-options.md index a5ddaf3a..48931f84 100644 --- a/docs/zh/getting-started/install-options.md +++ b/docs/zh/getting-started/install-options.md @@ -1,7 +1,7 @@ --- title: "安装选项与高级部署" source: docs/getting-started/install-options.md -source_hash: f9a5aae96ce8789030eda5cb399eac7c2e6bc6bd4d9bcce18138373c97cb0e96 +source_hash: 53468efe866d0774ec60d015eb6c168dd5ae5170f6b7af0c1505a63e32362d11 --- [默认安装](install.md)无需任何选项。使用本页可以在现有反向代理后运行,或者在无法访问互联网时进行安装。 @@ -55,9 +55,12 @@ docker compose -f compose.yaml exec web oac-web core-key | Flag | `.env` variable | | --- | --- | | `--public-url` | `OAC_PUBLIC_URL` | +| `--allow-insecure-origin` | `OAC_ALLOW_INSECURE_ORIGIN` | | `--host` | `OAC_HOST` | | `--web-port` | `OAC_WEB_PORT` | +`--allow-insecure-origin` 允许开发和测试使用非回环的明文 HTTP `--public-url`。默认关闭;TLS 证书校验保持不变。 + ## 安装操作 {#installation-actions} `--install-dir` 选择安装目录。它不是进程设置。 @@ -76,7 +79,7 @@ docker compose -f compose.yaml exec web oac-web core-key 默认安装在 `--host 0.0.0.0` 的 `--web-port`(8080)上发布 Web。Core 的管理 API 留在 `127.0.0.1:8091`。PostgreSQL 保持私有。`--host` 是不含端口、协议或区域的 IPv4 或 IPv6 地址。请在浏览器中使用服务器的具体 IP,而不是通配地址。 -`--public-url` 设置 `OAC_PUBLIC_URL`,即应用、节点和执行器使用的源地址。把它设为反向代理提供的 HTTPS 源地址。 +`--public-url` 设置 `OAC_PUBLIC_URL`,即应用、节点和执行器使用的源地址。把它设为反向代理提供的 HTTPS 源地址。非回环的 `http://` 源地址需要 `--allow-insecure-origin`;回环地址不需要。 ### 端口 {#ports}