写这篇文章之时恰逢中秋佳节之际,祝各位朋友中秋快乐!
我的博客自从2022年就已经建好,但是基本没有写很多东西在上面,搭建之初只是为了方便而使用了gitalk 来作为评论系统。但这个开源项目的评论是基于github的issue来实现,虽然数据也是存储在自己的仓库并且免费。但是由于github在国内的网络环境下时好时坏,大部分情况下无法正常加载。而从个人博客评论功能的需求出发我主要归结为以下两点:
加载迅速,不因为没有科学上网工具而无法使用 数据安全,也即数据自己可以操控在自己的存储系统里面最好 支持匿名评论,因为我不想让别人看个blog还要进行繁琐的登录 这个时候刚好看到了一个叫做Artalk 的开源项目,使用go语言编写号称轻量便捷并且它还在正常更新,拓展性高,可以本地化部署,正好满足我的需求。
部署 环境:Ubuntu 22.04
正确部署姿势 artalk/artalk-go
#### **域名解析** 到你域名解析供应商处添加Artalk的域名解析记录如 ```comment.example.cn```指向你的服务器地址 #### **nginx配置和安装ssl证书** 在nginx.conf里面添加如下server块: ```nginx server { listen 443 ssl; server_name comment.nighterdream.cn; ssl_certificate /etc/letsencrypt/live/comment.nighterdream.cn/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/comment.nighterdream.cn/privkey.pem; # managed by Certbot ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers 'HIGH:!aNULL:!MD5'; ssl_prefer_server_ciphers on; location / { proxy_pass http://localhost:8081; # Artalk 运行的地址和端口 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_set_header X-Forwarded-Proto $scheme; } }
其中证书由Cerbot生成, 至于为什么要反向代理请看下面曲折经历
安装 Certbot 和 Nginx 插件 首先,需要安装 Certbot 和它的 Nginx 插件。如果你使用的是 Ubuntu 或其他基于 Debian 的系统,使用以下命令: sudo apt updatesudo apt install certbot python3-certbot-nginx
运行 Certbot 自动化命令 运行以下命令,Certbot 将自动为你的域名生成证书,并更新 Nginx 配置以启用 SSL: 根据提示进行输入信息
测试 Nginx 配置 证书生成并配置完成后,重新加载 Nginx 以应用更改: sudo nginx -tsudo systemctl reload nginx
Hexo配置 以butterfly主题配置为例,打来主题配置文件_config.butterfly.yml找到评论配置部分修改以下内容
artalk: server: https://comment.example.cn # 你设置的Artalk服务端域名 site: example # 在Artalk配置中设置 visitor: false option:
记得把评论功能打开,并且切换成Artalk
# Comments System # -------------------------------------- comments: # Up to two comments system, the first will be shown as default # Choose: Disqus/Disqusjs/Livere/Gitalk/Valine/Waline/Utterances/Facebook Comments/Twikoo/Giscus/Remark42/Artalk use: # Valine,Disqus - Artalk text: true # Display the comment name next to the button # lazyload: The comment system will be load when comment element enters the browser's viewport. # If you set it to true, the comment count will be invalid lazyload: true count: false # Display comment count in post's top_img card_post_count: false # Display comment count in Home Page
Artalk配置 这个使用就可以通过https://comment.example.cn
访问Artalk的后台评论管理系统了
设置Artalk后台管理员账号 虽然能够访问了却需要账号和密码,在Artalk容器部署端执行: docker exec -it artalk artalk admin
Artalk文档
设置可信域 添加以下内容,实际就是设置请求头内容防止跨域问题产生http://comment.example.cn 防止国产浏览器无法加载,请参看国产浏览器的坑 https://comment.example.cn
配置站点 这里的站点要和docker run 里面的yoursite对应,同时也要和你的hexo 主题配置文件里的site对应
根据自己配置灵活进行,建议开启验证码,防止匿名评论轰炸消耗服务器资源,参考官方配置文档
总结 完成以上操作之后就可以hexo clean; hexo g; hexo d
来推送博文了 在配置Artalk过程中自己也是踩了很多的坑,局域网内证书注册,还有就是国产浏览器的坑 ,很多问题都是一开始没有发现,实际操作中才能认识到,特别是国产浏览器无法重定向,估计又是C2C (copy to China)的锅,希望官方能够改一改。很多问题也都是在官方文档和错误日志中找到答案和解决办法,看日志的能力也是得到了一次提升。
曲折经历 局域网的坑 我的博客部署在一台阿里云的服务器上,它的容量很小,所以的构想是将Artalk部署在本地的物理主机上,然后通过frp穿透出去。可是这个想法是好的在实际操作过程中却发现了问题。 我的博客为了安全采用了https协议传输数据,但是Artalk默认使用http在我部署好了之后我发现无法正常加载博客评论,打开浏览器终端发现是由于https和http不匹配造成的。之后我仔细查阅了Artalk的官方文档里面写道: 可以开启ssl加密传输 加密传输 ssl
ssl: enabled: true cert_path: '' key_path: '' 你可以配置该项,让 HTTP 升级为 HTTPS,通过 SSL 协议加密传输数据。 cert_path:SSL 证书公钥文件路径。 key_path:SSL 证书私钥文件路径。 你也可以直接反向代理 Artalk 本地服务器,然后在例如 Nginx 启用 HTTPS。
这时候就存在问题了我的Artalk是通过docker部署的而在docker 容器内安装证书显然不是一个很好的选择,我就剩下了另一个选择就是通过nginx反向代理Artalk服务器,但是这个时候就又存在了一个问题,**本地局域网内的物理机如何申请证书?**因为我是采用frp实现内网穿透的,所以申请证书基本可以宣告破产。 之后我想了一个办法,那就是把我服务器上使用certbot申请的证书给复制到我的局域网内的物理主机上,可结果确是不行,浏览器提示证书和域名不匹配,无法加载远程服务器资源,所以之后我将Artalk又使用docker部署到了我的阿里云服务器,并使用cerbot申请了证书,使用nginx将artalk本来的http反向代理成https,这似乎所有问题都得到了解决了我的博客的评论可以正常加载了,直到我发现了一个国产浏览器的坑。
国产浏览器的坑 nginx设置了将http请求重定向到https时,国产浏览器无法生效 我在博客评论系统部署好并测试好没有问题之后就可高枕无忧,专注到内容的书写上。可当我姐来我家,我让她用她手机访问我博客时却发现了问题,她使用手机的夸克浏览器没法加载评论,这个时候我没太放在心上,可能是一个概率问题。但后面我发了一篇博文到微信上,用微信自带的qq浏览器也提示评论加载错误我这个时候才意识到不是偶尔的问题,而确实存在bug,我本人一共使用三款浏览器分别是:firefox, chrome, edge测试都没有发现任何问题,这个时候我下载了一个QQ浏览器,这个时候提示跨域问题了。 这就让我很不解了我在Artalk(Artalk设置了另外的域名,博客的评论是从artalk的网址加载评论数据,所有需要跨站请求)里面设置可信域:https://www.nighterdraem.cn, https://nighterdream.cn
。 因为只有国产浏览器才无法加载评论所以我询问了chatgpt
为什么我的Artalk评论系统在国产浏览器中会遇到跨域问题,在edge和chrome中却能正常使用 以下是我的nginx配置 server { listen 443 ssl; server_name comment.nighterdream.cn; ssl_certificate /etc/letsencrypt/live/comment.nighterdream.cn/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/comment.nighterdream.cn/privkey.pem; # managed by Certbot ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers 'HIGH:!aNULL:!MD5'; ssl_prefer_server_ciphers on; location / { proxy_pass http://localhost:8081; # Artalk 运行的地址和端口 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_set_header X-Forwarded-Proto $scheme; } }
跨域问题(CORS,Cross-Origin Resource Sharing)在国产浏览器中可能会导致 Artalk 评论系统无法正常使用,而在 Edge 和 Chrome 中可以正常使用,原因可能与不同浏览器处理 CORS 的方式有关。以下是可能的原因和解决方案: ### 可能原因 1. **国产浏览器的安全策略差异**:国产浏览器(如 QQ 浏览器、360 浏览器等)有时会对跨域请求进行更加严格的处理,而国际浏览器如 Chrome 和 Edge 可能会对开发中的应用更宽容,特别是对于本地服务器或 HTTP 请求。 2. **CORS 头缺失**:你的 Nginx 配置中没有明确设置 CORS 相关的响应头,这可能导致国产浏览器拒绝跨域请求。 3. **代理转发的 Headers 问题**:Artalk 的跨域配置可能没有正确传递给浏览器。国产浏览器可能严格要求返回正确的跨域响应头。 ### 解决方案 1. **在 Nginx 中添加 CORS 头**:你可以在 Nginx 的配置中添加允许跨域的响应头,确保浏览器能够正确处理跨域请求。 你可以在 `location` 块中添加如下 CORS 配置 location / { proxy_pass http://localhost:8081; 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_set_header X-Forwarded-Proto $scheme; # 添加跨域响应头 add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; add_header Access-Control-Allow-Headers 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; add_header Access-Control-Expose-Headers 'Content-Length,Content-Range'; } 这将允许所有源对你的服务器进行请求。如果你想限制特定的源,可以将 `Access-Control-Allow-Origin` 的值替换为特定的域名。 2. **确保 Artalk 支持 CORS**:检查 Artalk 的配置文件或后端设置,确保它支持跨域请求。Artalk 可能需要配置允许的 `Origin`,确保它支持通过反向代理的跨域请求。 3. **OPTIONS 请求的处理**:有时候浏览器会发送预检请求(OPTIONS 请求)以确认服务器是否允许跨域访问。你可以在 Nginx 中为 `OPTIONS` 请求添加一个单独的处理: if ($request_method = OPTIONS) { add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; add_header Access-Control-Allow-Headers 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; return 204; } 4. **检查浏览器控制台的错误信息**:如果问题依然存在,可以在国产浏览器中打开开发者工具,查看具体的错误信息,确认是哪个请求遇到了 CORS 问题。 通过添加这些 CORS 设置,应该可以让国产浏览器与 Edge 和 Chrome 一样正常访问你的 Artalk 评论系统。
我按照他的建议进行了更改,但之后我发现连edge和chrome都无法加载了,查看请求头:
HTTP/1.1 200 OK Server: nginx/1.18.0 (Ubuntu) Date: Mon, 16 Sep 2024 09:44:16 GMT Content-Type: application/json Content-Length: 731 Connection: keep-alive X-Request-Id: 001151ae-c7f7-4002-945b-748a1af32112 Vary: Origin Access-Control-Allow-Origin: https://www.nighterdream.cn Access-Control-Allow-Origin: https://www.nighterdream.cn Access-Control-Allow-Methods: GET, POST, OPTIONS Access-Control-Allow-Headers: DNT,User-Agent,X-Requested-With, If-Modified-Since,Cache-Control,Content-Type,Authorization,Range Access-Control-Expose-Headers: Content-Length,Content-Range
问题出在了Access-Control-Allow-Origin的值出现了两次 https://www.nighterdream.cn
所以连edge和chrome也无法打开,原因是我在artalk的可信域里面进行了配置(应用层),然后在nginx里面又进行了配置(代理层),所以Access-Control-Allow-Origin 也就重复了导致edge无法打开,但神奇的是国产浏览器又能打开评论了,之后我将nginx配置中恢复了原样取消手动设置请求头。
这个时候我打开了QQ浏览器的开发者控制台发现如下报错:
Access to fetch at 'https://comment.nighterdream.cn/api/v2/conf' from origin 'http://nighterdream.cn' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
这就很奇怪了为什么是http://nighterdream.cn
而不是我设置的可信域https://nighterdream.cn
然后我就在QQ浏览浏览器的导航栏输入:http://nighterdream.cn
来访问我的网站,正常情况下我设置了nginx的http重定向https,浏览器应该会自动将导航栏上的地址改成https://nighterdram.cn
,但是QQ浏览器没有。之后我又测试了edge,chrome浏览器发现他们都能重定向到https所以能够加载评论。 而QQ浏览器,夸克浏览器移动端,微信浏览器为代表的国产浏览器没有重定向而是继续使用http来访问,这也就造成了请求头里的Access-Control-Allow-Origin字段值和Artalk后端的https://nighterdream.cn
不匹配,所以才无法加载评论,而我将Artalk的可信域里面加入http:nighterdream.cn
后问题也就迎刃而解。
参考资料 Artalk文档
Artalk自托管评论系统搭建与配置
跨源资源共享(CORS)
什么是反向代理?|代理服务器介绍