From 0f82920df0511edab0ceaab76506519377cebd9d Mon Sep 17 00:00:00 2001 From: OrangeRoll Date: Fri, 7 Aug 2026 15:27:16 +0800 Subject: [PATCH] =?UTF-8?q?tag(=E9=A1=B9=E7=9B=AE):=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E5=86=85=E5=AE=B9readme=E7=AD=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 3 + .gitignore | 3 + apps/ScreenShareApi/.dockerignore | 4 ++ apps/ScreenShareWeb/.dockerignore | 4 ++ apps/ScreenShareWeb/Dockerfile | 10 ++- apps/ScreenShareWeb/nginx.conf | 20 ++++++ docker-compose.yml | 12 ++-- docs/SERVER_DEPLOYMENT.md | 103 +++++++++++++++++++++++++++ infra/nginx/screenshare.conf.example | 48 +++++++++++++ scripts/package-release.sh | 41 +++++++++++ 10 files changed, 239 insertions(+), 9 deletions(-) create mode 100644 apps/ScreenShareApi/.dockerignore create mode 100644 apps/ScreenShareWeb/.dockerignore create mode 100644 apps/ScreenShareWeb/nginx.conf create mode 100644 docs/SERVER_DEPLOYMENT.md create mode 100644 infra/nginx/screenshare.conf.example create mode 100755 scripts/package-release.sh diff --git a/.env.example b/.env.example index 73aea08..b890d46 100644 --- a/.env.example +++ b/.env.example @@ -13,3 +13,6 @@ AUTH_JWT_SECRET=replace-with-a-different-long-random-secret BOOTSTRAP_ADMIN_USERNAME=admin BOOTSTRAP_ADMIN_PASSWORD=change-this-admin-password BOOTSTRAP_ADMIN_DISPLAY_NAME=管理员 + +# Docker image tag to run; set this to the imported release version on a server. +SCREENSHARE_VERSION=latest diff --git a/.gitignore b/.gitignore index 6a7ce02..fa4e4e1 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,6 @@ infra/caddy/certs/ !.vscode/extensions.json .DS_Store Thumbs.db + +# Release archives generated for offline server deployment +release/ diff --git a/apps/ScreenShareApi/.dockerignore b/apps/ScreenShareApi/.dockerignore new file mode 100644 index 0000000..2534132 --- /dev/null +++ b/apps/ScreenShareApi/.dockerignore @@ -0,0 +1,4 @@ +.gradle +build +.env +*.iml diff --git a/apps/ScreenShareWeb/.dockerignore b/apps/ScreenShareWeb/.dockerignore new file mode 100644 index 0000000..2760ced --- /dev/null +++ b/apps/ScreenShareWeb/.dockerignore @@ -0,0 +1,4 @@ +node_modules +dist +.env +npm-debug.log* diff --git a/apps/ScreenShareWeb/Dockerfile b/apps/ScreenShareWeb/Dockerfile index 8485797..c78203a 100644 --- a/apps/ScreenShareWeb/Dockerfile +++ b/apps/ScreenShareWeb/Dockerfile @@ -1,9 +1,13 @@ -FROM node:22-alpine +FROM node:22-alpine AS build WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci COPY . . +RUN npm run build -EXPOSE 5173 -CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"] +FROM nginx:1.27-alpine +COPY nginx.conf /etc/nginx/conf.d/default.conf +COPY --from=build /app/dist /usr/share/nginx/html + +EXPOSE 80 diff --git a/apps/ScreenShareWeb/nginx.conf b/apps/ScreenShareWeb/nginx.conf new file mode 100644 index 0000000..416a992 --- /dev/null +++ b/apps/ScreenShareWeb/nginx.conf @@ -0,0 +1,20 @@ +server { + listen 80; + server_name _; + + root /usr/share/nginx/html; + index index.html; + + location /api/ { + proxy_pass http://api:8080; + 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 $scheme; + } + + location / { + try_files $uri $uri/ /index.html; + } +} diff --git a/docker-compose.yml b/docker-compose.yml index db4f158..30de538 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,7 +6,7 @@ services: POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} ports: - - "5432:5432" + - "127.0.0.1:5432:5432" volumes: - postgres-data:/var/lib/postgresql/data healthcheck: @@ -23,11 +23,12 @@ services: environment: LIVEKIT_KEYS: "${LIVEKIT_API_KEY}: ${LIVEKIT_API_SECRET}" ports: - - "7880:7880" + - "127.0.0.1:7880:7880" - "7881:7881" - "50000-50100:50000-50100/udp" api: + image: screenshare-api:${SCREENSHARE_VERSION:-latest} build: context: ./apps/ScreenShareApi env_file: .env @@ -52,17 +53,16 @@ services: postgres: condition: service_healthy ports: - - "8080:8080" + - "127.0.0.1:8080:8080" web: + image: screenshare-web:${SCREENSHARE_VERSION:-latest} build: context: ./apps/ScreenShareWeb - environment: - VITE_API_PROXY_TARGET: http://api:8080 depends_on: - api ports: - - "5173:5173" + - "127.0.0.1:5173:80" volumes: postgres-data: diff --git a/docs/SERVER_DEPLOYMENT.md b/docs/SERVER_DEPLOYMENT.md new file mode 100644 index 0000000..e167faa --- /dev/null +++ b/docs/SERVER_DEPLOYMENT.md @@ -0,0 +1,103 @@ +# 服务器离线部署与配置 + +此文档适用于服务器已有 Nginx 的场景。部署包不包含 .env,因为其中存放数据库密码、JWT Secret、LiveKit Secret 和初始管理员密码。 + +## 1. 在构建机生成部署包 + +构建机需要 Docker,并能拉取镜像。 + +~~~bash +cd /path/to/ScreenShare +chmod +x scripts/package-release.sh +sudo ./scripts/package-release.sh 0.1.0 +~~~ + +生成文件: + +~~~text +release/screen-share-0.1.0.tar.gz +~~~ + +如使用 sudo 运行,按需将 release 目录归还给当前用户: + +~~~bash +sudo chown -R $USER:$USER release +~~~ + +## 2. 传输并导入服务器 + +服务器需要 Docker Compose,但不需要访问镜像仓库。 + +~~~bash +scp release/screen-share-0.1.0.tar.gz deploy@your-server:/opt/ +ssh deploy@your-server +cd /opt +tar -xzf screen-share-0.1.0.tar.gz +cd screen-share-0.1.0 +sudo docker load -i images.tar +~~~ + +## 3. 创建服务器 .env + +~~~bash +cp .env.example .env +chmod 600 .env +~~~ + +必须修改下列值,且不要提交或传回 Git: + +~~~dotenv +POSTGRES_PASSWORD=替换为随机数据库密码 +LIVEKIT_API_KEY=生产环境Key +LIVEKIT_API_SECRET=替换为随机LiveKit密钥 +LIVEKIT_PUBLIC_URL=wss://share.example.com +AUTH_JWT_SECRET=替换为随机JWT密钥 +BOOTSTRAP_ADMIN_PASSWORD=替换为强管理员密码 +SCREENSHARE_VERSION=0.1.0 +~~~ + +DOMAIN 仅供文档和 Nginx 示例使用;本项目由你已有的 Nginx 终止 HTTPS。 + +## 4. 配置 Nginx + +复制 infra/nginx/screenshare.conf.example 的 server 配置到现有 Nginx 站点,将 share.example.com、证书路径改为真实值。map 指令只能在 http 块中声明一次。 + +验证并重载: + +~~~bash +sudo nginx -t +sudo systemctl reload nginx +~~~ + +## 5. 启动服务 + +~~~bash +sudo docker compose --env-file .env up -d +sudo docker compose ps +sudo docker compose logs -f api +~~~ + +首次 API 启动会执行 Flyway 迁移并创建 bootstrap 管理员。浏览器访问 https://share.example.com。 + +## 6. 防火墙与安全组 + +开放: + +~~~text +TCP 80, 443, 7881 +UDP 50000-50100 +~~~ + +不要开放 PostgreSQL 5432、API 8080、LiveKit HTTP/WebSocket 7880;它们只绑定到服务器 127.0.0.1。 + +## 7. 更新版本 + +在构建机用新版本号重新打包,例如 0.1.1。服务器上导入新 images.tar,修改 .env 中 SCREENSHARE_VERSION,再重建服务: + +~~~bash +sudo docker load -i images.tar +sed -i 's/^SCREENSHARE_VERSION=.*/SCREENSHARE_VERSION=0.1.1/' .env +sudo docker compose --env-file .env up -d +~~~ + +PostgreSQL 卷会保留;Flyway 会自动执行新增迁移。数据库升级前建议备份卷或执行 pg_dump。 diff --git a/infra/nginx/screenshare.conf.example b/infra/nginx/screenshare.conf.example new file mode 100644 index 0000000..150f96f --- /dev/null +++ b/infra/nginx/screenshare.conf.example @@ -0,0 +1,48 @@ +# Put the map block in nginx.conf's http {} section, only once. +map $http_upgrade $connection_upgrade { + default upgrade; + '' close; +} + +server { + listen 80; + server_name share.example.com; + return 301 https://$host$request_uri; +} + +server { + listen 443 ssl http2; + server_name share.example.com; + + # Replace with your existing certificate paths. + ssl_certificate /etc/letsencrypt/live/share.example.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/share.example.com/privkey.pem; + + location / { + proxy_pass http://127.0.0.1:5173; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + } + + location /api/ { + proxy_pass http://127.0.0.1:8080; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + } + + location /rtc/ { + proxy_pass http://127.0.0.1:7880; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Host $host; + proxy_read_timeout 3600s; + } + + location /twirp/ { + proxy_pass http://127.0.0.1:7880; + proxy_set_header Host $host; + } +} diff --git a/scripts/package-release.sh b/scripts/package-release.sh new file mode 100755 index 0000000..8b06ecb --- /dev/null +++ b/scripts/package-release.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +set -euo pipefail + +version="${1:-}" +if [[ -z "$version" ]]; then + echo "Usage: $0 " + exit 1 +fi + +script_dir="$(cd "$(dirname "$0")" && pwd)" +project_dir="$(cd "$script_dir/.." && pwd)" +release_dir="$project_dir/release" +bundle_dir="$release_dir/screen-share-$version" +archive="$release_dir/screen-share-$version.tar.gz" + +if [[ -e "$bundle_dir" || -e "$archive" ]]; then + echo "Release already exists: $bundle_dir or $archive" + exit 1 +fi + +mkdir -p "$bundle_dir/infra/livekit" "$bundle_dir/infra/nginx" "$bundle_dir/docs" + +docker build -t "screenshare-api:$version" "$project_dir/apps/ScreenShareApi" +docker build -t "screenshare-web:$version" "$project_dir/apps/ScreenShareWeb" +docker pull postgres:16-alpine +docker pull livekit/livekit-server:v1.9.10 + +docker save + -o "$bundle_dir/images.tar" + "screenshare-api:$version" + "screenshare-web:$version" + postgres:16-alpine + livekit/livekit-server:v1.9.10 + +cp "$project_dir/docker-compose.yml" "$bundle_dir/" +cp "$project_dir/.env.example" "$bundle_dir/" +cp "$project_dir/infra/livekit/livekit.yaml" "$bundle_dir/infra/livekit/" +cp "$project_dir/infra/nginx/screenshare.conf.example" "$bundle_dir/infra/nginx/" +cp "$project_dir/docs/SERVER_DEPLOYMENT.md" "$bundle_dir/docs/" + +cat > "$bundle_dir/RELEASE_VERSION" <