chore(init): 初始化解忧商行项目并完成 Phase 0 基座
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
{
|
||||
email {$CADDY_EMAIL}
|
||||
on_demand_tls {
|
||||
ask http://backend:8080/api/distribution/check-domain
|
||||
}
|
||||
}
|
||||
|
||||
# 反代到后端时,用 Caddy 实测到的对端地址覆盖 X-Real-IP,
|
||||
# 防止客户端伪造 X-Forwarded-For 影响限流、审计和支付下单的 client_ip。
|
||||
(backend_proxy) {
|
||||
header_up X-Real-IP {remote_host}
|
||||
}
|
||||
|
||||
# 公开 API 反代片段:主站与选号网共用。
|
||||
(public_api) {
|
||||
@api_sse {
|
||||
path /api/chats/events /api/admin/chats/events
|
||||
}
|
||||
|
||||
handle @api_sse {
|
||||
reverse_proxy backend:8080 {
|
||||
flush_interval -1
|
||||
import backend_proxy
|
||||
}
|
||||
}
|
||||
|
||||
handle /api/* {
|
||||
request_body {
|
||||
max_size 11MB
|
||||
}
|
||||
reverse_proxy backend:8080 {
|
||||
import backend_proxy
|
||||
}
|
||||
}
|
||||
|
||||
handle /r/* {
|
||||
reverse_proxy backend:8080 {
|
||||
import backend_proxy
|
||||
}
|
||||
}
|
||||
|
||||
@health path /health /health/ready
|
||||
handle @health {
|
||||
reverse_proxy backend:8080 {
|
||||
import backend_proxy
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# 前台商城静态资源与安全头配置(主站与所有分销站点共享):
|
||||
# 前端通过 window.location.hostname 自动向 /api/distribution/site-info 请求分销配置。
|
||||
(storefront) {
|
||||
encode zstd gzip
|
||||
|
||||
header {
|
||||
Strict-Transport-Security "max-age=31536000"
|
||||
X-Content-Type-Options "nosniff"
|
||||
X-Frame-Options "DENY"
|
||||
Referrer-Policy "strict-origin-when-cross-origin"
|
||||
Permissions-Policy "camera=(), microphone=(), geolocation=()"
|
||||
Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' https: data: blob:; font-src 'self' data:; connect-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'; form-action 'self'"
|
||||
}
|
||||
|
||||
import public_api
|
||||
|
||||
# 平台校验文件(如 /e82f...txt)在 /m/<文件名>.txt 下也要能取到真实内容。
|
||||
# /m 是前端路由前缀,未命中静态文件时 try_files 会回退到 index.html,
|
||||
# 导致 /m/*.txt 返回 HTML;这里显式改写回根目录的同名文件。
|
||||
@mobile_verify_txt path_regexp ^/m/([^/]+\.txt)$
|
||||
handle @mobile_verify_txt {
|
||||
rewrite * /{re.mobile_verify_txt.1}
|
||||
root * /srv/dist
|
||||
file_server
|
||||
}
|
||||
|
||||
# 主站后台隐藏入口:storefront 片段同时服务主站和所有分销站点域名,
|
||||
# 这里统一 404,仅主站域名在下方主站 block 用 @main_admin 放行。
|
||||
@platform_admin path {$ADMIN_BASE_PATH:/console-jy8k3m} {$ADMIN_BASE_PATH:/console-jy8k3m}/*
|
||||
handle @platform_admin {
|
||||
respond 404
|
||||
}
|
||||
|
||||
# 生产后台页面使用构建时配置的隐藏入口,旧 /admin 入口直接返回 404。
|
||||
@legacy_admin path /admin /admin/*
|
||||
handle @legacy_admin {
|
||||
respond 404
|
||||
}
|
||||
|
||||
# 其余流量返回主站/分销前台前端静态资源。
|
||||
handle {
|
||||
root * /srv/dist
|
||||
try_files {path} /index.html
|
||||
file_server
|
||||
}
|
||||
}
|
||||
|
||||
# www 域名统一 301 到主域名,避免重复内容与后台入口分散。
|
||||
www.{$CADDY_DOMAIN} {
|
||||
redir https://{$CADDY_DOMAIN}{uri} permanent
|
||||
}
|
||||
|
||||
# 解忧商行主站。
|
||||
{$CADDY_DOMAIN} {
|
||||
# 主站后台隐藏入口只在本域名提供静态资源;分销站点域名由 storefront 片段统一 404。
|
||||
@main_admin path {$ADMIN_BASE_PATH:/console-jy8k3m} {$ADMIN_BASE_PATH:/console-jy8k3m}/*
|
||||
handle @main_admin {
|
||||
root * /srv/dist
|
||||
try_files {path} /index.html
|
||||
file_server
|
||||
}
|
||||
|
||||
import storefront
|
||||
}
|
||||
|
||||
# 分销管理后台使用独立 React + Ant Design 静态资源,API 与主站复用 backend。
|
||||
distribution.{$CADDY_DOMAIN} {
|
||||
encode zstd gzip
|
||||
import public_api
|
||||
handle {
|
||||
root * /srv/distribution-admin
|
||||
try_files {path} /index.html
|
||||
file_server
|
||||
}
|
||||
}
|
||||
|
||||
# 选号网(可选独立站点):仅当 CADDY_SHOW_DOMAIN 有值时由部署脚本启用 conf.d/show.caddy。
|
||||
# 未配置时 conf.d 为空,不影响主站。
|
||||
import /etc/caddy/conf.d/*.caddy
|
||||
|
||||
# Beszel 自带登录与权限控制;单独子域避免与业务站点的 CSP、路由相互影响。
|
||||
monitor.{$CADDY_DOMAIN} {
|
||||
encode zstd gzip
|
||||
|
||||
request_body {
|
||||
max_size 10MB
|
||||
}
|
||||
|
||||
reverse_proxy beszel:8090 {
|
||||
transport http {
|
||||
read_timeout 360s
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# 分销站点动态域名入口:
|
||||
# 支持任意二级域名及分销商独立域名,首次访问时通过 on_demand_tls 触发后端白名单校验并自动签发 SSL 证书。
|
||||
https:// {
|
||||
tls {
|
||||
on_demand
|
||||
}
|
||||
import storefront
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
# syntax=docker/dockerfile:1.7
|
||||
|
||||
# 第一阶段:构建主站前端静态资源
|
||||
FROM node:24-alpine AS build
|
||||
|
||||
ARG VITE_ADMIN_BASE_PATH=/console-jy8k3m
|
||||
ENV VITE_ADMIN_BASE_PATH=${VITE_ADMIN_BASE_PATH}
|
||||
# 主站后台里「打开独立分销后台」按钮与开通凭证使用的分销后台地址。
|
||||
ARG VITE_DISTRIBUTION_ADMIN_URL=https://distribution.zuhaoc.com
|
||||
ENV VITE_DISTRIBUTION_ADMIN_URL=${VITE_DISTRIBUTION_ADMIN_URL}
|
||||
|
||||
WORKDIR /src
|
||||
COPY frontend/package*.json ./
|
||||
RUN --mount=type=cache,target=/root/.npm \
|
||||
npm ci --prefer-offline --no-audit --fund=false
|
||||
COPY frontend/ .
|
||||
RUN npm run build
|
||||
|
||||
# 第二套独立分销管理后台(React + Ant Design)
|
||||
FROM node:24-alpine AS distribution-build
|
||||
WORKDIR /src
|
||||
COPY distribution-admin/package*.json ./
|
||||
RUN --mount=type=cache,target=/root/.npm \
|
||||
npm ci --prefer-offline --no-audit --fund=false
|
||||
COPY distribution-admin/ .
|
||||
RUN npm run build
|
||||
|
||||
# 第三阶段:Caddy 作为公网入口,托管主站、分销后台和选号网静态资源
|
||||
FROM caddy:2.10-alpine
|
||||
|
||||
COPY --from=build /src/dist /srv/dist
|
||||
# show-dist 由 deploy-prod.sh 在 build 前准备(hfb_show 构建产物或占位页)
|
||||
COPY deploy/caddy/show-dist /srv/show-dist
|
||||
COPY --from=distribution-build /src/dist /srv/distribution-admin
|
||||
|
||||
EXPOSE 80 443
|
||||
@@ -0,0 +1,4 @@
|
||||
# 占位片段:保证 import conf.d/*.caddy 至少匹配一个文件。
|
||||
# 选号网站点由 deploy-prod.sh 写入 conf.d/show.caddy。
|
||||
(optional_sites_base) {
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>选号网未构建</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<style>
|
||||
body {
|
||||
font-family: system-ui, sans-serif;
|
||||
max-width: 40rem;
|
||||
margin: 4rem auto;
|
||||
padding: 0 1rem;
|
||||
color: #17233d;
|
||||
line-height: 1.6;
|
||||
}
|
||||
code {
|
||||
background: #f1f5f9;
|
||||
padding: 0.1em 0.35em;
|
||||
border-radius: 4px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>选号网静态资源尚未构建</h1>
|
||||
<p>
|
||||
请配置 <code>CADDY_SHOW_DOMAIN</code> 与 <code>HFB_SHOW_DIR</code> 后重新执行
|
||||
<code>./scripts/deploy-prod.sh</code>,或手动构建
|
||||
<code>hfb_show</code> 并将 <code>dist/</code> 复制到
|
||||
<code>deploy/caddy/show-dist/</code>。
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,37 @@
|
||||
# 由 scripts/deploy-prod.sh 根据 CADDY_SHOW_DOMAIN 生成到 conf.d/show.caddy
|
||||
# 选号网静态页 + 同源 /api 反代到 hfb_jysh backend(本机 Docker 网络,非公网绕行)
|
||||
|
||||
__CADDY_SHOW_DOMAIN__ {
|
||||
encode zstd gzip
|
||||
|
||||
header {
|
||||
Strict-Transport-Security "max-age=31536000"
|
||||
X-Content-Type-Options "nosniff"
|
||||
X-Frame-Options "SAMEORIGIN"
|
||||
Referrer-Policy "strict-origin-when-cross-origin"
|
||||
}
|
||||
|
||||
# 与主站共用后端公开接口;浏览器访问选号网域名下的 /api/* 即可,无需跨域。
|
||||
handle /api/* {
|
||||
request_body {
|
||||
max_size 11MB
|
||||
}
|
||||
reverse_proxy backend:8080 {
|
||||
header_up X-Real-IP {remote_host}
|
||||
header_up X-Forwarded-Proto {scheme}
|
||||
}
|
||||
}
|
||||
|
||||
handle /health {
|
||||
reverse_proxy backend:8080 {
|
||||
header_up X-Real-IP {remote_host}
|
||||
header_up X-Forwarded-Proto {scheme}
|
||||
}
|
||||
}
|
||||
|
||||
handle {
|
||||
root * /srv/show-dist
|
||||
try_files {path} /index.html
|
||||
file_server
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user