#!/bin/bash #================================================================================ # Certimate & Cloudflare Tunnel Management Script for Debian/Ubuntu # # Author: Gemini # Version: 2.0 (Final Fix - Re-added missing update_software function) # # This script provides a comprehensive toolkit to deploy, manage, update, # backup, and uninstall Certimate with Cloudflared Tunnel. #================================================================================ # --- Configuration Variables --- CERTIMATE_SERVICE_NAME="certimate.service" CLOUDFLARED_SERVICE_NAME="cloudflared.service" CLOUDFLARED_CONFIG_DIR="/etc/cloudflared" SYSTEMD_DIR="/etc/systemd/system" BACKUP_DIR="/opt/certimate_backups" # --- Helper Functions --- print_color() { case "$2" in "green") color="\e[32m";; "red") color="\e[31m";; "yellow")color="\e[33m";; "blue") color="\e[34m";; *) color="\e[0m";; esac echo -e "${color}${1}\e[0m" } print_error() { case "$2" in "red") color="\e[31m";; "yellow")color="\e[33m";; *) color="\e[31m";; esac echo -e "${color}${1}\e[0m" >&2 } check_root() { if [[ $EUID -ne 0 ]]; then print_color "错误:此脚本必须以 root 权限运行。" "red"; exit 1 fi } press_enter_to_continue() { read -p "按 [Enter] 键继续..." } get_service_status_line() { local service_name="$1"; local display_name="$2"; local status_str status_color enabled_str if systemctl is-active --quiet "$service_name"; then status_str="● Running"; status_color="green" else status_str="○ Stopped"; status_color="red" fi if systemctl is-enabled --quiet "$service_name"; then enabled_str="(enabled)" else enabled_str="(disabled)" fi printf "%-12s: [%s] %s\n" "$display_name" "$(print_color "$status_str" "$status_color")" "$enabled_str" } detect_arch() { case "$(uname -m)" in "x86_64") ARCH="amd64" ;; "aarch64") ARCH="arm64" ;; *) print_error "错误:不支持的系统架构: $(uname -m)。" "red"; exit 1 ;; esac echo "$ARCH" } get_certimate_download_url() { local arch="$1"; local release_type="$2"; local api_url=""; local jq_filter="" if [[ "$release_type" == "stable" ]]; then api_url="https://api.github.com/repos/certimate-go/certimate/releases/latest" jq_filter=".assets[] | select(.name | endswith(\"linux_${arch}.zip\")) | .browser_download_url" print_error "正在从 GitHub API 获取最新稳定版本信息..." "yellow" else api_url="https://api.github.com/repos/certimate-go/certimate/releases" jq_filter=".[0].assets[] | select(.name | endswith(\"linux_${arch}.zip\")) | .browser_download_url" print_error "正在从 GitHub API 获取最新(含预发布)版本信息..." "yellow" fi local api_response; api_response=$(curl -s -L -H "Accept: application/vnd.github.v3+json" -H "User-Agent: Certimate-Management-Script" "$api_url") if echo "$api_response" | jq -e '.message' > /dev/null; then local error_msg; error_msg=$(echo "$api_response" | jq -r '.message') print_error "错误:从 GitHub API 获取信息失败: ${error_msg}" "red"; return 1 fi local download_url; download_url=$(echo "$api_response" | jq -r "$jq_filter") if [ -z "$download_url" ] || [ "$download_url" == "null" ]; then print_error "错误:无法在最新版本中找到适用于 'linux_${arch}.zip' 的下载链接。" "red"; return 1 fi echo "$download_url"; return 0 } # --- Core Logic Functions --- deploy_system() { print_color "--- 欢迎使用 Certimate & Cloudflare Tunnel 部署向导 ---" "blue" if [ -f "${SYSTEMD_DIR}/${CERTIMATE_SERVICE_NAME}" ]; then print_color "检测到系统似乎已经部署过了。如果您想重新部署,请先卸载。" "yellow"; return; fi print_color "\n[步骤 1/7] 收集必要信息..." "blue" read -p "请输入 Certimate 的安装目录 (默认: /opt/certimate): " CERTIMATE_INSTALL_DIR CERTIMATE_INSTALL_DIR=${CERTIMATE_INSTALL_DIR:-/opt/certimate} read -p "请输入运行 Certimate 服务的用户名 (默认: nobody): " CERTIMATE_USER CERTIMATE_USER=${CERTIMATE_USER:-nobody} if ! id "$CERTIMATE_USER" &>/dev/null; then read -p "用户 '$CERTIMATE_USER' 不存在。是否创建系统用户? [Y/n]: " create_user_choice if [[ "${create_user_choice:-Y}" =~ ^[Yy]$ ]]; then useradd -r -s /bin/false "$CERTIMATE_USER"; print_color "用户 '$CERTIMATE_USER' 创建成功。" "green"; else print_color "操作中止。" "red"; return; fi fi local CERTIMATE_PORT while true; do read -p "请输入 Certimate 的监听端口 (默认: 8090): " CERTIMATE_PORT; CERTIMATE_PORT=${CERTIMATE_PORT:-8090} if ! [[ "$CERTIMATE_PORT" =~ ^[0-9]+$ ]] || [ "$CERTIMATE_PORT" -lt 1 ] || [ "$CERTIMATE_PORT" -gt 65535 ]; then print_color "无效的端口号。请输入 1-65535 之间的数字。" "red"; continue; fi if ss -Hltn sport eq ":${CERTIMATE_PORT}" | grep -q 'LISTEN'; then print_color "端口 ${CERTIMATE_PORT} 已被占用,请换一个。" "red"; else print_color "端口 ${CERTIMATE_PORT} 可用。" "green"; break; fi done read -p "请输入您要使用的公共域名 (例如: certs.yourdomain.com): " PUBLIC_HOSTNAME if [ -z "$PUBLIC_HOSTNAME" ]; then print_color "错误:公共域名不能为空。" "red"; return; fi print_color "\n[步骤 2/7] 安装依赖软件..." "blue"; apt-get update >/dev/null; apt-get install -y curl wget jq unzip >/dev/null; print_color "依赖安装完成。" "green" print_color "\n[步骤 3/7] 安装 Certimate..." "blue" read -p "是否安装最新的非稳定(Pre-release)版本? [y/N]: " unstable_choice local release_type="stable"; if [[ "$unstable_choice" =~ ^[Yy]$ ]]; then release_type="prerelease"; fi ARCH=$(detect_arch); print_color "检测到系统架构为: $ARCH" "yellow" DOWNLOAD_URL=$(get_certimate_download_url "$ARCH" "$release_type") if [ $? -ne 0 ]; then print_color "部署中止。" "red"; return; fi print_color "正在从 $DOWNLOAD_URL 下载..." "yellow"; mkdir -p "$CERTIMATE_INSTALL_DIR" wget -q -O "/tmp/certimate.zip" "$DOWNLOAD_URL"; unzip -o "/tmp/certimate.zip" -d "$CERTIMATE_INSTALL_DIR"; rm "/tmp/certimate.zip"; chmod +x "${CERTIMATE_INSTALL_DIR}/certimate" local user_group; user_group=$(id -gn "$CERTIMATE_USER"); chown -R "${CERTIMATE_USER}:${user_group}" "$CERTIMATE_INSTALL_DIR" print_color "Certimate 安装并解压到 $CERTIMATE_INSTALL_DIR" "green"; print_color "数据将存储在默认目录: ${CERTIMATE_INSTALL_DIR}/pb_data" "yellow" print_color "\n[步骤 4/7] 安装 Cloudflare Tunnel..." "blue" rm -f /etc/apt/sources.list.d/cloudflared.list; mkdir -p --mode=0755 /usr/share/keyrings curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared buster main' | tee /etc/apt/sources.list.d/cloudflared.list >/dev/null apt-get update >/dev/null; apt-get install -y cloudflared >/dev/null if ! command -v cloudflared &> /dev/null; then print_color "错误: cloudflared 安装失败。" "red"; return; fi; print_color "cloudflared 安装成功。" "green" print_color "\n[步骤 5/7] 授权并创建隧道..." "blue"; press_enter_to_continue; cloudflared tunnel login TUNNEL_NAME="certimate-tunnel"; local TUNNEL_CREATE_OUTPUT; TUNNEL_CREATE_OUTPUT=$(cloudflared tunnel create "$TUNNEL_NAME" 2>&1) local CRED_FILE_PATH; CRED_FILE_PATH=$(echo "$TUNNEL_CREATE_OUTPUT" | grep -o -E '/.*\.json' | head -n 1) local TUNNEL_UUID if [ -n "$CRED_FILE_PATH" ] && [ -f "$CRED_FILE_PATH" ]; then TUNNEL_UUID=$(basename "$CRED_FILE_PATH" .json); print_color "隧道 '$TUNNEL_NAME' 创建成功!" "green" else TUNNEL_UUID=$(cloudflared tunnel list | grep -Fw "$TUNNEL_NAME" | awk '{print $1}') if [ -z "$TUNNEL_UUID" ]; then print_color "错误:创建或查找隧道 '$TUNNEL_NAME' 失败。" "red"; echo "$TUNNEL_CREATE_OUTPUT"; return; fi CRED_FILE_PATH="${HOME}/.cloudflared/${TUNNEL_UUID}.json" if [ ! -f "$CRED_FILE_PATH" ]; then print_color "错误:找不到凭证文件: ${CRED_FILE_PATH}" "red"; return; fi print_color "找到已存在的隧道 '$TUNNEL_NAME'。" "green" fi print_color "\n[步骤 6/7] 生成配置文件..." "blue"; mkdir -p "$CLOUDFLARED_CONFIG_DIR" cat > "${CLOUDFLARED_CONFIG_DIR}/config.yml" << EOF tunnel: ${TUNNEL_UUID} credentials-file: ${CLOUDFLARED_CONFIG_DIR}/${TUNNEL_UUID}.json ingress: - hostname: ${PUBLIC_HOSTNAME} service: http://127.0.0.1:${CERTIMATE_PORT} - service: http_status:404 EOF cp "$CRED_FILE_PATH" "${CLOUDFLARED_CONFIG_DIR}/"; print_color "Cloudflared 配置文件创建成功。" "green" print_color "\n[步骤 7/7] 创建并启动系统服务..." "blue" cat > "${SYSTEMD_DIR}/${CERTIMATE_SERVICE_NAME}" << EOF [Unit] Description=Certimate Go Service After=network.target [Service] Type=simple User=${CERTIMATE_USER} Group=$(id -gn "${CERTIMATE_USER}") WorkingDirectory=${CERTIMATE_INSTALL_DIR} ExecStart=${CERTIMATE_INSTALL_DIR}/certimate serve --http="127.0.0.1:${CERTIMATE_PORT}" Restart=on-failure RestartSec=10s [Install] WantedBy=multi-user.target EOF cloudflared service install >/dev/null; print_color "系统服务文件已创建。" "green" print_color "正在启动服务..." "yellow"; systemctl daemon-reload systemctl enable "$CERTIMATE_SERVICE_NAME" "$CLOUDFLARED_SERVICE_NAME" >/dev/null 2>&1 systemctl restart "$CERTIMATE_SERVICE_NAME"; systemctl restart "$CLOUDFLARED_SERVICE_NAME" print_color "正在为 ${PUBLIC_HOSTNAME} 创建 DNS 记录..." "yellow"; cloudflared tunnel route dns "$TUNNEL_NAME" "$PUBLIC_HOSTNAME" print_color "\n🎉 部署完成! 🎉" "green"; print_color "请稍等片刻,然后通过以下地址访问您的 Certimate 实例:" "yellow"; print_color "https://${PUBLIC_HOSTNAME}" "blue"; echo; manage_services "status" } # [FIXED] Re-added the missing update_software function update_software() { clear print_color "--- 软件更新 ---" "blue" echo "1. 更新 Certimate" echo "2. 更新 Cloudflared" echo "3. 全部更新" echo "0. 返回主菜单" read -p "请输入选项: " choice case $choice in 1) update_certimate ;; 2) update_cloudflared ;; 3) update_certimate; update_cloudflared ;; 0) return ;; *) print_color "无效选项。" "red" ;; esac } update_certimate() { print_color "\n--- 正在更新 Certimate ---" "blue" if ! command -v unzip &> /dev/null; then print_color "正在安装 'unzip'..." "yellow"; apt-get update >/dev/null; apt-get install -y unzip > /dev/null; fi SERVICE_FILE="${SYSTEMD_DIR}/${CERTIMATE_SERVICE_NAME}" if [ ! -f "$SERVICE_FILE" ]; then print_color "错误:找不到 Certimate 服务文件。" "red"; return; fi read -p "是否更新到最新的非稳定(Pre-release)版本? [y/N]: " unstable_choice local release_type="stable"; if [[ "$unstable_choice" =~ ^[Yy]$ ]]; then release_type="prerelease"; fi CERTIMATE_INSTALL_DIR=$(grep -oP 'WorkingDirectory=\K.*' "$SERVICE_FILE") CERTIMATE_USER=$(grep -oP 'User=\K.*' "$SERVICE_FILE") if [ -z "$CERTIMATE_INSTALL_DIR" ]; then print_color "错误:无法解析安装目录。" "red"; return; fi ARCH=$(detect_arch); DOWNLOAD_URL=$(get_certimate_download_url "$ARCH" "$release_type") if [ $? -ne 0 ]; then print_color "更新中止。" "red"; return; fi print_color "正在下载最新版本..." "yellow"; wget -q -O "/tmp/certimate_new.zip" "$DOWNLOAD_URL" print_color "停止 Certimate 服务..." "yellow"; systemctl stop "$CERTIMATE_SERVICE_NAME" print_color "备份旧版本并解压新版本..." "yellow" if [ -f "${CERTIMATE_INSTALL_DIR}/certimate" ]; then mv "${CERTIMATE_INSTALL_DIR}/certimate" "${CERTIMATE_INSTALL_DIR}/certimate_old_$(date +%F)"; fi unzip -o "/tmp/certimate_new.zip" -d "$CERTIMATE_INSTALL_DIR"; rm "/tmp/certimate_new.zip"; chmod +x "${CERTIMATE_INSTALL_DIR}/certimate" if [ -n "$CERTIMATE_USER" ]; then local user_group; user_group=$(id -gn "$CERTIMATE_USER"); chown -R "${CERTIMATE_USER}:${user_group}" "$CERTIMATE_INSTALL_DIR" fi print_color "启动 Certimate 服务..." "yellow"; systemctl start "$CERTIMATE_SERVICE_NAME"; print_color "Certimate 更新成功!" "green" } manage_services() { ACTION=$1; if [ -z "$ACTION" ]; then clear; print_color "--- 服务管理 ---" "blue"; echo "1. 启动所有服务"; echo "2. 停止所有服务"; echo "3. 重启所有服务"; echo "4. 查看所有服务状态"; echo "0. 返回主菜单"; read -p "请输入选项: " choice; case $choice in 1) ACTION="start";; 2) ACTION="stop";; 3) ACTION="restart";; 4) ACTION="status";; 0) return;; *) print_color "无效选项。" "red"; return;; esac; fi if ! [ -f "${SYSTEMD_DIR}/${CERTIMATE_SERVICE_NAME}" ]; then print_color "错误:系统尚未部署。" "red"; return; fi print_color "\n正在对服务执行 [${ACTION}] 操作..." "yellow" if [ "$ACTION" == "status" ]; then print_color "\n--- Certimate 服务状态 ---" "blue"; systemctl status "$CERTIMATE_SERVICE_NAME" --no-pager; print_color "\n--- Cloudflared 服务状态 ---" "blue"; systemctl status "$CLOUDFLARED_SERVICE_NAME" --no-pager; else systemctl "$ACTION" "$CERTIMATE_SERVICE_NAME"; systemctl "$ACTION" "$CLOUDFLARED_SERVICE_NAME"; print_color "\n操作完成!" "green"; fi } update_cloudflared() { print_color "\n--- 正在更新 Cloudflared ---" "blue"; apt-get update >/dev/null; apt-get install -y cloudflared; print_color "Cloudflared 更新完成。正在重启服务..." "yellow"; systemctl restart "$CLOUDFLARED_SERVICE_NAME"; print_color "服务已重启。" "green" } backup_config() { print_color "\n--- 备份配置文件 ---" "blue"; SERVICE_FILE="${SYSTEMD_DIR}/${CERTIMATE_SERVICE_NAME}" if [ ! -f "$SERVICE_FILE" ]; then print_color "错误:系统尚未部署。" "red"; return; fi CERTIMATE_INSTALL_DIR=$(grep -oP 'WorkingDirectory=\K.*' "$SERVICE_FILE") mkdir -p "$BACKUP_DIR"; BACKUP_FILENAME="certimate_backup_$(date +%Y-%m-%d_%H-%M-%S).tar.gz" BACKUP_FILE_PATH="${BACKUP_DIR}/${BACKUP_FILENAME}"; print_color "将要备份以下内容:" "yellow" echo "- ${SERVICE_FILE}"; [ -d "$CERTIMATE_INSTALL_DIR" ] && echo "- ${CERTIMATE_INSTALL_DIR}"; [ -d "$CLOUDFLARED_CONFIG_DIR" ] && echo "- ${CLOUDFLARED_CONFIG_DIR}" BACKUP_ITEMS=""; [ -f "$SERVICE_FILE" ] && BACKUP_ITEMS+=" $SERVICE_FILE"; [ -d "$CERTIMATE_INSTALL_DIR" ] && BACKUP_ITEMS+=" $CERTIMATE_INSTALL_DIR"; [ -d "$CLOUDFLARED_CONFIG_DIR" ] && BACKUP_ITEMS+=" $CLOUDFLARED_CONFIG_DIR" if [ -z "$BACKUP_ITEMS" ]; then print_color "错误:找不到任何需备份的文件。" "red"; return; fi tar -czf "$BACKUP_FILE_PATH" $BACKUP_ITEMS; print_color "\n备份成功!文件保存在: ${BACKUP_FILE_PATH}" "green" } restore_config() { print_color "\n--- 从备份恢复配置 ---" "blue"; read -p "请输入备份文件 (.tar.gz) 的完整路径: " BACKUP_FILE_PATH if [ ! -f "$BACKUP_FILE_PATH" ]; then print_color "错误:备份文件不存在!" "red"; return; fi read -p "警告:此操作将覆盖现有配置!确定吗? [y/N]: " confirm if [[ ! "$confirm" =~ ^[Yy]$ ]]; then print_color "操作已取消。" "yellow"; return; fi print_color "停止服务..." "yellow"; systemctl stop "$CERTIMATE_SERVICE_NAME" "$CLOUDFLARED_SERVICE_NAME" >/dev/null 2>&1 print_color "正在从备份文件中提取..." "yellow"; tar -xzpf "$BACKUP_FILE_PATH" -C / print_color "重新加载 systemd 并重启服务..." "yellow"; systemctl daemon-reload systemctl restart "$CERTIMATE_SERVICE_NAME" "$CLOUDFLARED_SERVICE_NAME"; print_color "\n恢复完成!" "green"; manage_services "status" } uninstall_system() { print_color "\n--- 卸载 Certimate 和 Cloudflare Tunnel ---" "blue" if ! [ -f "${SYSTEMD_DIR}/${CERTIMATE_SERVICE_NAME}" ]; then print_color "错误:系统尚未部署。" "red"; return; fi read -p "警告:此操作将停止服务并删除相关文件!确定吗? [y/N]: " confirm if [[ ! "$confirm" =~ ^[Yy]$ ]]; then print_color "卸载已取消。" "yellow"; return; fi print_color "正在停止并禁用服务..." "yellow"; systemctl stop "$CERTIMATE_SERVICE_NAME" "$CLOUDFLARED_SERVICE_NAME" >/dev/null 2>&1; systemctl disable "$CERTIMATE_SERVICE_NAME" "$CLOUDFLARED_SERVICE_NAME" >/dev/null 2>&1 print_color "正在删除文件..." "yellow"; SERVICE_FILE="${SYSTEMD_DIR}/${CERTIMATE_SERVICE_NAME}"; CERTIMATE_INSTALL_DIR=$(grep -oP 'WorkingDirectory=\K.*' "$SERVICE_FILE"); DEFAULT_DATA_DIR="${CERTIMATE_INSTALL_DIR}/pb_data" rm -f "$SERVICE_FILE" "${SYSTEMD_DIR}/${CLOUDFLARED_SERVICE_NAME}" if [ -d "$CERTIMATE_INSTALL_DIR" ]; then print_color "删除 Certimate 安装目录: $CERTIMATE_INSTALL_DIR" "yellow"; rm -rf "$CERTIMATE_INSTALL_DIR"; fi if [ -d "$DEFAULT_DATA_DIR" ]; then print_color "删除 Certimate 数据目录: $DEFAULT_DATA_DIR" "yellow"; rm -rf "$DEFAULT_DATA_DIR"; fi systemctl daemon-reload; print_color "正在卸载 cloudflared 软件包..." "yellow" apt-get purge -y cloudflared >/dev/null; rm -f /etc/apt/sources.list.d/cloudflared.list* apt-get update >/dev/null read -p "是否删除 Cloudflare 配置目录 (${CLOUDFLARED_CONFIG_DIR})? [y/N]: " delete_config if [[ "$delete_config" =~ ^[Yy]$ ]]; then print_color "正在删除配置目录..." "red"; rm -rf "$CLOUDFLARED_CONFIG_DIR"; print_color "配置已删除。" "green"; else print_color "配置文件已保留。" "yellow"; fi print_color "\n卸载完成!" "green"; print_color "请注意:您可能需要手动登录 Cloudflare Dashboard 删除 DNS 记录和隧道。" "yellow" } main_menu() { while true; do clear print_color "======================================================" "blue" print_color " Certimate & Cloudflare Tunnel 综合管理脚本 " "blue" print_color " (版本 2.0 - 最终修正版) " "blue" print_color "======================================================" "blue" echo if [ -f "${SYSTEMD_DIR}/${CERTIMATE_SERVICE_NAME}" ]; then print_color "当前服务状态:" "yellow" get_service_status_line "$CERTIMATE_SERVICE_NAME" "Certimate" get_service_status_line "$CLOUDFLARED_SERVICE_NAME" "Cloudflared" echo fi echo "1. 部署系统 (首次安装)"; echo "2. 管理服务 (启/停/重/查)"; echo "3. 更新软件" echo "4. 备份配置文件"; echo "5. 从备份恢复配置"; echo "6. 卸载系统" echo "0. 退出脚本" echo read -p "请输入您的选项 [0-6]: " main_choice case $main_choice in 1) deploy_system; press_enter_to_continue ;; 2) manage_services; press_enter_to_continue ;; 3) update_software; press_enter_to_continue ;; 4) backup_config; press_enter_to_continue ;; 5) restore_config; press_enter_to_continue ;; 6) uninstall_system; press_enter_to_continue ;; 0) print_color "感谢使用!再见!" "green"; exit 0 ;; *) print_color "无效的选项。" "red"; sleep 2 ;; esac done } # --- Script Entry Point --- check_root main_menu
作者你好,另一个帖子回复总是自动删除,只能这里问下,请问BBR原版内核不能用的话,我使用 11. 使用BBR+FQ加速 用哪个内核, 我看评论XANMOD只能bbr3,官方cloud可能无法开机,用原版bbr加速的话哪个内核合适。
已回复,见原帖