R24-1 R24-2: 补齐同机部署脚本与 Nginx 配置
这个提交包含在:
+16
@@ -0,0 +1,16 @@
|
||||
.git
|
||||
.github
|
||||
.agent
|
||||
.agents
|
||||
.codex
|
||||
.claude
|
||||
node_modules
|
||||
client/node_modules
|
||||
server/node_modules
|
||||
client/test-results
|
||||
client/playwright-report
|
||||
server/generated
|
||||
deploy/trialrun/data
|
||||
coverage
|
||||
dist
|
||||
*.log
|
||||
@@ -4,10 +4,17 @@
|
||||
## cp deploy/trialrun/.env.example deploy/trialrun/.env
|
||||
## 然后按需修改 deploy/trialrun/.env 中的值(不要提交 .env)
|
||||
##
|
||||
## 同机公网部署建议:
|
||||
## - 官网继续使用 hyinda.com / www.hyinda.com
|
||||
## - OA 单独使用 oa.example.com 一类二级域名
|
||||
## - 正式公网环境请保持 APP_ORIGIN=https://oa.example.com
|
||||
## - 正式公网环境请保持 COOKIE_SECURE=true
|
||||
## - 若仅做本机临时演练,再改回 http://127.0.0.1:3000 和 COOKIE_SECURE=false
|
||||
##
|
||||
|
||||
# ===== 基础域名(用于 refresh cookie 的 origin 校验)=====
|
||||
# 单域托管模式下,前端与后端同域访问(建议生产/试运行)。
|
||||
APP_ORIGIN="http://127.0.0.1:3000"
|
||||
APP_ORIGIN="https://oa.example.com"
|
||||
|
||||
# ===== 服务端密钥(必须修改)=====
|
||||
JWT_SECRET="change_me_in_trialrun"
|
||||
@@ -68,7 +75,7 @@ HOST="0.0.0.0"
|
||||
PORT="3000"
|
||||
|
||||
# ===== Cookie 安全(HTTPS 反代时建议 true)=====
|
||||
COOKIE_SECURE="false"
|
||||
COOKIE_SECURE="true"
|
||||
|
||||
# ===== Metrics(Prometheus)=====
|
||||
METRICS_ENABLED="true"
|
||||
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
#!/usr/bin/env bash
|
||||
# ============================================================
|
||||
# hyb-oa - 同机部署脚本(本地执行)
|
||||
# ============================================================
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
DEPLOY_SERVER="${DEPLOY_SERVER:-deploy@118.89.77.218}"
|
||||
REMOTE_DIR="${REMOTE_DIR:-/opt/hyb-oa-trialrun}"
|
||||
REMOTE_ENV_FILE="${REMOTE_ENV_FILE:-${REMOTE_DIR}/deploy/trialrun/.env}"
|
||||
ENABLE_WORKER="${ENABLE_WORKER:-0}"
|
||||
ENABLE_MINIO="${ENABLE_MINIO:-0}"
|
||||
SYNC_ENV="${SYNC_ENV:-0}"
|
||||
COMPOSE_FILE="deploy/trialrun/docker-compose.yml"
|
||||
LOCAL_ENV_FILE="deploy/trialrun/.env"
|
||||
|
||||
need_cmd() {
|
||||
command -v "$1" >/dev/null 2>&1 || {
|
||||
echo "[ERROR] 缺少命令: $1" >&2
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
need_cmd rsync
|
||||
need_cmd ssh
|
||||
|
||||
if [[ ! -f "${ROOT_DIR}/${COMPOSE_FILE}" ]]; then
|
||||
echo "[ERROR] 缺少 ${COMPOSE_FILE}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "${SYNC_ENV}" == "1" && ! -f "${ROOT_DIR}/${LOCAL_ENV_FILE}" ]]; then
|
||||
echo "[ERROR] SYNC_ENV=1 但本地不存在 ${LOCAL_ENV_FILE}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ">>> 1. 创建远端目录"
|
||||
ssh "${DEPLOY_SERVER}" "mkdir -p '${REMOTE_DIR}'"
|
||||
|
||||
echo ">>> 2. 同步 OA 仓库到服务器"
|
||||
rsync -az --delete \
|
||||
--exclude '.git' \
|
||||
--exclude '.github' \
|
||||
--exclude '.agent' \
|
||||
--exclude '.agents' \
|
||||
--exclude '.codex' \
|
||||
--exclude '.claude' \
|
||||
--exclude 'node_modules' \
|
||||
--exclude 'client/node_modules' \
|
||||
--exclude 'server/node_modules' \
|
||||
--exclude 'client/test-results' \
|
||||
--exclude 'client/playwright-report' \
|
||||
--exclude 'server/generated' \
|
||||
--exclude 'deploy/trialrun/data' \
|
||||
--exclude 'deploy/trialrun/.env' \
|
||||
--exclude 'coverage' \
|
||||
--exclude 'dist' \
|
||||
--exclude '*.log' \
|
||||
"${ROOT_DIR}/" "${DEPLOY_SERVER}:${REMOTE_DIR}/"
|
||||
|
||||
if [[ "${SYNC_ENV}" == "1" ]]; then
|
||||
echo ">>> 3. 同步部署环境变量"
|
||||
ssh "${DEPLOY_SERVER}" "mkdir -p '$(dirname "${REMOTE_ENV_FILE}")'"
|
||||
rsync -az "${ROOT_DIR}/${LOCAL_ENV_FILE}" "${DEPLOY_SERVER}:${REMOTE_ENV_FILE}"
|
||||
else
|
||||
echo ">>> 3. 跳过 .env 同步(默认安全模式)"
|
||||
echo " 如果你确认本地 deploy/trialrun/.env 可直接上服务器,可用:SYNC_ENV=1 bash deploy/trialrun/deploy.sh"
|
||||
fi
|
||||
|
||||
echo ">>> 4. 在服务器执行部署"
|
||||
ssh "${DEPLOY_SERVER}" \
|
||||
"REMOTE_DIR='${REMOTE_DIR}' REMOTE_ENV_FILE='${REMOTE_ENV_FILE}' COMPOSE_FILE='${COMPOSE_FILE}' ENABLE_WORKER='${ENABLE_WORKER}' ENABLE_MINIO='${ENABLE_MINIO}' bash -s" <<'REMOTE'
|
||||
set -euo pipefail
|
||||
cd "$REMOTE_DIR"
|
||||
mkdir -p deploy/trialrun/data/postgres deploy/trialrun/data/storage deploy/trialrun/data/minio
|
||||
|
||||
if [[ ! -f "$REMOTE_ENV_FILE" ]]; then
|
||||
echo "[ERROR] 远端缺少 $REMOTE_ENV_FILE,请先手工创建或使用 SYNC_ENV=1" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if docker compose version >/dev/null 2>&1; then
|
||||
compose_cmd=(docker compose -f "$COMPOSE_FILE" --env-file "$REMOTE_ENV_FILE")
|
||||
elif command -v docker-compose >/dev/null 2>&1; then
|
||||
compose_cmd=(docker-compose -f "$COMPOSE_FILE" --env-file "$REMOTE_ENV_FILE")
|
||||
else
|
||||
echo "[ERROR] 远端既没有 docker compose,也没有 docker-compose" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
profile_args=()
|
||||
if [[ "$ENABLE_MINIO" == "1" ]]; then
|
||||
profile_args+=(--profile minio)
|
||||
fi
|
||||
if [[ "$ENABLE_WORKER" == "1" ]]; then
|
||||
profile_args+=(--profile worker)
|
||||
fi
|
||||
|
||||
"${compose_cmd[@]}" up -d db
|
||||
if [[ "$ENABLE_MINIO" == "1" ]]; then
|
||||
"${compose_cmd[@]}" "${profile_args[@]}" up -d minio minio_init
|
||||
fi
|
||||
"${compose_cmd[@]}" "${profile_args[@]}" up -d --build server
|
||||
if [[ "$ENABLE_WORKER" == "1" ]]; then
|
||||
"${compose_cmd[@]}" "${profile_args[@]}" up -d worker
|
||||
fi
|
||||
"${compose_cmd[@]}" run --rm init
|
||||
"${compose_cmd[@]}" ps
|
||||
REMOTE
|
||||
|
||||
echo ">>> 5. 部署完成"
|
||||
echo " 远端目录: ${REMOTE_DIR}"
|
||||
echo " 环境文件: ${REMOTE_ENV_FILE}"
|
||||
echo " 请确认 Nginx 已把 OA 域名反代到 127.0.0.1:3000"
|
||||
@@ -43,11 +43,11 @@ services:
|
||||
entrypoint: ["sh", "-c"]
|
||||
command: |
|
||||
set -e
|
||||
for i in $(seq 1 60); do
|
||||
mc alias set local http://minio:9000 "$MINIO_ROOT_USER" "$MINIO_ROOT_PASSWORD" && break || true
|
||||
for i in $$(seq 1 60); do
|
||||
mc alias set local http://minio:9000 "$$MINIO_ROOT_USER" "$$MINIO_ROOT_PASSWORD" && break || true
|
||||
sleep 1
|
||||
done
|
||||
mc mb --ignore-existing "local/$S3_BUCKET"
|
||||
mc mb --ignore-existing "local/$$S3_BUCKET"
|
||||
|
||||
server:
|
||||
build:
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
# hyb-oa 生产反向代理(同机官网服务器)
|
||||
# 使用方式:
|
||||
# 1) 复制到 /etc/nginx/sites-available/hyb-oa
|
||||
# 2) 将 server_name / 证书路径改成你的实际值
|
||||
# 3) ln -sf /etc/nginx/sites-available/hyb-oa /etc/nginx/sites-enabled/hyb-oa
|
||||
# 4) nginx -t && systemctl reload nginx
|
||||
|
||||
limit_req_zone $binary_remote_addr zone=oa_general:10m rate=10r/s;
|
||||
|
||||
upstream hyb_oa_upstream {
|
||||
server 127.0.0.1:3000;
|
||||
keepalive 32;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name oa.hyinda.com;
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name oa.hyinda.com;
|
||||
|
||||
ssl_certificate /etc/nginx/ssl/oa.hyinda.com/server.crt;
|
||||
ssl_certificate_key /etc/nginx/ssl/oa.hyinda.com/server.key;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305;
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_timeout 10m;
|
||||
|
||||
client_max_body_size 20m;
|
||||
|
||||
location / {
|
||||
limit_req zone=oa_general burst=20 nodelay;
|
||||
proxy_pass http://hyb_oa_upstream;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Port 443;
|
||||
proxy_read_timeout 300s;
|
||||
proxy_send_timeout 300s;
|
||||
}
|
||||
|
||||
location /metrics {
|
||||
allow 127.0.0.1;
|
||||
deny all;
|
||||
proxy_pass http://hyb_oa_upstream;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
}
|
||||
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
}
|
||||
@@ -1,14 +1,12 @@
|
||||
# hyb-oa 反向代理示例(Nginx)
|
||||
#
|
||||
# 说明:
|
||||
# - 适用于单机试运行:Nginx(443) -> hyb-oa server(3000)
|
||||
# - server 内已启用 `trustProxy: true`,会读取 X-Forwarded-*。
|
||||
# - 快速试运行:可先用本文件的 HTTP 版本
|
||||
# - 正式公网:建议直接使用 deploy/trialrun/nginx-hyb-oa.conf
|
||||
#
|
||||
server {
|
||||
listen 80;
|
||||
server_name oa.example.com;
|
||||
|
||||
# 试运行可以先走 http;生产建议配 TLS 并把 COOKIE_SECURE=true
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
proxy_http_version 1.1;
|
||||
@@ -17,6 +15,6 @@ server {
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Port $server_port;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env bash
|
||||
# ============================================================
|
||||
# hyb-oa - 同机部署服务器初始化脚本(在服务器上执行)
|
||||
# 适用:官网 hyb-web 已在同机运行,现新增 OA 子域名
|
||||
# ============================================================
|
||||
set -euo pipefail
|
||||
|
||||
DEPLOY_USER="${DEPLOY_USER:-deploy}"
|
||||
REMOTE_DIR="${REMOTE_DIR:-/opt/hyb-oa-trialrun}"
|
||||
OA_HOST="${OA_HOST:-oa.hyinda.com}"
|
||||
NGINX_SITE_NAME="${NGINX_SITE_NAME:-hyb-oa}"
|
||||
|
||||
need_cmd() {
|
||||
command -v "$1" >/dev/null 2>&1 || {
|
||||
echo "[ERROR] 缺少命令: $1" >&2
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
if [[ "$(id -u)" -ne 0 ]]; then
|
||||
echo "[ERROR] 请以 root 执行该脚本" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ">>> 1. 安装 Docker / Compose 插件 / rsync"
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get update -y
|
||||
apt-get install -y docker.io rsync
|
||||
|
||||
if apt-cache show docker-compose-plugin >/dev/null 2>&1; then
|
||||
apt-get install -y docker-compose-plugin
|
||||
elif apt-cache show docker-compose-v2 >/dev/null 2>&1; then
|
||||
apt-get install -y docker-compose-v2
|
||||
elif apt-cache show docker-compose >/dev/null 2>&1; then
|
||||
apt-get install -y docker-compose
|
||||
else
|
||||
echo "[WARN] 未在当前软件源找到 Compose 插件/包,请后续手工安装 Docker Compose。" >&2
|
||||
fi
|
||||
systemctl enable docker
|
||||
systemctl start docker
|
||||
|
||||
echo ">>> 2. 让 ${DEPLOY_USER} 可运行 Docker"
|
||||
id "${DEPLOY_USER}" >/dev/null 2>&1 || {
|
||||
echo "[ERROR] 用户 ${DEPLOY_USER} 不存在,请先按官网方式创建 deploy 用户" >&2
|
||||
exit 1
|
||||
}
|
||||
usermod -aG docker "${DEPLOY_USER}"
|
||||
|
||||
echo ">>> 3. 创建 OA 目录"
|
||||
mkdir -p "${REMOTE_DIR}/deploy/trialrun/data/postgres"
|
||||
mkdir -p "${REMOTE_DIR}/deploy/trialrun/data/storage"
|
||||
mkdir -p "${REMOTE_DIR}/deploy/trialrun/data/minio"
|
||||
mkdir -p "/etc/nginx/ssl/${OA_HOST}"
|
||||
chown -R "${DEPLOY_USER}:${DEPLOY_USER}" "${REMOTE_DIR}"
|
||||
|
||||
echo ">>> 4. 初始化完成,后续手工操作:"
|
||||
echo " 1) 把 OA Nginx 配置放到 /etc/nginx/sites-available/${NGINX_SITE_NAME}"
|
||||
echo " 2) ln -sf /etc/nginx/sites-available/${NGINX_SITE_NAME} /etc/nginx/sites-enabled/${NGINX_SITE_NAME}"
|
||||
echo " 3) 上传证书到 /etc/nginx/ssl/${OA_HOST}/server.crt 和 server.key"
|
||||
echo " 4) 在 ${REMOTE_DIR}/deploy/trialrun/.env 写入 OA 环境变量"
|
||||
echo " 5) 切换到 deploy 用户后,从本地执行 deploy/trialrun/deploy.sh"
|
||||
echo " 6) 执行 nginx -t && systemctl reload nginx"
|
||||
在新工单中引用
屏蔽一个用户