用 IP 地址搭一套自签名 HTTPS:够用、可控、不折腾域名

如果服务只给自己或受控用户通过 IP 访问,自签名 HTTPS 完全可行:不需要域名,也不用开放 80 端口。代价是浏览器默认会提示"证书不受信任",要消除提示,就得在每台访问终端上信任这张证书,更好的做法是信任自己的内部 CA。它不适合面向公网陌生用户,因为自签名无法提供公共 CA 那样的身份认证。

整套流程可以概括为"证书 → 配置 → 网关 → 验证"四段,其中只有最后一段会与浏览器产生信任交互:
flowchart LR A"生成 IP 自签名证书\
SAN = IP"
--> B"配置 .env\
HTTPS 地址与证书路径"
B --> C"生成数据源主密钥\
写入本机 .env"
C --> D"构建前端" D --> E"生成 Nginx 网关配置" E --> F"停止 Vite 前端" F --> G"启动 Nginx\
对外 8025"
G --> H{"浏览器访问<br/>证书是否受信"} H -- "未受信" --> I"确认指纹后手动继续\
或导入证书 / 内部 CA"
H -- "已受信" --> J"正常访问" I --> J

01 | 生成 IP 自签名证书

进入项目目录,创建证书存放目录并收紧权限:

bash 复制代码
cd /home/alfred/projects/fastOnto

mkdir -p .runtime/tls
chmod 700 .runtime/tls

接着生成证书:

bash 复制代码
openssl req -x509 -newkey rsa:3072 -sha256 -nodes -days 365 \
  -keyout .runtime/tls/privkey.pem \
  -out .runtime/tls/fullchain.pem \
  -subj "/CN=[已脱敏IP]" \
  -addext "subjectAltName = IP:[已脱敏IP]"

chmod 600 .runtime/tls/privkey.pem .runtime/tls/fullchain.pem

关键是 subjectAltName = IP:[已脱敏IP] 这一项。只写 CN 不够,现代浏览器会检查 SAN。

02 | 配置环境变量与主密钥

修改 .env,把对外地址切到 HTTPS,并指定证书和私钥路径:

bash 复制代码
FASTONTO_PUBLIC_ORIGIN=https://[已脱敏IP]:8025
FASTONTO_ALLOW_INSECURE_HTTP=false

FASTONTO_TLS_CERT_FILE=/home/alfred/projects/fastOnto/.runtime/tls/fullchain.pem
FASTONTO_TLS_KEY_FILE=/home/alfred/projects/fastOnto/.runtime/tls/privkey.pem

然后生成外部业务数据源加密主密钥:

bash 复制代码
conda run -n fastonto python -c \
'import base64,secrets; print(base64.urlsafe_b64encode(secrets.token_bytes(32)).decode().rstrip("="))'

将结果仅写入本机 .env:

bash 复制代码
FASTONTO_SOURCE_MASTER_KEY=生成的值
FASTONTO_SOURCE_MASTER_KEY_VERSION=v1

这一步涉及三类配置项,职责各不相同,混在一起容易配错:
flowchart TB subgraph ENV".env 配置" direction TB O"FASTONTO_PUBLIC_ORIGIN\
对外 HTTPS 地址"
I"FASTONTO_ALLOW_INSECURE_HTTP\
置为 false"
T"FASTONTO_TLS_CERT_FILE\
证书路径"
K"FASTONTO_TLS_KEY_FILE\
私钥路径"
M"FASTONTO_SOURCE_MASTER_KEY\
主密钥与版本"
end O --> R"对外访问与 Secure Cookie 行为" I --> R T --> N"Nginx 网关加载证书" K --> N M --> S"外部数据源凭据加密"

03 | 切换前端网关并访问

先构建前端:

bash 复制代码
cd /home/alfred/projects/fastOnto/frontend
npm run build

再生成项目网关配置:

bash 复制代码
cd /home/alfred/projects/fastOnto
conda run -n fastonto python -m app.frontend_gateway

停止当前 Vite 前端,然后按生成的配置启动 Nginx:

bash 复制代码
bash scripts/stop-frontend.sh

nginx -c /home/alfred/projects/fastOnto/.runtime/nginx/nginx.conf \
  -p /home/alfred/projects/fastOnto/.runtime/nginx

后端仍监听本机回环地址 127.0.0.1:8026,由 Nginx 反向代理对外提供 HTTPS。浏览器访问:

text 复制代码
https://[已脱敏IP]:8025

首次会出现证书告警。确认指纹正确后可手动继续;由于本文第 01 步生成的是自签名证书本身,可将该证书导入访问者浏览器或操作系统的信任库来消除告警。若后续改为由内部 CA 签发,则应导入内部 CA 根证书而非叶子证书。

请求路径上,对外只暴露 Nginx 的 8025 端口,后端始终留在回环地址上:
flowchart LR U"浏览器\
https://\[已脱敏IP
:8025"] --> N"Nginx\
加载 fullchain.pem / privkey.pem"
N --> B"后端\
127.0.0.1:8026"

04 | 普通用户启动 Nginx 的日志权限处理

如果是普通用户,上述命令打开默认日志会权限不足。不要用 sudo nginx,改为显式指定当前项目可写的错误日志:

bash 复制代码
cd /home/alfred/projects/fastOnto

touch .runtime/nginx/error.log
chmod 600 .runtime/nginx/error.log

nginx \
  -e /home/alfred/projects/fastOnto/.runtime/nginx/error.log \
  -c /home/alfred/projects/fastOnto/.runtime/nginx/nginx.conf \
  -p /home/alfred/projects/fastOnto/.runtime/nginx

先做配置检查:

bash 复制代码
nginx -t \
  -e /home/alfred/projects/fastOnto/.runtime/nginx/error.log \
  -c /home/alfred/projects/fastOnto/.runtime/nginx/nginx.conf \
  -p /home/alfred/projects/fastOnto/.runtime/nginx

若检查失败,查看项目私有日志:

bash 复制代码
cat /home/alfred/projects/fastOnto/.runtime/nginx/error.log

之后检查是否监听 HTTPS:

bash 复制代码
ss -ltnp | grep 8025
curl -k -I https://[已脱敏IP]:8025/

-k 仅用于快速确认服务可达,它会跳过证书校验,无法验证 SAN 是否正确。要验证证书本身,可改用 curl --cacert .runtime/tls/fullchain.pem -I https://[已脱敏IP]:8025/;浏览器应手工确认或导入证书/内部 CA 信任。

排查顺序建议固定下来,避免在权限、配置、证书三类问题之间来回试:
flowchart TD S"启动 Nginx" --> P{"是否报日志权限错误"} P -- "是" --> L"改用 -e 指定项目内 error.log\
不使用 sudo nginx"
P -- "否" --> T{"nginx -t 配置检查"} L --> T T -- "失败" --> E"查看 .runtime/nginx/error.log" E --> T T -- "通过" --> R"ss 检查 8025 监听" R --> C"curl 验证服务可达" C --> V"curl --cacert 验证证书\
或浏览器确认 / 导入信任"

在 FASTONTO_PUBLIC_ORIGIN 为 https:// 且 FASTONTO_ALLOW_INSECURE_HTTP=false 的前提下,fastOnto 会启用 Secure Cookie,外部 Oracle 数据源凭据配置接口也会允许使用;具体行为以所用版本的实际配置和测试结果为准。


关注我,和AI一起成长~