[转]Nostr代理转发中继部署过程
软件选型
github上有很多Nostr代理转发的现成项目可以直接拿来用,而且自己写也很费时间,我自己对这块程序也不太熟,所以选择直接拿来主义。
我前几天尝试的第一个项目是 https://github.com/bndw/nostr-relay-proxy.git ,这个项目是golang写的,编译部署也不麻烦,就是有内存泄漏,我买的便宜低配的vps主机(cloudcone的kvm主机,可以支付宝付款比较方便),跑一会儿就OOM了,进程会反复重启,1G内存都不够,没法用。
这两天尝试的是另外一个项目 https://github.com/Yonle/bostr.git ,这个项目比上面那个可以配置的选项更多,是node.js写的,编译部署也比较简单(唯一要注意的是依赖的node版本>=16),最主要的是他不占用啥资源,我新买的1CPU/512M内存的VPS目前看起来也跑的很欢快(也是cloudcone的,主要是前两天买的那个退款之后,那个促销的配置卖完了,尴尬。。。这次买的是包月的,先用几天试试看好不好用吧,好用再说)。
部署过程
- 买vps
这个不多说,随便整一个国外的vps就行,有公网地址那种。我选的操作系统是ubuntu 20.04,其实我想选22.04,但是512M内存不够用起不来。。。内存够用的话还是用新版本比较好。
- 申请域名
我是申请的免费的域名,试了3个才找到一个能用的(有些是国内dns解析不到,有些是不能申请ssl证书),我是用这个网站申请的免费域名 https://freedns.afraid.org/ 。
其实我自己有付费域名,但是是国内买的,容易泄漏个人信息,还是免费的凑合用吧。我注册的二级域名是 nostr-bostr-relay-proxy.ignorelist.com ( 已更新为:tnruygu.cn ) ,这个测试了下可以用certbot申请免费ssl证书,国内外dns解析也正常。
最后就是配置dns A记录,把 nostr-bostr-relay-proxy.ignorelist.com 解析到你的vps 公网地址,等十几分钟才会生效,可以ping一下域名看看解析地址,或者用dig、nslookup之类的工具查询dns记录。
- 部署代理软件
项目的README文档写的比较清楚了,主要是依赖的nmp和node.js运行环境要装好。
- 安装
npm:apt install npm
(最好先执行apt-get update
) - 安装node运行环境:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
, 然后nvm install v18.19.0
,我选择的是18版本,比16高就行。 - 下载bostr项目代码:
git clone https://github.com/Yonle/bostr.git
- 编译bostr项目:
cd bostr
;npm i
- 修改bostr配置:
cp config.js.example config.js
;vi config.js
; 修改内容如下:
// Bostr config
module.exports = {
// Server listener [Required]
address: "0.0.0.0",
port: "8080",
// 独立 HTTPS 服务器。通常情况下,bostr 接受不安全的连接。
// 指定私钥/证书的绝对路径将使 bostr 只接受安全连接。
//
// 提示:如果在反向代理(reverse proxy)后面运行 bostr,则不需要此项。
https: {
privKey: "",
certificate: "",
ticketKey: ""
},
// 集群。
// 0 将使 bostr 运行可用并行性/CPU 内核的集群。
clusters: 0,
// 使用继电器连接保镖的日志?
log_about_relays: false,
// 对 websocket 使用 deflate 压缩。
perMessageDeflate: true,
// 重新连接继电器前的时间(毫秒)。
reconnect_time: 5000,
// 在上游中继器发出限制后的限制到期时间,单位为毫秒。
// 设置为 0 时,将禁用鼠限处理。
upstream_ratelimit_expiration: 10000,
// 客户端可打开的最大订阅。
// 设置为 -1 将禁用最大订阅限制。
max_client_subs: -1,
// 等待每个连接的继电器发送 EOSE。
// 可以提高接收事件的准确性。
//
// 取决于您配置的中继、
// 由于弹跳器发送 EOSE 的速度较慢,这可能会导致客户端出现加载问题。
// 可以尝试通过更改 <eose_timeout> 或 <max_eose_score> 值来解决这个问题。
wait_eose: true,
// 当订阅达到 <filter.limit> 时,暂停订阅,不再接收其他事件。
// 可以节省客户端带宽。如果需要获取更多事件,请禁用此功能。
// 这也被称为保存模式。
//
// 您可能还需要调整 <max_eose_score>。
pause_on_limit: true,
// 从中继站接收到 EOSE 后向客户端发送 EOSE 的最大值。
// 通常,等待 3 个中继器的 EOSE 就足够了。将其设为 0 等于等待每一个已建立的中继站。
// 注意:请根据您配置的中继正确调整最大值。
// 如果只设置了 3 个继电器,请将 <max_eose_score> 设置为 0。
// 提示:越大 = EOSE 发送越准确,越小 = EOSE 发送越早。
max_eose_score: 0,
// 客户端事件广播限制(以毫秒为单位)。
// 客户端只能在 <broadcast_ratelimit> 之后向该弹跳器广播新事件。
// 将其设为 0 将禁用此功能。
broadcast_ratelimit: 0,
// 传入 websocket 连接速率限制(单位:毫秒)。
// 设置为 0 将禁用此功能。
incomming_ratelimit: 0,
// 可以使用此保镖的用户公钥白名单。
// 留空此项将允许所有人使用此保镖。
// NOTE: - Require NIP-42 compatible nostr client.
// 如果客户端不支持 NIP-42,可以使用 <allowed_event_authors> 代替。
authorized_keys: [
// "pubkey-in-hex",
// "npub ....",
// ....
],
// 经批准的事件发布者白名单。
// 将此项留空将允许所有人使用此弹跳器发布事件。
approved_publishers: [
// "pubkey-in-hex",
// "npub ....",
// ....
],
// 被阻止的事件发布者黑名单。
blocked_publishers: [
// "pubkey-in-hex",
// "npub ....",
// ....
],
// 阻止来自以下主机的 websocket 连接。
blocked_hosts: [
// "127.0.0.1",
// "127.0.0.2",
// "::1",
// "::2",
// ....
],
// 用于从某些继电器访问受 NIP-42 保护的事件。
// 这可能是您的密钥。将其留空可完全禁用 NIP-42 功能。
//
// 您甚至可以将此函数用作公共保镖。
// 不会有安全风险,因为它会利用 NIP-42 识别客户端公钥。
//
// 注意: - 需要与 NIP-42 兼容的 nostr 客户端
private_keys: {
// "pubkey-in-hex": "privatekey-in-hex",
// "pubkey-in-hex": "nsec ...."
},
// 提示:如果要将密钥/私人密钥转换为十六进制、
// 您可以运行以下命令:
// $ node hexconverter.js npub....
// $ node hexconverter.js nsec....
// 或
// $ bostr hexconverter npub....
// $ bostr hexconverter nsec....
// 服务器信息。
// 仅在 nostr 客户端请求服务器信息时使用。
server_meta: {
"contact": "https://cfblog.lepidus.me",
"pubkey": "09fbf8f3be5ae763435881698d6e845de83be9b5e1cca99988918d17fa3d60f0",
"description": "Make yourself stronger.",
"name": "Lepidus",
"software": "git+https://github.com/Yonle/bostr",
// 某些 nostr 客户端可能会读取以下内容,以进行兼容性检查。
// 你可以修改 supported_nips 来匹配你的中继支持。
"supported_nips": [1,2,9,11,12,15,16,20,22,33,40,42,50],
// "icon_url": ""
},
// favicon 文件的路径。
favicon: "img/favicon.ico",
// 使用 x-forwarded-for 将客户端 IP 地址转发给上游中继器
forward_ip_address_to_upstream: true,
// Nostr 继电器跳转 [必填]
relays: [
"wss://relayable.org",
"wss://ca.relayable.org",
"wss://la.relayable.org",
"wss://relay.damus.io",
"wss://purplerelay.com",
"wss://tw.purplerelay.com",
"wss://jp.purplerelay.com",
"wss://za.purplerelay.com",
"wss://ae.purplerelay.com",
"wss://relay-jp.shino3.net",
"wss://nostrich.friendship.tw",
"wss://relay.nostr.band",
"wss://relay.snort.social",
"wss://offchain.pub",
"wss://relay.primal.net",
"wss://nostr-pub.wellorder.net",
"wss://nostr.wine",
"wss://nos.lol",
"wss://relay.mostr.pub",
"wss://nostr.wine",
"wss://nostr21.com",
"wss://relay.freefrom.space",
"wss://relay.nostrcheck.me",
"wss://yabu.me",
"wss://relay.nostrr.de",
"wss://damus.relay.center",
"wss://eden.relay.center",
"wss://adre.su",
"wss://public.relaying.io",
"wss://relay.noswhere.com",
"wss://nostr.globals.fans",
"wss://nostr.zkid.social",
"wss://relay.leligobit.link",
"wss://nostr-relay.derekross.me",
"wss://nostr.coinfund.app",
"wss://nostr.data.haus",
"wss://nostr-02.yakihonne.com",
"wss://relay.plebstr.com",
"wss://nostr.blockpower.capital",
"wss://nostr.swiss-enigma.ch",
"wss://relay.sendstr.com",
// "wss://example3.com",
// ...and so on
]
}
ps.
- /root/bostr/favicon.ico 这个网站图标是在网上随便做的: https://favicon.io/favicon-generator/
- authorized_keys 和 approved_publishers 和 server_meta 这三个配置写的hex格式的pubkey,不是npub开头的,需要用 node hexconverter.js npub…. 转换格式
运行bostr软件: node index.js 测试下能不能跑起来,跑起来之后,可以新开一个vps ssh窗口,curl 127.0.0.1:8080 看下输出是否正常:
Hello. This nostr bouncer (bostr) is bouncing the following relays: - wss://relay.damus.io - wss://purplerelay.com ......省略更多内容
看到上面的输出就表示运行正常了,这个时候其实代理relay已经可以用了,只不过是明文http协议(实际是websocket协议,ws://开头的),没有加密,谁都能看到你往这个代理中继上发送了什么内容(可能nostr协议本身也有消息加密,但是我不确定),因此还要配置ssl加密也就是wss。
Docker部署
项目提供docker的部署方式,编辑好上面的config.js文件。执行以下命令
git clone https://github.com/Yonle/bostr
cd bostr
docker build -t bostr:local .
docker run -d --name bostr -p 8080:8080 -v ./config.js:/usr/src/app/config.js bostr:local
Docker部署,打包到hub.docker.com
克隆作者的仓库到自己的仓库,或者直接用作者的仓库也可以
docker login登录docker hub账号
#将github打包镜像
docker build -t zhoupingxiao/bostr:latest https://github.com/zhoupingxiao/bostr.git
docker push zhoupingxiao/bostr:latest
docker run -d --name bostr -p 8080:8080 -v ./config.js:/usr/src/app/config.js zhoupingxiao/bostr
部署nginx反向代理
这个很简单,apt install nginx 安装上nginx,然后写一个转发配置,把指定域名请求转发到 bostr 程序的指定端口上,例如:
server {
server_name nostr-bostr-relay-proxy.ignorelist.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
}
}
把这个配置保存到 /etc/nginx/sites-available/relay-proxy , 然后 cd /etc/nginx/sites-enabled/ ; ln -s ../sites-available/relay-proxy . ; 启用转发配置,最后reload nginx进程 systemctl reload nginx.service 。
部署Caddy配置反向代理(Caddy可以自动部署证书,只需要以下代码就行)
你的域名 {
handle {
reverse_proxy http://bostr:8080 { #反代对应的websocket网站
header_up X-Forwarded-Host {host}
header_up X-Real-IP {remote_host}
header_up Host {upstream_hostport} #header_up Host {host}
}
}
}
配置ssl加密
默认websocket协议不加密,也就是ws://不是wss://,多一个s表示ssl加密。
配置ssl加密可以使用certbot,非常简单易用,最主要的是免费。。。
安装certbot:先安装snapd apt install snapd ; 再用snap安装certbot(这样才能安装最新版本certbot,老版本不好用) snap install certbot —classic
用certbot申请免费ssl证书:certbot —nginx -d nostr-bostr-relay-proxy.ignorelist.com ,输入邮箱,之后就会自动申请这个域名的ssl证书了,并且会自动添加ssl相关配置到 /etc/nginx/sites-available/relay-proxy ,包括监听443端口等。另外注意邮箱要是你自己真正的,会发确认邮件,需要点击确认。网上也有很多nginx配置ssl的教程,可以搜索看看。还要在 /etc/nginx/sites-available/relay-proxy 配置文件中加一行 proxy_set_header X-Forwarded-Proto “https”; ,位置就在 proxy_set_header 那几行都可以。
最后reload nginx进程 systemctl reload nginx.service ,就可以通过https或者wss访问中继代理服务器了。 curl https://nostr-bostr-relay-proxy.ignorelist.com/ :
Hello. This nostr bouncer (bostr) is bouncing the following relays:
- wss://relay.damus.io
- wss://purplerelay.com
......省略输出
看到上述内容就表示ssl加密配置ok了。
然后你就可以添加 wss://nostr-bostr-relay-proxy.ignorelist.com/ ( 请使用更新后的域名:wss://tnruygu.cn/ ) 到你的nostr客户端的中继列表里面使用了。