部署Tailscale的中转服务器的过程

了解Tailscale很久,但是基本很少用,常用的场景下基本没有办法直联,官方中继延迟太高了。后来突然有一天了解到,tailscale可以自行部署中转服务器derp,于是就打算部署一个来解决延迟太高的问题. 过程中基本是按照官方文档来进行操作,文档本身已经写的很好了,只是正好不是我的母语,tailscale我又没有特别的深入使用,同时又有不少专属名词,导致有点东西理解,因此大概折腾了一周左右,反反复复的折腾,才算是真正的搞好和理解。 下面是具体操作步骤: 打开云服务器的防火墙设置,当前教程下需要开启10443(tcp协议),3478(UDP协议), icmp协议的防火墙策略。以上防火墙策略是必须的。 在云服务上安装go应用程序,具体参考go官网 执行一下命令,安装并编译最新的derper程序。(这个步骤可能在你的tailscale无法连接到这个中继服务器的时候重复执行,以保持与tailscale各个客户端的兼容性) go install tailscale.com/cmd/derper@latest 安装certbot程序(其实就是Let`s Encryept)来获取https证书, 具体安装步骤见certbot官网 执行一下命令获取https证书,一切按照默认继续下去即可。具体意思就是单独获取你域名的nginx证书,并保存到指定路径。 sudo certbot certonly --manual --preferred-challenges dns -d <你的域名> 上一步获取到https证书之后,会打印出来证书保存的路径。其中fullchain.pem和privkey.pem分别代表你证书的crt和key,在很多地方使用https证书的时候会指定具体的crt和key文件路径。我们通过ln -s命令分别创建privkey.pem的副本,并重命名为.crt和.key的后缀文件。 sudo ln -s <cerbot证书保存路径>/fullchain.pem <cerbot证书保存路径>/<你的域名>.crt sudo ln -s <cerbot证书保存路径>/privkey.pem <cerbot证书保存路径>/<你的域名>.key 启动derper程序开启中继服务 sudo <go的bin目录>/derper -a :10443 --http-port=-1 --hostname=<你的域名> -certmode manual -certdir <cerbot证书保存路径> --verify-clients -a :10443 指定https服务的监听端口为10443,且监听所有网口 http-port=-1 不开启http服务 hostname 指定你的derp中继服务的对外域名 certmode manual代表手动管理https证书 certdir 指定手动管理的https证书的具体路径 –verify-clients 代表需要校验tailscale的客户端,这个可以去掉(第8步无需执行)。但是就意味着你的服务谁都可以使用 在云服务器上安装tailscale客户端,并登录授权,具体参考官网。...

2024-12-15 14:41 · 1 min · 江波·林沂

返利插件后台服务器崩溃与恢复的一点感想

去年5,6月份的时候,临时兴起写了一个京东返利插件。放到chrome和edge的插件市场,没啥流量,不过每天也有点人用,高峰期大概可以给我攻陷个差不多200的收入。 前两天研究rspress,想把我的返利插件的文档页面重构一下,更美观一点。当时手残的就在返利插件的后台服务器上使用vscode尝试。心想一个静态网站生成器吗,没啥大问题,我之前在上面跑rust开发也没出现什么大事。谁知道就坏在这个上面。 在修改一个文件重新编译生成的时候,系统竟然没反应了,我以为可能是网络卡顿了,谁知道差不多10分钟也没恢复,登录到腾讯云控制台,发现cpu和内存同时爆到到99%以上。没办法,只能重启。谁知道重启之后,ssh竟然链接不上,通过控制台的vnc连接工具连接到机器上,发现启动的时候死在了cloudflared服务上。不知道我当初怎么安装的,竟然自启动cloudflared,然后还没其他成功,导致整个系统完全进入不来kernel. 由此而来第一个教训就是不能在生产机器上进行无关生产操作的其他任务,说不定什么时候这个任务就会导致生产服务器崩溃。 这就坑了,本来就是个重启解决的问题,现在要解决系统问题了。拜托了google和chatgpt搞了半天也没解决怎么进入系统问题。还好腾讯还有个救援模式,通过vnc进入之后还可以挂载原来机器的数据,否则数据丢失就坑了。虽然用户不是很多,涉及的钱也不多,但是也不能白白浪费了。 vnc连接机器虽然可以挂载原来机器数据,但是不能直接下载。好在我有台nas,通过cloudflare可以webdav暴露到公网。简单的通过curl将重要数据传递到nas上之后我重装了服务器,然后很快的就恢复了服务。 从系统崩溃到最终恢复过去了大概12小时,仅操作尝试就花了大概4个小时。主要还是不太了解linux的启动过程,导致在排查启动问题时就消耗了很长时间,最终还没有解决。其次,就是数据备份不存在,导致后续通过救援模式进入系统之后要重新备份数据,因为救援模式不太好安装新的工具,只能通过curl命令上传webdav简单的备份数据,如果遇到大量的数据,那么就花费更多的时间。最终的纯系统重装及恢复服务,其实到并没有花费太多的时间。 由此也可见数据备份的重要性。也就是我这个服务用户量小,影响面低,如果换成其他重要服务,这么长的恢复时间就会造成很大的损失。如果有完善的数据备份,那么完全可以开一台新机器很快的恢复服务。 在最终备份数据的时候还发现另外一个问题。因为这个插件的后台我开发的有段时间且后续也没有怎么维护,导致数据备份的时候差点忘记一块重要的数据。这个时候就体现出项目readme.md的重要性了。核心内容及操作一定要记录其中,否则过了一段时间之后,即使你是当初的开发者,有意外情况发生时也会忘记重要步骤,从而导致事故。

2024-02-20 16:11 · 1 min · 江波·林沂

使用Cloudflare Pages及Meilsearch搭建一个Linux Git提交日志查询网站

本文章主要受网站https://linux-commits-search.typesense.org/启发,并根据其源码进行修改。 文章重点讲述项目部署在Cloudflare Pages过程,其他细节只做简略的叙述。目前可通过域名https://linux-commit-search.jiangbo.space进行访问。 网站本身是一个前后端分离的网站, 后台有meilsearch提供http服务。meilisearch是一个开源的搜索服务,可以理解为一个简单的ES服务,便于搭建和使用。 前端使用Parcel进行打包,js方面使用的还是比较老的jquery。使用instant-meilisearch和instantsearch进行搜索控件的构建,整体来说结构比较简单。如果进行常规的部署,还是相当简单的。之前我是在自己的轻量级服务器上进行的部署,只是用了nginx就轻松的部署完成。为什么要使用cloudflare呢?主要是考虑到服务的稳定性以及访问的广度,毕竟cloudflare的机器遍布全球,而我的服务器只有一台。同时,使用cloudflare pages可以轻松的做到部署自动化。 Cloudflare pages部署前端项目还是非常简单的,选择好git项目以及构建步骤之后,前端代码就轻松的部署到了Cloudflare的全球网络上了,配置好相应的域名之后,测试访问,前端页面展示的非常完美。 接下来问题就来了, 在自有服务器上可以简单实现的代理功能,在Cloudflare Pages上就比较麻烦了。我先后尝试了以下三种方式: 使用Cloudflare Pages提供的Functions功能进行代理功能的实现。 这里遇到的问题是,Functions提供的fetch功能,只能使用env.ASSET进行调用。开始的时候,我没有自己,认为fetch并不是什么大问题,直接将前端页面域名中的域名替换成meilisearch服务的后端页面进行调用。functions部署之后,进行简单调用,发现返回的竟然还是前端页面。这是什么鬼啊,我又详细的检查了一遍functions文档, 返现evn.ASSET只能访问CloudFlare Pages域名下的静态文件。这就太坑了,只能放弃这种处理方式了。 使用Cloudflare Pages提供的Rediects功能进行代理功能的实现。 这里面耽误的时间到不是很多,看文档的时候,我就看到了proxy功能是不支持的,说是未来将会支持。但是总归不信邪,试一下吧。打包阶段就通知我这种配置方式是不支持的。哎! 使用Cloudflare Pages提供的Functions与Workers绑定的功能实现。 不得不说,Cloudflare Pages中的Functions的文档写的有点稀碎,同时很多措辞感觉有点模棱两可的感觉,也不知道是不是我英语不过关的原因。Functions与Workers绑定的文档我看了好多次,也尝试了多次,才最终完成绑定的工作。 在配置界面进行Functions和Workers(Service)进行绑定的时候,页面显示的Variable Name。在文档界面,又显示的是select the environment, 同时文档界面Service bindings下面就是Environment variables, 搞的我一直以为设置界面设置的参数是环境变量而已,是用来区分环境的。真正调用workers直接使用文档里面的例子就可以了。 Functions与Service绑定配置页面的配置: Functions与Service绑定配置页面 Functions与Service绑定的文档页面: Functions与Service绑定的文档页面 文档中的调用服务的例子如下: export async function onRequestGet(context) { return context.env.SERVICE.fetch(context.request); } 我一直认为其中的SERVICE是固定写法,文档中是这样写的:“Here is an example of how to use service bindings in your Function, our service binding is named “SERVICE”"。同样的写法我怎么调用,都直接告诉我系统异常。困扰了我好久,后来我突然想到,是不是我在设置页面设置的变量值才是env.后面应该跟随的参数,而不是固定的SERVICE。我进行了尝试,果然一下就成功了。后续再看了文档,才有点理解。...

2023-01-30 13:46 · 1 min · 江波·林沂

使用Automata和Rust索引1,600,000,000Keys(5)

FST构造 构造确定性非循环有限状态转换器的工作方式与构造确定性非循环有限状态接受器的工作方式大致相同。关键区别在于转换时输出的放置和共享。 Constructing deterministic acyclic finite state transducers works in much the same way as constructing deterministic acyclic finite state acceptors. The key difference is the placement and sharing of outputs on transitions. 为了降低心理负担,我们将重用上一节中的示例,其中包含key mon,tues和thurs。由于使用FST表示map,我们将一周中的数字日期2,3,5分别与每个key相关联。 To keep the mental burden low, we will reuse the example in the previous section with keys mon, tues and thurs. Since FSTs represent maps, we will associate the numeric day of the week with each key: 2, 3 and 5, respectively....

2022-09-30 11:04 · 8 min · 江波·林沂

使用Automata和Rust索引1,600,000,000Keys(4)

在前两节中,我一直小心避免谈论用于表示有序集或map的有限状态机的构造。也就是说,构造比简单的遍历要复杂一些。 In the previous two sections, I have been careful to avoid talking about the construction of finite state machines that are used to represent ordered sets or maps. Namely, construction is a bit more complex than simple traversal. 为了简单起见,我们对 set 或 map 中的元素进行了限制:它们必须按字典顺序添加。这是一个繁重的限制,但我们稍后会看到如何减轻它。 To keep things simple, we place a restriction on the elements in our set or map: they must be added in lexicographic order. This is an onerous restriction, but we will see later how to mitigate it....

2022-09-29 16:43 · 6 min · 江波·林沂