随着Google推进90天证书步伐的加快,已有几家机构发布了调整通知,缩短有效期已经成为了板上钉钉的事。
主流的解决办法是使用证书自动化部署,但受限于部分设备不方便安装ACME以及可能出现的更新失败,还是得搭一个证书监控应用。
也借由这个契机,把一直想做但没做的网站状态监控一并解决了,摆脱掉"网站挂了全靠用户通知"的局面。
几番寻找,发现Uptime Kuma正好符合规定,不止支持监控证书和网站,还支持DNS、Ping、Radis等应用的监控,而且通知方式也多。
美中不足的是不支持接入腾讯的SMS,所以本次部署还会要自己写一个接口来做适配。
通过Docker部署Uptime。
使用Python实现一个WebHook接口,用于发送通知短信。
安装Nginx反代Uptime和WebHook接口,并绑定域名,更加美观。
不使用宝塔等面板程序。
这里选择使用Lighthouse自带的Docker镜像。
既省去安装的时间,后期也可以在控制台直接看服内得多Docker容器,十分方便。
首先,启动docker
service docker start
创建放数据的文件夹
mkdir -p /root/docker/uptime/data
执行命令拉去镜像并部署
docker run -d --restart=always -p 3001:3001 -v uptime-kuma:/root/docker/uptime/data --name uptime-kuma louislam/uptime-kuma:1
UFW放通3001端口
ufw allow 3001
轻量防火墙放通3001端口
这时候,访问:http://[IP]:3001
就能看到uptime的管理页面了
进入短信控制台,点击国内短信
->签名管理
新建一个签名
选择网站
和公众号
最容易过,需要注意的是网站需要是已备案的网站
审核通过后记下签名ID
点击正文模板管理
创建一个新的模板,同样的,审核通过后记下模板ID
这里提供一个示例
模板名称:
服务器故障通知
短信内容:
服务器故障通知
监控名称: {1}
故障状态: {2}
故障时间: {3}
故障信息: {4}
申请说明:
用于监控程序发送服务器故障提醒,在服务故障时提醒管理员进行排查。
如下为示例:
服务器故障通知
监控名称: 主站
故障状态: 0
故障时间: 2023-11-23 17:23:19
故障信息: 访问超时
注意,
\n
在短信内容中会被当成文本输出
用python写一个接口,用来给uptime做webhook告警推送
import hashlib, hmac, json, time, requests, uvicorn, re
from datetime import datetime
from fastapi import FastAPI,Request
# 短信应用ID
SmsSdkAppId = ""
# 签名文本
SignName = ""
# 模板ID
TemplateId = ""
# 手机号
PhoneNumber = ""
# API密钥
SecretId=""
SecretKey=""
app = FastAPI()
def qcloud_v3_post(SecretId,SecretKey,service,bodyDict,headersDict):
secret_id = SecretId
secret_key = SecretKey
service = service
algorithm = "TC3-HMAC-SHA256"
timestamp = int(time.time())
date = datetime.utcfromtimestamp(timestamp).strftime("%Y-%m-%d")
http_request_method = "POST"
canonical_uri = "/"
canonical_querystring = ""
headersDict = {k: v for k, v in sorted(headersDict.items(), key=lambda x: x[0])}
signed_headers = ""
canonical_headers = ""
for dict_key in headersDict:
signed_headers = signed_headers + dict_key.lower() + ";"
signed_headers = signed_headers[:-1]
for dict_value in headersDict:
canonical_headers = canonical_headers + dict_value.lower() + ":" + headersDict[dict_value].lower() + "\n"
payload = json.dumps(bodyDict)
hashed_request_payload = hashlib.sha256(payload.encode("utf-8")).hexdigest()
canonical_request = (http_request_method + "\n" +
canonical_uri + "\n" +
canonical_querystring + "\n" +
canonical_headers + "\n" +
signed_headers + "\n" +
hashed_request_payload)
credential_scope = date + "/" + service + "/" + "tc3_request"
hashed_canonical_request = hashlib.sha256(canonical_request.encode("utf-8")).hexdigest()
string_to_sign = (algorithm + "\n" +
str(timestamp) + "\n" +
credential_scope + "\n" +
hashed_canonical_request)
def sign(key, msg):
return hmac.new(key, msg.encode("utf-8"), hashlib.sha256).digest()
secret_date = sign(("TC3" + secret_key).encode("utf-8"), date)
secret_service = sign(secret_date, service)
secret_signing = sign(secret_service, "tc3_request")
signature = hmac.new(secret_signing, string_to_sign.encode("utf-8"), hashlib.sha256).hexdigest()
authorization = (algorithm + " " +
"Credential=" + secret_id + "/" + credential_scope + ", " +
"SignedHeaders=" + signed_headers + ", " +
"Signature=" + signature)
headersDict["X-TC-Timestamp"] = str(timestamp)
headersDict["Authorization"] = authorization
return headersDict
@app.post("/sendsms")
async def sendsms(request: Request):
content_type = request.headers['Content-Type']
if content_type != "application/json":
return {"code":-1,"msg":"类型不正确"}
body = await request.body()
try:
body_json = json.loads(body)
except Exception as e:
return {"code":-1,"msg":str(e)}
name = body_json["monitor"]["name"]
status = body_json["heartbeat"]["status"]
time = body_json["heartbeat"]["time"]
msg = body_json["msg"]
Service = "sms"
host = "sms.tencentcloudapi.com"
protocol = "https://"
apiurl = protocol + host
PhoneNumberSet = [PhoneNumber]
name = re.sub(r'(\d+).(\d+).\d+.\d+', '*.*.*.*', name)
msg = re.sub(r'(\d+).(\d+).\d+.\d+', '*.*.*.*', msg)
name = re.sub(r'[^\u4e00-\u9fa5a-zA-Z0-9\[\]\s]', '', name)
msg = re.sub(r'[^\u4e00-\u9fa5a-zA-Z0-9\[\]\s]', '', msg)
TemplateParamSet = [name,str(status),time,msg]
SessionContext = "uptime"
payload = {
"PhoneNumberSet": PhoneNumberSet,
"SmsSdkAppId" : SmsSdkAppId,
"SignName" : SignName,
"TemplateId" : TemplateId,
"TemplateParamSet": TemplateParamSet,
"SessionContext" : SessionContext
}
headersPending = {
'Host': host,
'Content-Type': 'application/json',
'X-TC-Action': 'SendSms',
'X-TC-Version': '2021-01-11',
'X-TC-Region': 'ap-guangzhou',
}
headersSend = qcloud_v3_post(SecretId,SecretKey,Service,payload,headersPending)
r = requests.post(apiurl,json=payload,headers=headersSend)
return {"code":200,"msg":"OK"}
if __name__ == '__main__':
uvicorn.run(app=app, host="0.0.0.0", port=8080)
轻量Docker镜像自带了Python 3.8.2,但没有安装pip,所以要先安装下
apt install python3-pip
然后安装依赖库
python3 -m pip install requests fastapi uvicorn
使用nano直接新建一个sms.py文件,把上面的程序粘贴上去
nano sms.py
试运行
python3 sms.py
看到如下结果表示依赖没有问题:
后台运行sms.py
nohup python3 sms.py &
apt install nginx
service nginx start
安装成功后,在浏览器输入IP可以看到如下网页
进入Nginx配置文件存放目录
cd /etc/nginx/conf.d
配置uptime的反向代理
新建配置文件
nano uptime.conf
输入如下配置
server
{
listen 80;
server_name [需要绑定到uptime的域名];
location / {
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
配置sms webhook的反向代理
server
{
listen 80;
server_name [需要绑定到webhook的域名];
location / {
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
service nginx restart
分别访问两个域名,可以看到已经设置成功了
uptime
webhook
因为接口使用的是POST,使用浏览器测试是GET请求,所以显示如下内容是正常的,不影响实际使用
登录以后,直接点击左上角新建监控项
这里拿腾讯云举例
在高级
处可以找到证书通知
除了网站,uptime还能监控许多不同类型的服务
找到webhook
填入刚才部署的webhook的url
注意不用点右下角的测试,右下角的测试发送的内容不完整,是无法收到信息的
保存通知设置和监控项设置
设置完成后即可看到当前网站的监控状态。
点击证书有效期
还能看到网站当前的证书信息
相比于CVM,Lighthouse不管是价格还是操作体验上都要舒服得多。
换成CVM,同样的2C2G-3M不限流量要103
换成按量计费0.8元/G,200G要160,还没算配置得38
即使使用共享流量包,按37元/50G算,200G也得148元。
而且操作还麻烦,购买页面和CVM是分开的,你得到VPC里才能找到购买和管理入口
而换成Lighthouse,流量使用状况一目了然,套餐不够用点一下升级重启就完事了
几台Lighthouse之间也不用考虑什么VPC直接默认内网互通,对于普通用户来说十分方便。