From 743824e0a266f416a1459b3f95a1332467fb58a5 Mon Sep 17 00:00:00 2001 From: xzx3344521 Date: Tue, 18 Nov 2025 08:39:35 +0800 Subject: [PATCH] =?UTF-8?q?Create=20=E8=87=AA=E5=8A=A8=E9=83=A8=E7=BD=B2?= =?UTF-8?q?=E5=B9=B6=E9=85=8D=E7=BD=AE=20cloudflared=20=E9=9A=A7=E9=81=93?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 自动部署并配置 cloudflared 隧道服务 --- 自动部署并配置 cloudflared 隧道服务 | 221 ++++++++++++++++++++++++++++ 1 file changed, 221 insertions(+) create mode 100644 自动部署并配置 cloudflared 隧道服务 diff --git a/自动部署并配置 cloudflared 隧道服务 b/自动部署并配置 cloudflared 隧道服务 new file mode 100644 index 0000000..6e2984c --- /dev/null +++ b/自动部署并配置 cloudflared 隧道服务 @@ -0,0 +1,221 @@ +#!/bin/bash + +# cloudflared Docker 容器化一键部署脚本 +# 功能:自动部署并配置 cloudflared 隧道服务 + +set -e # 遇到任何错误立即退出脚本 + +# 颜色定义用于输出美化 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # 无颜色 + +# Cloudflare Tunnel 令牌(您提供的) +CF_TUNNEL_TOKEN="eyJhIjoiYmI2OTg1ZGU4N2ZiMDEyYjNjNjI2YWExM2VkYTY3OTciLCJ0IjoiNGYyMjNhM2UtNWNjYy00ZmMwLWI1N2MtNjQzZGY5ZmI1ZWZmIiwicyI6Ik1qTmxOR1U0WmpndE5ERXlPQzAwTjJKaExUazNaVFl0WVRWaU5tUmtObVkxTkdSaSJ9" + +# 输出带颜色的信息函数 +log_info() { + echo -e "${GREEN}[INFO]${NC} $1" +} + +log_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +log_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +log_step() { + echo -e "${BLUE}[STEP]${NC} $1" +} + +# 检查 Docker 是否可用 +check_docker() { + log_step "检查 Docker 服务状态..." + if ! command -v docker &> /dev/null; then + log_error "Docker 未安装,请先安装 Docker" + exit 1 + fi + + if ! docker info &> /dev/null; then + log_error "Docker 服务未运行,请启动 Docker 服务" + exit 1 + fi + log_info "Docker 服务状态正常" +} + +# 准备数据目录和配置文件 +prepare_directories() { + log_step "准备数据目录和配置文件..." + + # 创建 /data 目录(如果不存在) + if [ ! -d "/data" ]; then + log_info "创建 /data 目录" + sudo mkdir -p /data + sudo chmod 755 /data + fi + + # 切换到工作目录 + cd /data + + # 创建 cloudflared 相关目录 + mkdir -p cloudflared/{config,logs,cert} + chmod -R 755 cloudflared + + # 创建配置文件 + cat > /data/cloudflared/config/config.yml << EOF +# Cloudflare Tunnel 配置文件 +tunnel: $(echo $CF_TUNNEL_TOKEN | cut -d'.' -f2 | base64 -d 2>/dev/null | grep '"t"' | cut -d'"' -f4 || echo "tunnel-id") +credentials-file: /etc/cloudflared/credentials.json +logfile: /var/log/cloudflared/cloudflared.log +loglevel: info + +# 服务配置(示例,请根据实际需求调整) +ingress: + - hostname: example.your-domain.com + service: http://localhost:80 + originRequest: + connectTimeout: 30s + noTLSVerify: false + - service: http_status:404 +EOF + + # 创建凭证文件 + cat > /data/cloudflared/config/credentials.json << EOF +{"AccountTag":"$(echo $CF_TUNNEL_TOKEN | cut -d'.' -f2 | base64 -d 2>/dev/null | grep '"a"' | cut -d'"' -f4 || echo "account-tag")","TunnelSecret":"$(echo $CF_TUNNEL_TOKEN | cut -d'.' -f2 | base64 -d 2>/dev/null | grep '"s"' | cut -d'"' -f4 || echo "tunnel-secret")","TunnelID":"$(echo $CF_TUNNEL_TOKEN | cut -d'.' -f2 | base64 -d 2>/dev/null | grep '"t"' | cut -d'"' -f4 || echo "tunnel-id")","TunnelName":"docker-tunnel"} +EOF + + log_info "数据目录和配置文件准备完成" +} + +# 验证 Cloudflare Token 格式 +validate_token() { + log_step "验证 Cloudflare Tunnel Token..." + + if [ -z "$CF_TUNNEL_TOKEN" ]; then + log_error "Cloudflare Tunnel Token 不能为空" + exit 1 + fi + + # 简单的 token 格式验证 + if [[ ! "$CF_TUNNEL_TOKEN" =~ ^eyJ ]]; then + log_warning "Token 格式可能不正确,但将继续部署" + else + log_info "Token 格式验证通过" + fi +} + +# 部署 cloudflared 容器 +deploy_cloudflared() { + log_step "开始部署 cloudflared 容器..." + + local container_name="cloudflared-tunnel" + + # 检查容器是否已存在 + if docker ps -a --format "{{.Names}}" | grep -q "^${container_name}$"; then + log_info "发现已存在的 ${container_name} 容器,正在清理..." + docker stop ${container_name} >/dev/null 2>&1 || true + docker rm ${container_name} >/dev/null 2>&1 || true + fi + + # 运行 cloudflared 容器 + log_info "启动 cloudflared 隧道服务..." + docker run -d \ + --name ${container_name} \ + --restart=unless-stopped \ + --network host \ + -v /data/cloudflared/config:/etc/cloudflared \ + -v /data/cloudflared/logs:/var/log/cloudflared \ + -v /data/cloudflared/cert:/home/nonroot/.cloudflared \ + -e TUNNEL_TOKEN="${CF_TUNNEL_TOKEN}" \ + cloudflare/cloudflared:latest \ + tunnel --config /etc/cloudflared/config.yml run + + log_info "cloudflared 容器部署完成" +} + +# 验证容器状态 +verify_deployment() { + log_step "验证容器运行状态..." + + local container_name="cloudflared-tunnel" + local max_retries=10 + local retry_interval=5 + + for i in $(seq 1 $max_retries); do + if docker ps --format "{{.Names}}" | grep -q "^${container_name}$"; then + local status=$(docker inspect -f '{{.State.Status}}' ${container_name} 2>/dev/null || echo "unknown") + + if [ "$status" = "running" ]; then + log_info "✅ cloudflared 容器正在正常运行" + + # 显示容器信息 + echo "" + log_info "容器名称: ${container_name}" + log_info "运行状态: ${status}" + log_info "数据目录: /data/cloudflared/" + log_info "配置目录: /data/cloudflared/config" + log_info "日志目录: /data/cloudflared/logs" + log_info "证书目录: /data/cloudflared/cert" + echo "" + + # 显示最近日志 + log_info "容器启动日志:" + docker logs ${container_name} --tail 10 + + return 0 + else + log_warning "容器状态: ${status},等待中... (尝试 $i/$max_retries)" + fi + else + log_warning "容器未运行,等待中... (尝试 $i/$max_retries)" + fi + sleep $retry_interval + done + + log_error "❌ 容器启动失败或超时" + docker logs ${container_name} --tail 50 + exit 1 +} + +# 显示使用说明 +show_usage() { + echo "" + log_info "🔧 使用说明:" + log_info "查看日志: docker logs cloudflared-tunnel -f" + log_info "重启服务: docker restart cloudflared-tunnel" + log_info "停止服务: docker stop cloudflared-tunnel" + log_info "查看状态: docker ps -f name=cloudflared-tunnel" + echo "" + log_info "📁 配置文件路径: /data/cloudflared/config/config.yml" + log_info "请根据实际需求修改配置文件中的域名和服务设置" + echo "" +} + +# 主执行函数 +main() { + echo "" + log_info "🚀 开始部署 Cloudflare Tunnel Docker 容器..." + log_info "==========================================" + + validate_token + check_docker + prepare_directories + deploy_cloudflared + verify_deployment + + log_info "==========================================" + log_info "✅ Cloudflare Tunnel 部署完成!" + log_info "隧道已使用提供的 Token 进行认证" + + show_usage +} + +# 异常处理 +trap 'log_error "脚本执行被中断"; exit 1' INT TERM + +# 执行主函数 +main "$@"