#!/bin/bash # ============================================================ # TPanel v1.3.2 一键安装脚本 # 官网: https://tpanel.cn # 作者: Zhang Pu # 修复: 2026-06-05 - 修复 zip 魔数校验永远失败的 bug(grep -q "PK\x03\x04") # 修复: 2026-06-04 - 修正下载源 URL(去掉不存在的 404 路径) # ============================================================ set -e PANEL_VERSION="1.3.2" PANEL_PORT=8888 GITHUB_REPO="zhang-pu/tpanel" INSTALL_DIR="/opt/tpanel" LOG_FILE="/tmp/tpanel_install.log" RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m' log() { echo -e "${GREEN}[$(date +%H:%M:%S)]${NC} $1" | tee -a "$LOG_FILE"; } warn() { echo -e "${YELLOW}[!]${NC} $1" | tee -a "$LOG_FILE"; } err() { echo -e "${RED}[✗]${NC} $1" | tee -a "$LOG_FILE"; } ok() { echo -e "${GREEN}[✓]${NC} $1" | tee -a "$LOG_FILE"; } if [ "$EUID" -ne 0 ]; then err "请用 root 用户运行: sudo bash install.sh"; exit 1 fi # 探测包管理器 if command -v apt-get &>/dev/null; then PKG="apt-get"; PKG_UPDATE="apt-get update"; PKG_INSTALL="apt-get install -y" elif command -v yum &>/dev/null; then PKG="yum"; PKG_UPDATE="yum makecache"; PKG_INSTALL="yum install -y" elif command -v dnf &>/dev/null; then PKG="dnf"; PKG_UPDATE="dnf makecache"; PKG_INSTALL="dnf install -y" else err "不支持的发行版(需要 apt / yum / dnf)"; exit 1 fi log "检测到包管理器: $PKG" read -p "请输入 TPanel 访问域名(留空用 IP): " PANEL_DOMAIN PANEL_DOMAIN=$(echo "$PANEL_DOMAIN" | xargs) # 1/8 依赖 log "[1/8] 安装系统依赖..." $PKG_UPDATE >>"$LOG_FILE" 2>&1 || warn "更新源失败,继续..." DEB_PKGS="nginx python3 python3-pip python3-venv sqlite3 certbot python3-certbot-nginx curl wget unzip" RPM_PKGS="nginx python3 python3-pip sqlite certbot python3-certbot-nginx curl wget unzip" if [ "$PKG" = "apt-get" ]; then $PKG_INSTALL $DEB_PKGS >>"$LOG_FILE" 2>&1 || { err "依赖安装失败,查看 $LOG_FILE"; exit 1; } else $PKG_INSTALL $RPM_PKGS >>"$LOG_FILE" 2>&1 || { err "依赖安装失败,查看 $LOG_FILE"; exit 1; } fi ok "依赖安装完成" # 2/8 用户和目录 log "[2/8] 创建 TPanel 用户和目录..." id tpanel &>/dev/null || useradd -r -s /bin/bash -m tpanel mkdir -p "$INSTALL_DIR"/{backend,frontend,logs,backups,sites,ssl} chown -R tpanel:tpanel "$INSTALL_DIR" ok "目录就绪: $INSTALL_DIR" # 3/8 下载源码 log "[3/8] 下载 TPanel v${PANEL_VERSION} 源码..." TMP_ZIP="/tmp/tpanel-v${PANEL_VERSION}.zip" # 校验文件是否为合法 zip(看前 4 字节魔数 50 4b 03 04) is_valid_zip() { local file="$1" [ -f "$file" ] || return 1 local magic magic=$(od -An -tx1 -N4 "$file" 2>/dev/null | tr -d ' \n') [ "$magic" = "504b0304" ] } download_from_github() { local url="$1" log " 尝试下载: $url" rm -f "$TMP_ZIP" if curl -fsSL --connect-timeout 15 --max-time 300 -o "$TMP_ZIP" "$url" 2>>"$LOG_FILE"; then if is_valid_zip "$TMP_ZIP"; then return 0 else warn " 下载到的东西不是 zip(可能 404 HTML)" return 1 fi else warn " 下载失败 (HTTP 错误或网络不通)" return 1 fi } # ✅ 修正后的下载源(按优先级,只保留真实存在的) URLS=( # 1. 官网镜像(最快,国内用户友好) "https://tpanel.cn/tpanel-v${PANEL_VERSION}-source.zip" # 2. GitHub release 当前版本 "https://github.com/${GITHUB_REPO}/releases/download/v${PANEL_VERSION}/tpanel-v${PANEL_VERSION}-source.zip" # 3. latest 通用 - install.sh 路径 "https://github.com/${GITHUB_REPO}/releases/latest/download/install.sh" # 4. 源码 tag zip "https://github.com/${GITHUB_REPO}/archive/refs/tags/v${PANEL_VERSION}.zip" # 5. main 分支源码 zip "https://github.com/${GITHUB_REPO}/archive/refs/heads/main.zip" ) DOWNLOADED=0 for url in "${URLS[@]}"; do if download_from_github "$url"; then ok " 源码下载成功 ($(ls -lh $TMP_ZIP | awk '{print $5}'))" DOWNLOADED=1 break fi done # 本地兜底 if [ $DOWNLOADED -eq 0 ]; then for local_zip in /tmp/tpanel.zip /tmp/tpanel_v1.3.zip /tmp/tpanel-v1.3.1.zip /tmp/tpanel-v1.3.1-source.zip; do if [ -f "$local_zip" ] && is_valid_zip "$local_zip"; then warn " GitHub 下载失败,使用本地 $local_zip" cp "$local_zip" "$TMP_ZIP" DOWNLOADED=1 ok " 使用本地源码" break fi done fi if [ $DOWNLOADED -eq 0 ]; then err "所有下载源都失败!" echo echo " 手动下载后放到 /tmp/tpanel.zip 再重跑:" echo " wget -O /tmp/tpanel.zip https://tpanel.cn/tpanel-v${PANEL_VERSION}-source.zip" echo " bash install.sh" exit 1 fi # 解压(自适应目录) log " 解压源码..." rm -rf "$INSTALL_DIR"/{backend,frontend} unzip -q -o "$TMP_ZIP" -d /tmp/tpanel_extracted if [ -d /tmp/tpanel_extracted/tpanel-main ]; then EXTRACT_DIR=/tmp/tpanel_extracted/tpanel-main elif [ -d /tmp/tpanel_extracted/tpanel-${PANEL_VERSION} ]; then EXTRACT_DIR=/tmp/tpanel_extracted/tpanel-${PANEL_VERSION} elif [ -d /tmp/tpanel_extracted/backend ]; then EXTRACT_DIR=/tmp/tpanel_extracted else err " 解压目录结构不认识: /tmp/tpanel_extracted/" ls -la /tmp/tpanel_extracted/ exit 1 fi cp -r "$EXTRACT_DIR"/backend "$INSTALL_DIR/" cp -r "$EXTRACT_DIR"/frontend "$INSTALL_DIR/" chown -R tpanel:tpanel "$INSTALL_DIR" ok "源码部署完成" # 4/8 venv log "[4/8] 配置 Python 虚拟环境..." sudo -u tpanel python3 -m venv "$INSTALL_DIR/venv" sudo -u tpanel "$INSTALL_DIR/venv/bin/pip" install --upgrade pip >>"$LOG_FILE" 2>&1 sudo -u tpanel "$INSTALL_DIR/venv/bin/pip" install -r "$INSTALL_DIR/backend/requirements.txt" >>"$LOG_FILE" 2>&1 || { err "Python 依赖安装失败,查看 $LOG_FILE"; exit 1; } ok "Python 环境就绪" # 5/8 Nginx log "[5/8] 配置 Nginx..." cat > /etc/nginx/sites-available/tpanel <>"$LOG_FILE" 2>&1 && systemctl reload nginx ok "Nginx 配置完成" # 6/8 systemd log "[6/8] 注册 systemd 服务..." cat > /etc/systemd/system/tpanel.service <>"$LOG_FILE" 2>&1 systemctl restart tpanel sleep 2 if curl -fs http://127.0.0.1:${PANEL_PORT}/api/health >/dev/null 2>&1; then ok "TPanel 启动成功" else warn "健康检查失败,查看: journalctl -u tpanel -n 50" fi # 7/8 防火墙 log "[7/8] 配置防火墙..." if command -v ufw &>/dev/null; then ufw allow 80/tcp >/dev/null 2>&1 || true ufw allow 443/tcp >/dev/null 2>&1 || true ok "ufw 规则已添加" elif command -v firewall-cmd &>/dev/null; then firewall-cmd --permanent --add-service=http >/dev/null 2>&1 || true firewall-cmd --permanent --add-service=https >/dev/null 2>&1 || true firewall-cmd --reload >/dev/null 2>&1 || true ok "firewalld 规则已添加" else warn "未检测到防火墙,跳过" fi # 8/8 SSL if [ -n "$PANEL_DOMAIN" ]; then log "[8/8] 申请 SSL 证书(${PANEL_DOMAIN})..." if certbot --nginx -d "$PANEL_DOMAIN" --non-interactive --agree-tos -m "admin@${PANEL_DOMAIN}" >>"$LOG_FILE" 2>&1; then ok "SSL 证书签发成功" else warn "SSL 签发失败,稍后手动: certbot --nginx -d ${PANEL_DOMAIN}" fi else log "[8/8] 跳过 SSL(无域名)" fi ACCESS_URL="http://${PANEL_DOMAIN:-$(curl -s ifconfig.me 2>/dev/null || echo 'YOUR_SERVER_IP')}" echo echo "============================================================" echo -e "${GREEN} TPanel v${PANEL_VERSION} 安装完成!${NC}" echo "============================================================" echo echo " 访问地址: ${ACCESS_URL}" echo " 默认账号: admin" echo " 默认密码: tpanel.cn" echo echo -e "${YELLOW} ⚠️ 请登录后立即修改密码!${NC}" echo "============================================================"