Files
edge-node/registrar.sh
lingyuzeng 6bf070ab66 之前的注册脚本里把中间件写成了 security-headers@file(还出现过一个带逗号的 security-headers@file,)。而在你的 routes/global.yml 里真正定义的名字是 sec-headers@file。
目的就是对齐中间件名称,避免 Traefik 在装配 router 时引用了一个不存在的中间件,导致该条 router 报告 warning / 被降级,进而被其它“更泛”的路由(比如系统自带面板 8000/5666)抢走域名流量。
2025-10-02 23:12:21 +08:00

94 lines
3.6 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/sh
set -eu
: "${SERVICE_NAME:?need SERVICE_NAME}"
: "${SERVICE_ADDR:?need SERVICE_ADDR}"
: "${SERVICE_PORT:?need SERVICE_PORT}"
: "${ROUTE_HOST:?need ROUTE_HOST}"
CONSUL="${CONSUL_HTTP_ADDR:?need CONSUL_HTTP_ADDR}"
SERVICE_PROTOCOL="${SERVICE_PROTOCOL:-http}" # http | tcp
CHECK_TYPE="${CHECK_TYPE:-tcp}" # http | tcp
CHECK_PATH="${CHECK_PATH:-/}"
CHECK_INTERVAL="${CHECK_INTERVAL:-10s}"
CHECK_TIMEOUT="${CHECK_TIMEOUT:-2s}"
DEREG_AFTER="${DEREG_AFTER:-1m}"
TRAEFIK_HTTP_ENTRYPOINT="${TRAEFIK_HTTP_ENTRYPOINT:-websecure}"
TRAEFIK_TCP_ENTRYPOINT="${TRAEFIK_TCP_ENTRYPOINT:-tcp}"
# TRAEFIK_CERT_RESOLVER="${TRAEFIK_CERT_RESOLVER:-cf}"
echo "[registrar] consul: $CONSUL, service: $SERVICE_NAME@$SERVICE_ADDR:$SERVICE_PORT"
# 等云端 Consul Server 可用
for i in $(seq 1 90); do
if wget -qO- "$CONSUL/v1/status/leader" >/dev/null 2>&1; then
break
fi
sleep 1
done
ID="${SERVICE_NAME}-${SERVICE_ADDR}-${SERVICE_PORT}"
# 组装 Traefik tags按“行”累加避免值中逗号被拆
NL='
'
TAGS="traefik.enable=true"
if [ "$SERVICE_PROTOCOL" = "http" ]; then
TAGS="$TAGS${NL}traefik.http.routers.${SERVICE_NAME}.rule=Host(\`${ROUTE_HOST}\`)"
TAGS="$TAGS${NL}traefik.http.routers.${SERVICE_NAME}.entrypoints=${TRAEFIK_HTTP_ENTRYPOINT}"
TAGS="$TAGS${NL}traefik.http.routers.${SERVICE_NAME}.tls=true"
TAGS="$TAGS${NL}traefik.http.services.${SERVICE_NAME}.loadbalancer.server.scheme=http"
TAGS="$TAGS${NL}traefik.http.services.${SERVICE_NAME}.loadbalancer.server.port=${SERVICE_PORT}"
# 抢占路由:给当前 Host 的 router 设置更高优先级
TAGS="$TAGS${NL}traefik.http.routers.${SERVICE_NAME}.priority=10000"
# 可选中间件(注意:值里有逗号也安全)
TAGS="$TAGS${NL}traefik.http.routers.${SERVICE_NAME}.middlewares=gzip-all@file,sec-headers@file"
# 如需 ACME 证书解析器可再加一行(取消注释)
# TAGS="$TAGS${NL}traefik.http.routers.${SERVICE_NAME}.tls.certresolver=${TRAEFIK_CERT_RESOLVER}"
elif [ "$SERVICE_PROTOCOL" = "tcp" ]; then
TAGS="$TAGS${NL}traefik.tcp.routers.${SERVICE_NAME}.rule=HostSNI(\`${ROUTE_HOST}\`)"
TAGS="$TAGS${NL}traefik.tcp.routers.${SERVICE_NAME}.entrypoints=${TRAEFIK_TCP_ENTRYPOINT}"
TAGS="$TAGS${NL}traefik.tcp.services.${SERVICE_NAME}.loadbalancer.server.port=${SERVICE_PORT}"
else
echo "unsupported SERVICE_PROTOCOL=$SERVICE_PROTOCOL" >&2; exit 2
fi
# 转 JSON 数组(按“行”解析)
to_json_array() {
# 逐行 -> trim -> "..." -> [ ... ]
awk 'BEGIN{RS="\n"} NF {gsub(/^[ \t]+|[ \t]+$/,""); printf "\"%s\",\n",$0}' |
sed '1s/^/[/' | sed '$s/,\s*$/]/'
}
TAGS_JSON="$(printf "%s" "$TAGS" | to_json_array)"
# 健康检查 JSON
if [ "$CHECK_TYPE" = "http" ]; then
CHECK_JSON=$(cat <<EOF
{"Name":"http","HTTP":"http://${SERVICE_ADDR}:${SERVICE_PORT}${CHECK_PATH}","Interval":"${CHECK_INTERVAL}","Timeout":"${CHECK_TIMEOUT}","DeregisterCriticalServiceAfter":"${DEREG_AFTER}"}
EOF
)
else
CHECK_JSON=$(cat <<EOF
{"Name":"tcp","TCP":"${SERVICE_ADDR}:${SERVICE_PORT}","Interval":"${CHECK_INTERVAL}","Timeout":"${CHECK_TIMEOUT}","DeregisterCriticalServiceAfter":"${DEREG_AFTER}"}
EOF
)
fi
# 写 service 定义并注册到云端 Consul
cat > /tmp/svc.json <<EOF
{"service":{"id":"${ID}","name":"${SERVICE_NAME}","address":"${SERVICE_ADDR}","port":${SERVICE_PORT},"tags":${TAGS_JSON},"checks":[${CHECK_JSON}]}}
EOF
echo "[registrar] register ${ID} -> ${CONSUL}"
consul services register -http-addr="$CONSUL" /tmp/svc.json
term() {
echo "[registrar] deregister ${ID}"
consul services deregister -http-addr="$CONSUL" /tmp/svc.json || true
exit 0
}
trap term TERM INT
tail -f /dev/null