#!/bin/bash # ============================================================ # TPanel v1.3.1 一键安装脚本 # 官网: https://tpanel.cn # 作者: Zhang Pu # ============================================================ set -e PANEL_VERSION="1.3.1" 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' BLUE='\033[0;34m' 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"; } # 必须 root 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 用户和目录..." if ! id tpanel &>/dev/null; then useradd -r -s /bin/bash -m tpanel fi 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" download_from_github() { local url="$1" log " 尝试下载: $url" rm -f "$TMP_ZIP" # -f: 失败时返回非 0;-S: 显示错误 if curl -fsSL --connect-timeout 15 --max-time 300 -o "$TMP_ZIP" "$url" 2>>"$LOG_FILE"; then # 校验:必须是合法 zip(PK\003\004 开头) if head -c 4 "$TMP_ZIP" | grep -q "PK\x03\x04"; then return 0 else warn " 下载到的东西不是 zip(可能 404 HTML)" return 1 fi else warn " 下载失败 (HTTP 错误或网络不通)" return 1 fi } # 候选 URL 列表(按优先级) URLS=( "https://github.com/${GITHUB_REPO}/releases/download/v${PANEL_VERSION}/tpanel-v${PANEL_VERSION}.zip" "https://github.com/${GITHUB_REPO}/releases/latest/download/tpanel.zip" "https://github.com/${GITHUB_REPO}/archive/refs/tags/v${PANEL_VERSION}.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 " 源码下载成功" DOWNLOADED=1 break fi done # 兜底:本地 /tmp 里如果已有 zip(比如手动上传的),就用它 if [ $DOWNLOADED -eq 0 ]; then for local_zip in /tmp/tpanel.zip /tmp/tpanel_v1.3.zip /tmp/tpanel-v1.3.1.zip; do if [ -f "$local_zip" ] && head -c 4 "$local_zip" 2>/dev/null | grep -q "PK\x03\x04"; 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 " echo " bash install.sh" exit 1 fi # 解压 log " 解压源码..." rm -rf "$INSTALL_DIR"/{backend,frontend} unzip -q -o "$TMP_ZIP" -d /tmp/tpanel_extracted # GitHub 源码 zip 解压后是 tpanel-{version}/ 目录,release zip 一般是顶层 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 Python 虚拟环境 ============== 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 "TPanel 启动后健康检查失败,查看日志: 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 ufw allow ${PANEL_PORT}/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 签发失败(可能 DNS 未解析),稍后可用: 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 echo " 常用命令:" echo " systemctl status tpanel # 查看状态" echo " systemctl restart tpanel # 重启服务" echo " journalctl -u tpanel -f # 实时日志" echo " tail -f ${INSTALL_DIR}/logs/tpanel.log" echo echo " 卸载:" echo " systemctl stop tpanel && systemctl disable tpanel" echo " rm -rf ${INSTALL_DIR} /etc/systemd/system/tpanel.service" echo "============================================================"