From d6ec01065af6dd57dadc1e53d4f226a1c1a83cbb Mon Sep 17 00:00:00 2001 From: eddy Date: Wed, 1 Jul 2026 03:00:22 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=20NewApi=20=E5=AE=89?= =?UTF-8?q?=E8=A3=85=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增基于 Docker Compose 的 NewApi 安装脚本,包含 SQLite、Redis、随机密钥、健康检查、防火墙配置和定时自动更新 - 在 README 中补充从远程安装路径运行该脚本的命令 --- README.md | 5 ++ install/20-NewApi.sh | 186 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+) create mode 100644 install/20-NewApi.sh diff --git a/README.md b/README.md index 318dd46..8bfcb83 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,11 @@ bash <(curl -fsSL https://gitea.tohub.top/Share/vps/raw/branch/main/install/14-J bash <(curl -fsSL https://gitea.tohub.top/Share/vps/raw/branch/main/install/15-LobeChat.sh) ``` +- 20-NewApi.sh +```sh +bash <(curl -fsSL https://gitea.tohub.top/Share/vps/raw/branch/main/install/20-NewApi.sh) +``` + - 23-Sub2API ```sh bash <(curl -fsSL https://gitea.tohub.top/Share/vps/raw/branch/main/install/23-Sub2API.sh) diff --git a/install/20-NewApi.sh b/install/20-NewApi.sh new file mode 100644 index 0000000..872e1fb --- /dev/null +++ b/install/20-NewApi.sh @@ -0,0 +1,186 @@ +#!/bin/bash +# chmod +x 20-NewApi.sh && ./20-NewApi.sh +# curl -sS -O https://gitea.tohub.top/Share/vps/raw/branch/main/install/20-NewApi.sh && chmod +x 20-NewApi.sh && ./20-NewApi.sh + +set -euo pipefail + +port80=8200 + +if [ "$(id -u)" -ne 0 ]; then + echo "请使用 root 用户运行本脚本。" >&2 + exit 1 +fi + +for required_cmd in openssl curl grep sed apt; do + if ! command -v "$required_cmd" >/dev/null 2>&1; then + echo "未检测到 $required_cmd。本脚本依赖 Debian/Ubuntu 系统环境,请先安装后再运行。" >&2 + exit 1 + fi +done + +# 生成 sed 安全的随机密钥(hex) +redis_password=$(openssl rand -hex 16) +session_secret=$(openssl rand -hex 24) + +ipv4_address=$(curl -fsS --max-time 10 ipv4.ip.sb || true) +# 校验 IPv4 +ipv4_octet='(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])' +if ! printf '%s' "$ipv4_address" | grep -qE "^$ipv4_octet(\.$ipv4_octet){3}$"; then + ipv4_address="服务器IP" +fi + +# 1、更新包(更新失败不阻断后续安装) +export DEBIAN_FRONTEND=noninteractive +apt update -y || true +apt upgrade -y || true + +# 2、创建安装目录 +mkdir -p /root/data/docker_data/NewApi +cd /root/data/docker_data/NewApi || { echo "无法进入安装目录 /root/data/docker_data/NewApi" >&2; exit 1; } + +# 3、填写 docker-compose 配置 +# 先写入占位符,再替换为实际配置 +cat <<'EOF' > docker-compose.yml +services: + new-api: + image: calciumion/new-api:latest + container_name: new-api + restart: always + command: --log-dir /app/logs + ports: + - "__PORT80__:3000" + volumes: + - ./data:/data + - ./logs:/app/logs + - ./sqlite:/app/sqlite # SQLite数据库存储目录 + environment: + - SQL_DB_TYPE=sqlite + - SQL_DB_PATH=/app/sqlite/new-api.db # SQLite数据库文件路径 + - REDIS_CONN_STRING=redis://:__REDIS_PASSWORD__@redis + - TZ=Asia/Shanghai + - SESSION_SECRET=__SESSION_SECRET__ + depends_on: + - redis + healthcheck: + test: + [ + "CMD-SHELL", + "(command -v wget >/dev/null 2>&1 && wget -q -O - http://localhost:3000/api/status || command -v curl >/dev/null 2>&1 && curl -fsS http://localhost:3000/api/status) | grep -q '\"success\"[[:space:]]*:[[:space:]]*true'" + ] + interval: 30s + timeout: 10s + retries: 3 + + redis: + image: redis:alpine # 使用Alpine版本的Redis,更轻量 + container_name: new-api-redis + restart: always + command: redis-server --requirepass __REDIS_PASSWORD__ + volumes: + - redis_data:/data # 持久化Redis数据 + +volumes: + redis_data: +EOF + +# 替换占位符为实际值 +sed -i \ + -e "s|__PORT80__|$port80|g" \ + -e "s|__REDIS_PASSWORD__|$redis_password|g" \ + -e "s|__SESSION_SECRET__|$session_secret|g" \ + docker-compose.yml + +# 4、安装 +if ! command -v docker >/dev/null 2>&1; then + echo "未检测到 docker,请先安装 Docker 后再运行本脚本。" >&2 + exit 1 +fi + +if docker compose version >/dev/null 2>&1; then + compose_cmd=(docker compose) +elif command -v docker-compose >/dev/null 2>&1; then + compose_cmd=(docker-compose) +else + echo "未检测到 docker compose 或 docker-compose,请先安装 Docker Compose。" >&2 + exit 1 +fi + +"${compose_cmd[@]}" up -d + +# 5、打开防火墙的端口 +if command -v ufw >/dev/null 2>&1; then + ufw allow "$port80" + ufw status +else + echo "未检测到 ufw,跳过防火墙端口放行。" +fi + +# 6、配置每日自动更新 +install_dir=/root/data/docker_data/NewApi +update_script=/root/data/docker_data/NewApi/auto-update.sh + +cat <<'EOF' > "$update_script" +#!/bin/bash +set -euo pipefail + +install_dir=/root/data/docker_data/NewApi +archive_dir=/root/data/docker_data/NewApi.archive + +# 备份数据,先写入临时目录,成功后再替换旧备份 +mkdir -p "$(dirname "$archive_dir")" +tmp_archive_dir="${archive_dir}.tmp" + +rm -rf "$tmp_archive_dir" +mkdir -p "$tmp_archive_dir" + +if command -v rsync >/dev/null 2>&1; then + rsync -a --delete --exclude 'auto-update.log' --exclude 'logs/' "$install_dir"/ "$tmp_archive_dir"/ +else + cp -a "$install_dir"/. "$tmp_archive_dir"/ + rm -f "$tmp_archive_dir"/auto-update.log + rm -rf "$tmp_archive_dir"/logs +fi + +rm -rf "$archive_dir" +mv "$tmp_archive_dir" "$archive_dir" + +cd "$install_dir" # 进入 docker-compose 所在的文件夹 + +if docker compose version >/dev/null 2>&1; then + compose_cmd=(docker compose) +elif command -v docker-compose >/dev/null 2>&1; then + compose_cmd=(docker-compose) +else + echo "未检测到 docker compose 或 docker-compose,无法自动更新。" >&2 + exit 1 +fi + +"${compose_cmd[@]}" pull +"${compose_cmd[@]}" up -d + +# 清理旧镜像,释放磁盘空间 +docker image prune -f +EOF + +chmod +x "$update_script" + +# 写入每日 04:00 自动更新任务 +cron_line="0 4 * * * $update_script >> /root/data/docker_data/NewApi/auto-update.log 2>&1" +if command -v crontab >/dev/null 2>&1; then + # 使用脚本路径去重,避免重复写入 NewApi 自动更新任务 + ( crontab -l 2>/dev/null | grep -v -F -- "$update_script" || true ; echo "$cron_line" ) | crontab - + echo "已配置定时自动更新任务:每天 04:00 自动更新 NewApi。" +else + echo "未检测到 crontab,跳过定时更新任务配置。可手动执行 $update_script 更新。" +fi + +# 打印访问链接 +echo "------------------------" +echo "访问链接:" +echo "http://$ipv4_address:$port80" +echo "User: root" +echo "默认密码: 123456 —— 该端口已对公网开放,请【立即】登录并修改密码!" +echo "------------------------" +echo "已开启定时自动更新:每天 04:00 自动备份并拉取最新镜像。" +echo "手动更新可执行:$update_script" +echo "------------------------"