部署 Tailscale Derper 自建中继服务器 使用宝塔Let’s Encrypt证书

部署教程与其他博主相同

部署 Tailscale Derper 自建中继服务器 – 猫猫博客

(8 封私信 / 2 条消息) 大内网战略(6):自建 Tailscale DERP 中继服务器 保姆级教程 – 知乎

区别:证书使用宝塔签发的证书

1.这里使用derp的域名建立网站,并且开启ssl,主要用这个网站生成的证书

图片[1]-部署 Tailscale Derper 自建中继服务器 使用宝塔Let’s Encrypt证书-起风啦

2.进入宝塔证书路径

图片[2]-部署 Tailscale Derper 自建中继服务器 使用宝塔Let’s Encrypt证书-起风啦

fullchain.pem 里面包含域名证书.crt ,拆分出来即可。

privkey.pem 直接重命名为key文件。先手动生成文件,并且运行derp

图片[3]-部署 Tailscale Derper 自建中继服务器 使用宝塔Let’s Encrypt证书-起风啦

这里可以看到运行成功了。

图片[4]-部署 Tailscale Derper 自建中继服务器 使用宝塔Let’s Encrypt证书-起风啦

3.宝塔面板三个月自动更新证书,可以在后台运行一个分离证书的sh,提取crt 和重命名key

以下是最终优化版脚本,支持自动覆盖目标文件明确输出目录信息,并为新生成的证书文件设置644权限(私钥保持600):

#!/bin/bash
# split_cert.sh - 拆分 PEM 证书并按目录名重命名(自动覆盖 + 权限规范)

set -e

# ========== 参数处理 ==========
TARGET_DIR="${1:-/www/server/panel/vhost/ssl/ts.qifeng.la}"

if [[ ! -d "$TARGET_DIR" ]]; then
    echo "❌ 错误: 目标目录不存在"
    echo "   路径: $TARGET_DIR"
    echo "用法: $0 [目标目录路径]"
    exit 1
fi

# 获取绝对路径和目录名
ABS_PATH=$(cd "$TARGET_DIR" && pwd 2>/dev/null || echo "$TARGET_DIR")
DIR_NAME=$(basename "$ABS_PATH")

# ========== 文件路径定义 ==========
FULLCHAIN="${ABS_PATH}/fullchain.pem"
PRIVKEY="${ABS_PATH}/privkey.pem"
DOMAIN_CERT="${ABS_PATH}/${DIR_NAME}.crt"
CHAIN_CERT="${ABS_PATH}/root_bundle.crt"
PRIVKEY_RENAMED="${ABS_PATH}/${DIR_NAME}.key"

# ========== 显示处理信息 ==========
echo "=========================================="
echo "📁 证书拆分处理(自动覆盖模式)"
echo "=========================================="
echo "✅ 完整目录路径 : $ABS_PATH"
echo "✅ 目录名称     : $DIR_NAME"
echo "------------------------------------------"

# ========== 检查输入文件 ==========
if [[ ! -f "$FULLCHAIN" ]]; then
    echo "❌ 错误: 未找到 fullchain.pem"
    echo "   路径: $FULLCHAIN"
    exit 1
fi

if [[ ! -f "$PRIVKEY" ]]; then
    echo "❌ 错误: 未找到 privkey.pem"
    echo "   路径: $PRIVKEY"
    exit 1
fi

echo "✓ 检测到输入文件:"
echo "   • fullchain.pem"
echo "   • privkey.pem"
echo ""

# ========== 覆盖提示 ==========
OVERWRITE_FILES=()
[[ -f "$DOMAIN_CERT" ]] && OVERWRITE_FILES+=("$DOMAIN_CERT")
[[ -f "$CHAIN_CERT" ]] && OVERWRITE_FILES+=("$CHAIN_CERT")
[[ -f "$PRIVKEY_RENAMED" ]] && OVERWRITE_FILES+=("$PRIVKEY_RENAMED")

if [[ ${#OVERWRITE_FILES[@]} -gt 0 ]]; then
    echo "⚠️  以下文件将被覆盖:"
    for f in "${OVERWRITE_FILES[@]}"; do
        echo "   • $(basename "$f")"
    done
    echo ""
fi

# ========== 拆分证书(直接覆盖) ==========
echo "📦 正在提取域名证书(第一个证书)..."
awk '
BEGIN {count=0; output=0}
/-----BEGIN CERTIFICATE-----/ {
    count++
    if (count == 1) {
        output=1
        print
    } else {
        output=0
    }
    next
}
/-----END CERTIFICATE-----/ {
    if (output) {
        print
        exit
    }
    next
}
{if (output) print}
' "$FULLCHAIN" > "$DOMAIN_CERT"
chmod 644 "$DOMAIN_CERT"  # 设置证书权限为 644

echo "🔗 正在提取证书链(中间证书 + 根证书)..."
awk '
BEGIN {count=0; output=0}
/-----BEGIN CERTIFICATE-----/ {
    count++
    if (count > 1) output=1
    else output=0
    if (output) print
    next
}
/-----END CERTIFICATE-----/ {
    if (output) print
    next
}
{if (output) print}
' "$FULLCHAIN" > "$CHAIN_CERT"
chmod 644 "$CHAIN_CERT"  # 设置证书链权限为 644

# ========== 重命名私钥(直接覆盖) ==========
echo "🔑 正在重命名私钥文件(覆盖模式)..."
cp -f "$PRIVKEY" "$PRIVKEY_RENAMED"
chmod 600 "$PRIVKEY_RENAMED"  # 私钥保持 600 权限

# ========== 验证结果 ==========
if [[ ! -s "$DOMAIN_CERT" ]]; then
    echo "❌ 错误: 域名证书生成失败或为空"
    exit 1
fi

CHAIN_COUNT=$(grep -c '-----BEGIN CERTIFICATE-----' "$CHAIN_CERT" 2>/dev/null || echo 0)
if [[ $CHAIN_COUNT -eq 0 ]]; then
    echo "ℹ️  提示: 证书链为空(fullchain.pem 可能仅包含单个证书)"
fi

if [[ ! -s "$PRIVKEY_RENAMED" ]]; then
    echo "❌ 错误: 私钥文件生成失败"
    exit 1
fi

# ========== 最终输出 ==========
echo ""
echo "=========================================="
echo "✅ 处理完成(所有目标文件已覆盖)"
echo "=========================================="
echo "📁 完整目录路径 : $ABS_PATH"
echo "🏷️  目录名称     : $DIR_NAME"
echo "------------------------------------------"
echo "生成的文件及权限:"
echo "   • ${DIR_NAME}.crt (权限 644)"
echo "     路径: $DOMAIN_CERT"
echo ""
echo "   • root_bundle.crt (权限 644)"
echo "     路径: $CHAIN_CERT"
echo "     包含证书数量: $CHAIN_COUNT"
echo ""
echo "   • ${DIR_NAME}.key (权限 600)"
echo "     路径: $PRIVKEY_RENAMED"
echo "=========================================="

# 显示证书主题(可选)
if command -v openssl &>/dev/null; then
    SUBJECT=$(openssl x509 -in "$DOMAIN_CERT" -noout -subject 2>/dev/null | sed 's/subject=//g' | sed 's/^[[:space:]]*//g' || echo "N/A")
    echo "📄 域名证书主题: $SUBJECT"
fi

🔑 权限说明

文件类型文件名权限说明
域名证书${DIR_NAME}.crt644公开可读,Web 服务常用权限
证书链root_bundle.crt644公开可读,中间/根证书
私钥${DIR_NAME}.key600仅所有者可读写,保障安全

🚀 使用示例

# 保存脚本(例如 ~/scripts/split_cert.sh)
chmod +x ~/scripts/split_cert.sh

# 处理指定目录(自动覆盖 + 权限规范)
~/scripts/split_cert.sh /www/server/panel/vhost/ssl/ts.qifeng.la

💡 输出示例片段

生成的文件及权限:
   • ts.qifeng.la.crt (权限 644)
     路径: /www/server/panel/vhost/ssl/ts.qifeng.la/ts.qifeng.la.crt

   • root_bundle.crt (权限 644)
     路径: /www/server/panel/vhost/ssl/ts.qifeng.la/root_bundle.crt
     包含证书数量: 2

   • ts.qifeng.la.key (权限 600)
     路径: /www/server/panel/vhost/ssl/ts.qifeng.la/ts.qifeng.la.key

4.将此文件设置为计划任务

/www/wwwroot/split_cert.sh /www/server/panel/vhost/ssl/ts.qifeng.la

图片[5]-部署 Tailscale Derper 自建中继服务器 使用宝塔Let’s Encrypt证书-起风啦
图片[6]-部署 Tailscale Derper 自建中继服务器 使用宝塔Let’s Encrypt证书-起风啦

5.记得给宝塔网站加个备案号,防止掉备案

图片[7]-部署 Tailscale Derper 自建中继服务器 使用宝塔Let’s Encrypt证书-起风啦
© 版权声明
THE END
喜欢就支持一下吧
点赞9 分享