Headscale使用gRPC API
背景
最近在开发一个 Headscale
控制管理平台用来管理用户创建、设备管理等等。但是当我试用了 Headscale
官网推荐的几个 UI
程序后,发现它们离我预期的功能还相差很多。我试用的几个 Headscale UI
程序,都使用 REST API
与 Headscale
进行通信,但是我遇到一个问题,在高版本 Headscale(0.25.1及以上)
中,REST API
不能创建带 Namespace
或 displayName
的用户。
所以我就通过搜索引擎查找关于 Headscale
REST API
创建 带租户的用户名,发现了以下两个链接:
- https://github.com/juanfont/headscale/issues/2166
- https://github.com/juanfont/headscale/commit/028d9aab73206eadbccd600d63910e057de7feb8
知道, Headscale
提供 gRPC API
提供 用户 displayName
创建。不过互联网上关于 Headscale gRPC API
的资料少之又少,跟别提 demo
程序了。
一番检索之后,我发现只能自己来完成这项工作了,并且在程序开发完成后,将 Headscale
一部分管理控制功能开源出来。
开发
知道使用 gRPC API
可以创建带 displayName
的用户后,后面的开发就简单多了,是的,全部交给 AI
来完成。
不过 AI
的知识库没有那么多新内容,在处理 gRPC
返回格式时一直出现错误。此时我们需要把 Headscale
的 Github
相关链接告诉它,并且提供 gRPC
返回的数据格式,AI
就顺利的完成了整个代码编写。 后续我自己进行相关测试即可。
开源
由于关于 Headscale
gRPC API
功能的说明文档以及示例代码很少,所以我就准备将这部分开源出来。
开源的程序有 两套,一套是基于 headscale-admin
添加的 gRPC
功能,这是一个纯 NodeJS
项目;另一套是 Java
程序,纯后端,没有前端配套界面。
从零到一:利用AI工具增强Headscale管理面板并探索gRPC实战价值
一、Headscale生态现状与痛点
作为Tailscale控制平面的开源实现,Headscale凭借其轻量级架构和灵活的ACL策略管理能力,正逐渐成为自建零信任网络的首选方案。然而其原生部署仅提供命令行工具和RESTful API接口,对于运维团队而言存在明显的学习曲线。当前社区提供的Web管理界面普遍存在以下问题:
- 功能碎片化:多数UI仅实现基础节点管理,ACL策略编辑等高级功能缺失
- 版本滞后:无法适配v0.25+版本的新特性,如改进的路由管理接口
- 交互体验差:缺乏实时状态更新、批量操作等现代UI必备功能
二、基于headscale-admin的功能增强实践
我们选择GoodiesHQ/headscale-admin作为基础项目,通过Augment Code等AI编程工具实现了三大核心功能增强:
1. gRPC调试支持模块开发
关键改造点:
- 通过protoc生成TypeScript gRPC stubs
- 在前端添加gRPC调试控制台
- 实现双向流式日志捕获功能
2. API兼容性修复
针对v0.25+版本接口变更,我们重构了核心API调用层:
1 | - // 旧版preauthkey获取方式 |
3. 用户管理增强
新增displayName字段的持久化存储:
三、gRPC实践的教学价值
该项目填补了社区在Headscale gRPC应用领域的空白:
- 提供完整的proto文件解析示例
- 展示TLS双向认证的实现细节
- 包含流式API的浏览器端实现方案
- 可视化调试界面降低学习门槛
通过Chrome开发者工具的Network面板,可以直观观察到gRPC-web请求的交互过程:
1 | // 示例gRPC调用日志 |
四、AI编程的实战挑战与应对
在增强开发过程中,我们发现AI工具存在以下局限性:
- 版本感知滞后:Augment Code默认基于v0.24文档生成代码,需要主动告知版本信息以及相关链接
应对策略:
- 使用搜索引擎查找相关信息,将信息链接提供给 AI
- 数据格式问题,需要给AI获取到的明确格式,防止AI乱猜影响效率
该项目已在GitHub开源,欢迎贡献代码或提交Issue讨论。通过持续改进Headscale管理体验,我们相信零信任网络的落地成本将大幅降低,让安全连接惠及更多开发者。
Docker容器中运行docker命令
问题
在使用 docker 部署程序的时候,经常需要用到 docker 命令,但是容器内部默认是无法使用 docker 命令的。
解决方案
方法一:
示例:
1 | docker run --privileged \ |
使用 --privileged
,挂载 docker.sock
以及 /usr/bin/docker
此方法安全性较差。
方法二:
A、使用 docker in docker
镜像,不过仍需要挂载 -v /var/run/docker.sock:/var/run/docker.sock
命令: docker run -itd -v /var/run/docker.sock:/var/run/docker.sock --name=docker-cmd --privileged docker
B、使用 dind
标签的docker in docker
镜像,采用--privileged
方式,此时操作将在 容器内部进行,不会涉及docker
宿主机,不需要挂载 docker.sock
;该镜像有完整的docker
命令。
注意点: 使用dind
作为基础镜像打包程序时可能出现无法运行docker
命令问题,进入容器后可以先运行: dockerd &
,之后就可正常使用;
C、使用 dind
标签的docker in docker
镜像,采用Sysbox Runtime
(需要另行安装),不需要privileged
权限,更安全,但资源配置有要求。
https://github.com/nestybox/sysbox#installing-sysbox
命令示例: docker run --runtime=sysbox-runc --name sysbox-dind -d docker:dind
参考:https://devopscube.com/run-docker-in-docker/
此方法安全性较好,隔离性比较高。
headscale及derp server部署
部署 headscale 及 使用内嵌 derp server
推荐使用 docker compose
进行部署,方便、简单。本文使用的是 v0.26.1
版本。
headscale
支持使用IP以及域名进行连接,推荐使用 域名 + https
的方式,使用 ip
部署的情况下,tailscale
客户端在重新登入的时候会自动转到 https
方式,导致登入失败。
1 | version: '3.5' |
其中 ./container-config
目录放置 config
文件。config
配置文件配置如下:
1 | --- |
上面的配置,部署 headscale
的同时,也开启了 headscale
内嵌的 derp
服务。 derp.server.enable
设置成 true
,ipv4
设置成你服务器的IP。server_url: https://xxx.ownding.xyz:9999
填写服务器的域名及端口,端口可自行确定。
比如我使用的是 9999
端口,那么需要在服务器防火墙以及云服务商的安全组里放行 9999
端口,同时需要放行 3478
tcp/udp端口。这两个端口放行后,部署完毕就可以正常使用 headscale 服务了。headscale 服务端部署后,客户端使用 tailscale
的客户端,可从 tailscale
官网下载对应的版本。
derp server 配置
使用 docker
部署 derp server
,同时修改 headscale
的配置文件。
docker
镜像:ghcr.io/yangchuansheng/derper:latest
修改的内容如下:
1 | derp: |
derp.server.enable
设置成 false
,同时在 paths
引入 derp
的配置。如果有两台 derp server,可以引入两台,如果只有一台,那么就引入一个配置即可。
config.yaml
中 derp.yaml
示例:
1 | # /etc/headscale/derp.yaml |
config.yaml
中 derp2.yaml
示例:
1 | # /etc/headscale/derp.yaml |
将 derp.yaml
和 derp2.yaml
放置在服务器 ./container-config
目录下(docker-compose.yaml中的挂载目录)。
derp server
服务器开放 3478/udp
,12345/tcp
端口。
重启 headscale
服务即可。
使用 IP 部署 Headscale
使用 IP
部署跟使用 域名
部署方式一致,就是修改下配置文件。
注意:使用 IP
部署,可能导致内置的 derp server
无法使用,可以先使用 tailscale
官方的中继节点。
1 | # 将 server_url 替换成 IP + 端口 |
使用 nginx
代理 headscale
服务
1 | user root; |
使用git submodule实现代码权限管控方案
使用git submodule实现代码权限管控方案
1、问题及目的
“程序A” 是一个 多模块 的Spring Boot
项目,为了防止代码泄露,需要加强对代码的管控。
2、解决方案
针对代码可能存在的泄漏风险,现提出两种解决方案:
- 将现有 “程序A” 后端的代码按模块分拆成一个个项目,相关人员只能拥有其权限内的项目(模块),不能接触到其它项目(模块)。该方案成本低,操作简单,虽然降低了整体代码泄漏的风险,但是模块代码泄漏的风险依旧存在。开发人员现有电脑配置不变,但是电脑需要进行域控管理。
- 在IDC配置开发服务器,为每个开发人员配置
16G内存、4核CPU、80G硬盘
的Ubuntu
虚拟机,同时更换开发人员现有的办公电脑,降低电脑配置节省电脑租赁费用。所有开发人员的开发工作均通过浏览器访问各自的开发虚拟机的开发工具进行开发,开发人员无法直接接触代码文件。该方案大大降低了代码泄漏的风险,但是实施成本高。为了防止办公电脑私自安装盗版软件,可对办公电脑进行域控管理。
2.1、模块拆分方案
“程序A” 后端模块拆分在保证开发人员权限管控的前提下,考虑开发人员操作习惯及开发效率。
经综合考虑,在不破坏 “程序A” 后端代码结构的前提下,使用Git submodule
功能实现开发人员权限管控。
前端代码暂时不考虑进行权限管控,凡是前端开发均拥有整个前端代码的修改权限。
图1 “程序A”后端拆分示例图
拆分方法:
- 将”程序A”后端除
imes_common
,imes_common_model
,imes_eureka
三个模块外,其余模块按整个模块一个项目移到同imes-parent同级的目录。移除多余模块的imes-parent
项目变成imes-application
项目。在Gitlab
中新建imes-application
项目,将本地imes-application
所有文件上传到Gitlab
中。注意:不要删减任何文件。 - 在Gitlab中新建
imes-dev
项目,将整个移动到外部目录的imes_dev
文件上传到imes-dev
项目中。注意:不要删减修改任何文件。 - 按照
imes_dev
步骤,对其它模块进行相同的操作。 imes-application
模块所有开发人员均有权限访问;其它模块按管理要求分配相应的开发人员。
总结:整个”程序A”后端拆分不涉及对文件的删除修改,拆分过程方便快速。
开发人员开发方法说明:
情形:开发人员A拥有imes-application
和imes-system
两个项目的权限,但是没有其它模块的权限
- 开发人员A使用新账号将
imes-application
克隆到自己的开发电脑上。 - 开发人员A进入到
imes-application
文件夹,然后使用git submodule add http://url/user/imes-system.git imes_system
命令将imes-system
代码拉取到本地imes-application
目录中。等待编译器索引完成即可正常开发调试,使用方法同现有后端开发方式。
2.1.1、模块拆分举例
本案例已”程序B”拆分为例,为了方便起见,整个”程序B”只保留四个模块:imes_common
,imes_common_model
,imes_eureka
,imes_system
作举例说明。
1、将”程序B”按照前文所述的方法拆分成imes-console-common
,imes-console-eureka
,imes-console-system
三个项目。每个项目文件均不要进行修改删除操作。imes-console-common
包含imes_common
和imes_common_model
两个模块。
图2 “程序B”拆分示例
2、将imes-console-common
项目添加system
和eureka
两个submodule
后并提交后,将在imes-console-common
项目中看到两个子模块信息。
图3 添加子模块后项目信息
3、开发人员A拥有imes-console-common
及imes-console-eureka
两个项目的权限,虽然他可以看到项目中imes_system
目录的显示,但是当他点imes-console-common
项目的imes_system
时,会提示找不到相关页面从而达到代码管控的目的。
图4 项目内代码管控
2.1.2、Jenkins打包
由于”程序A”项目整体结构并没有变化,Jekins打包方式基本不变,不过有两处变化。
1、Jenkinsfile
中新增一行:sh 'git submodule update --init --recursive'
图5 Jenkinsfile修改
2、Jenkins中项目打包配置修改,如下图:
图6 Jenkins中打包配置新增子模块选项
图7 Jenkins打包测试
2.2、方案1说明(模块拆分+本地化开发)
1、开发人员保持现有开发环境不变。
2、管理人员将”程序A”后端代码按照模块进行分离,每个模块即是一个项目。
3、管理人员对项目(模块)进行授权,每个项目只授权给对应的开发人员,其他开发人员无法查看、下载。
4、管理人员取消开发人员原有”程序A”后端的代码权限。
5、开发人员拉取各自项目的代码到本地笔记上进行开发。
6、开发人员电脑需要进行域控管理。
图8 本地化开发
2.3、方案2说明(模块拆分+服务器化开发)
1、运维人员根据需要购买”程序A”开发服务器。
2、运维人员配置开发服务器(系统选用Ubuntu20.04 LTS桌面版,管理员权限禁用SSH),安装好开发工具IDEA Projector
,Code-Server
。
3、管理人员将”程序A”后端代码按照模块进行分离,每个模块即是一个项目。
4、管理人员对项目(模块)进行授权,每个项目只授权给对应的开发人员,其他开发人员无法查看、下载。
5、管理人员取消开发人员原有”程序A”后端的代码权限。
6、运维人员收回开发人员32G内存的机器,改成租赁16G内存的机器。
7、运维人员给每个开发人员分配开发虚拟机,以及浏览器访问链接。
8、运维人员搭建开发k8s,部署”程序A”。
9、开发人员在办公电脑的浏览器上进行开发工作。如果人员居家办公需要使用VPN连入公司内网进行开发工作。
图9 网页版IDEA
图10 浏览器上进行后端开发工作
图11 浏览器上进行前端开发工作
图12 开发服务器安装的系统(注:开发人员无法访问服务器,只能通过浏览器访问开发工具)
图13 服务器化开发示意图
图14 开发服务器网络说明
2.4、方案3说明(模块拆分+服务器化开发)
同方案2(需要启用SSH),将Projector
替换成 JetBrains Gateway
,实现相同的效果。使用Gateway
时需要在本地电脑安装该软件,使用SSH连接到远程电脑。平常开发同本地使用IDEA一样。
前端开发采用VS Code Remote
的开发方式。开发人员同样使用本地VS Code
编辑器SSH
方式连接到远程电脑。
下载地址:
JetBrains Gateway - Remote Development for JetBrains IDEs
本方案同方案2一样不会将远程代码复制到开发人员电脑上。
要求:
- 需要运维人员事先在服务器中配置好
Git
,Java
,Node.js
等环境,并且将特定开发人员的Git
密码事先登入。 - 需要运维人员在开发人员电脑上实现配置好Gateway及SSH登入密码。
- 服务器账户密码、
Git
账户密码不告知开发人员。 - 代码服务器需每天备份。
- 开发人员一人一台远程服务器。运维人员在给开发人员配置好系统环境、开发环境后需要对服务器进行快照备份,在出现意外时可快速恢复开发环境。
- 运维人员需制作基础服务器镜像或快照,可以在开发人员入职后快速的部署开发环境。减少人员搭建开发环境的时间或者更换电脑重新搭建开发环境的时间。
图15 Gateway远程开发
图16 同本地开发体验基本一致
图17 可同时打开多个IDEA窗口
2.5、方案4说明(服务器化开发)
同方案3,但是不进行模块拆分(即”程序A”后端仍旧是一个工程,不按模块进行工程拆分了)。这样的好处是节省了模块拆分的麻烦、消除了模块拆分后开发人员隐形增加的调试程序的时间成本,同时开发体验同现有开发人员习惯完全一致。
图18 不拆分模块,远程流畅调试”程序A”后端
3、方案对比
方案1(模块拆分+本地化开发) | 方案2/3 | 方案4 | |
安全性 | 中 | 高 | 高 |
方案实施便利性 | 高 | 低 | 中 |
花费 | 低 | 高(按30 ~ 40开发人员统计,预估服务器花销6 ~ 10万,同时电脑租赁可节省2万/年) | 高(按30 ~ 40开发人员统计,预估服务器花销6 ~ 10万,同时电脑租赁可节省2万/年) |
开发便利性 | 高 | 中 | 高 |
开发工具费用 | 无(但是IDEA、数据库工具很多是破解版) | 无(IDEA社区版、Code-Server、Ubuntu系统均免费) | 可能需要付费IDEA工具 |
办公/开发电脑域控 | 需要 | 不需要 | 不需要 |
居家办公 | 支持 | 支持 | 支持 |
出差 | 支持 | 支持(需网络) | 支持(需网络) |
开发工具插件支持 | 支持 | 支持 | 支持 |
开发环境统一性 | 低 | 高 | 高 |
风险点 | 开发工具使用了很多破解软件 | 大量人员在服务器上开发可能导致服务器卡顿,影响开发效率;需要高速的内网网络。网络延迟等会影响开发效率。代码等均在服务器,如果服务器突然故障等会导致开发人员无法工作。 | 大量人员在服务器上开发可能导致服务器卡顿,影响开发效率;需要高速的内网网络。网络延迟等会影响开发效率。代码等均在服务器,如果服务器突然故障等会导致开发人员无法工作。 |
4、方案选择
方案1相对其它方案安全性较低。方案2使用Projector
操作流畅度不行,相比方案3、4操作不够流畅,体验感不佳,多IDEA
窗口操作繁琐。综合方案1、2、3、4,建议选用方案3
。
各云厂商轻量云服务器的另类用法
各云厂商轻量云服务器的另类用法
一、场景创新:当轻量云遇上全球IP需求
在云计算普及的今天,2核2G内存的Windows Server轻量云服务器正成为技术爱好者的新宠。这类产品独特的按天计费模式 (实际是按月收费,但是使用完毕退订服务器是按天收费,如阿里云1.5元/天、腾讯云1.3元/天),配合全球数据中心布局,意外地成为了获取多地域IP地址的高效工具。通过在云端构建临时Windows工作站,用户可快速获取美国、新加坡、欧洲等地的IP资源,满足跨境电商、SEO优化、网络研究等特殊需求。
二、厂商产品横向评测
云厂商 | 基础配置 | 包月价格 | 数据中心分布 | Windows支持 | 特色功能 |
---|---|---|---|---|---|
阿里云 | 2核2G/ | 54元 | 全球20+区 | ✔️ | 自动快照备份 |
腾讯云 | 2核2G/ | 44元 | 全球15+区 | ✔️ | 一键重装系统 |
注:价格为大致折算人民币月费,实际以厂商官网为准
三、实战操作全流程
1. 账号准备阶段
- 注册时绑定支付宝/微信(国内厂商)
- 设置支付密码防误操作
2. 浏览器环境优化
- 安装Chrome便携版(免更新困扰)
- 设置临时书签同步(Edge浏览器同步功能)
4. IP资源利用策略
- 跨境电商:多账号防关联(亚马逊店铺矩阵)
- 内容采集:突破地域限制抓取海外数据
- 广告测试:验证不同地区广告投放效果
- 网络研究:进行合法的渗透测试(需授权)
- 资料查找:查找工作/学习中所需的文献资料
四、使用
直接使用 windows 自带的远程桌面连接到 服务器即可。
由于远程端口在公网开放,请将服务器密码设置的复杂点。对网络安全方便不熟悉的用户,在使用完毕后可以直接关闭服务器或退订。
五、问题处理
腾讯、阿里轻量云海外服务器购买后,经常出现”服务器创建“失败的情况,直接”工单“联系售后。
Cassandra备份及恢复
1、使用 Cassandra:3.0.9 镜像
2、cd /opt/cassandra/bin/
- 3、全量备份,执行:
nodetool snapshot
程序会自动在每张表下生成备份时间戳的文件夹,里面有备份文件。
备份单个keyspace执行:nodetool snapshot yourkeyspace
- 4、启用增量备份
启用:nodetool enablebackup
查看状态:nodetool statusbackup
- 5、删除快照
命令:nodetool clearsnapshot
- 6、备份恢复
将备份目录下的文件复制到 表目录下:cp /var/lib/cassandra/data/thingsboard/ts_kv_latest_cf-49f924507df811eeaf8a3b94212b0656/snapshots/1699939125001/* /var/lib/cassandra/data/thingsboard/ts_kv_latest_cf-49f924507df811eeaf8a3b94212b0656/
再执行恢复命令:nodetool refresh -- yourkeyspace yourtable
headscale使用nginx代理
当我们部署了 headscale 以及 headscale UI等程序,需要对 headscale 及UI 进行代理。本文使用nginx进行代理。
headscale ui相关的开源程序,推荐使用 headscale-admin,界面美观,功能较丰富,使用较简单,只要启动容器即可。
1 | user root; |
以上配置中需要注意 add_header 'Access-Control-Allow-Origin' '*' always;
, 将 *
替换为你自己服务器的域名。
如果你想部署 headscale-admin
,以及不希望api暴露,可以在 nginx
中删除 /admin
的配置,以及 /
中 cros
配置即可。
自动提交Bing索引IndexNow脚本
目的
为了加快Bing搜索引擎对网站的索引,可通过 IndexNow 主动提交网址链接。
- 1、在 https://www.bing.com/indexnow/getstarted 获得 API key
- 2、将
key
的txt
文件放到网站根目录下,方便访问 - 3、将网站的所有链接生成一个
txt
文档,使用脚本提交 - 4、到
Bing Webmaster Tools
网站查看提交情况
脚本
以下是用于批量提交链接到 Bing IndexNow 的 shell 脚本:
1 | #!/bin/bash |
baidu_urls.txt
文件中 URL
格式:
1 | http://www.ownding.com/2025/06/12/%E5%9C%A8%E6%9C%89%E5%85%AC%E7%BD%91IP%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%E5%A6%82%E4%BD%95%E5%AE%89%E5%85%A8%E5%9C%B0%E8%BF%9B%E8%A1%8C%E8%BF%9C%E7%A8%8B%E6%A1%8C%E9%9D%A2%E8%BF%9E%E6%8E%A5/ |
使用说明:
- 将脚本保存为
submit_to_bing.sh
- 修改配置参数:
HOST
: 你的网站域名KEY
: 你的 Bing IndexNow API 密钥KEY_LOCATION
: 验证密钥文件的 URLURL_FILE
: 你的 URL 文件路径
- 赋予执行权限:
1
chmod +x submit_to_bing.sh
- 运行脚本:
1
./submit_to_bing.sh