内网穿透搭建 overleaf 服务器
introduction
在前序文章《从零搭建一个又快又安全的 VNC 服务》中,我们实现了从非公网机器连接到使用了 ddns 的公网机器,并搭建了公网机器的 VNC 服务;在中序文章《Learn 内网穿透 the hard way》中,我们使用了 ddns 的公网机器作为跳板机,连接到了另一台非公网机器,从而实现了居家办公的梦想;接下来这篇文章的目的是在中序文章的基础上,在另一台非公网机器搭建 web 服务(也就是 overleaf),本地访问,从而达到省掉一年 $89 订阅费用的目的。
prerequisites
- 一台可以连上公网的跳板机(我这里仍然是中序文章中支持 RVV1.0 的开发板)
- 较高性能的,用来安装 overleaf 社区版的 linux 服务器
- 确保主机、服务器、跳板机可以互相 ssh 连接
- 确保跳板机有对应的域名
steps
先保证服务器的 overleaf 正常运行
1 | git clone https://github.com/overleaf/toolkit.git ./overleaf-toolkit |
修改一下 ./config/overleaf.rc
:
1 | OVERLEAF_LISTEN_IP=0.0.0.0 # 监听所有的IP,默认只能本地访问 |
然后启动:
1 | sudo bin/up -d |
如果 docker-compose 代理不好使,可以设置换源:
1 | sudo tee /etc/docker/daemon.json <<-'EOF' |
curl 一下 http://localhost:9999 能否正常显示页面,例如:
1 | > unset http_proxy && curl http://localhost:9999/ |
如果没有问题证明服务端本身工作正常,进入下一步。
服务器先内网穿透到跳板机
可以参考这个文档。
下载同一个版本的 frpc
与
frps
(笔者使用0.61.0
),客户端(也就是
overleaf 服务器)修改 frpc.toml
:
1 | serverAddr = <frps server domain name or IP> |
然后到 frps 服务端(也就是跳板机)修改 frps.toml
:
1 | bindPort = 7000 |
之后启动客户端的 frpc
:
1 | ./frpc -c frpc.toml |
与服务端的 frps
:
1 | ./frps -c frps.toml |
假设你服务器的域名是foo.example.com
,并且跳板机映射 http
端口的值为8080
,在跳板机 curl 一下:
1 | > unset http_proxy && curl http://foo.example.com:8080 |
如果成功,代表 frp 工作正常。如果你只需在 HTTP
环境访问,并且域名已备案,使用 http://foo.example.com:8080
来访问已经没有问题,否则进行下一步。
建议将 frps 与 frpc 加入 systemctl 以方便开机启动,例如:
1 | ### /etc/systemd/system/frps.service |
let's encrypt 获取域名证书(如果没有)
let's encrypt 使用 certbot 进行域名所有权验证,证书有效期为 90 天。但默认参数允许自动续期,在配置好 nginx 的情况只需要一行命令,中间选择第一个选项即可。
1 | > sudo certbot certonly --preferred-challenges dns -d <frps server domain name> |
或者你认为这是一个套娃问题,你可以使用手动获取,再配好 nginx 后转为自动续期。手动获取需要在你的 DNS provider 编辑两个 TXT 字段,这里就不赘述过程了。
1 | sudo certbot certonly --manual --preferred-challenges dns -d <frps server domain name> |
验证成功后,certbot 将证书存放于
/etc/letsencrypt/live/<frps server domain name>/fullchain.pem
,私钥存放于
/etc/letsencrypt/live/<frps server domain name>/privkey.pem
。
http 转 https
除了文档中所述“结合 https2http 插件来实现将本地的 HTTP 服务以 HTTPS 协议暴露出去”之外,也可以使用 nginx 来达到这一点。
安装 nginx 后,编辑
/etc/nginx/sites-available/default
:
1 | server { |
其中<https port>
正常情况(即已备案条件下)为
443,<frps server domain name>
为你的跳板机域名,<your cert>
与<your cert key>
是先前通过
let's encrypt
来获取的证书与私钥,<the mapped port in jump server>
即先前
frp 映射的 http 协议服务端(也就是跳板机)端口。
填写好参数后:
1 | sudo systemctl daemon-reload |
假设你服务器的域名是foo.example.com
,并且跳板机映射
https 端口的值为443
,在跳板机 curl 一下:
1 | > unset http_proxy && curl https://foo.example.com |
代表 nginx 服务正常,如果此时你的跳板机域名已经备案,在本地访问这个 URL 应该可以正常打开页面了。
绕过未备案限制
一句话,https 端口不要用常用端口,应该可以绕过,但不保证稳定性。
之后本地访问的时候,域名后面加上你自己设置的端口应该就可以了。
用户配置
访问 https://foo.example.com/launchpad 设置管理员账号与添加账号(如果没有设置邮箱服务器,可以让管理员账户在后台添加用户,后台会给出一个注册成功的修改密码的链接,把那个链接发给注册用户就好了)。
然后访问 https://foo.example.com/ 自己登录刚注册的账号然后使用。完结撒花。
Updated on Mar 18th, 2025
frp https2http 插件
使用 frp https2http 插件可以在本地将 overleaf 的 http 连接转为 https,省去了跳板机配置nginx的麻烦,并同时解决了FAQ中的websocket连接超时的问题。
- client
1 | serverAddr = <frps server domain name> |
- server
1 | bindPort = 7001 |
你甚至可以再套一层 netlify 的 cdn 反代把这个
<https port>
变成默认的 443。
certbot 手动 hook
使用以下指令可以手动模拟对example.com
域名的 dns
续订(注意是续订,初次不能通过这种方式),并使用foo.sh
脚本:
1 | sudo certbot renew \ |
certbot 会给 foo.sh
传递两个参数:
$CERTBOT_DOMAIN
:你要续订的域名。$CERTBOT_VALIDATION
:验证字符串。
这个脚本要做的内容是在你的 dns provider 中插入一行名为
_acme-challenge. + $CERTBOT_DOMAIN
,值为
$CERTBOT_VALIDATION
的 TXT 记录。如果你使用 netlify 作为
dns,这一点我在 https://github.com/junyu33/netlify-dynamic-dns-py 中的
dns-auth.sh
和 renew.py
中做了一个自动化的实现。
如果运行成功,就可以把 --dry-run
这个参数去掉以执行真正的自动续订。如果续订成功,certbot
会设置一个计划任务,在证书即将到期时再次调用这个脚本进行续订,所以需要保持你的
hook 脚本始终在该路径存在。
FAQ
launchpad 界面中 websocket 检测超时怎么办?
ignore it(目前看来并不影响使用),或者使用 frp 的 https2http 插件。
进入项目时提示 connection error?
原因就是 websocket 连接超时,解决方案同上。
为什么我只能上传最大 1M 的文件?
见此issue,原因是
nginx 配置的问题,有可能是 docker 内部的 nginx 配置,也可能是跳板机中的
nginx 配置(但笔者已经在这里加了
client_max_body_size 50M
,因此可以排除后者原因)。
不使用 HTTPS 可以吗?
至少在本机最新版 Microsoft Edge 会直接提示 connection not secure,并且无法 proceed。其他情况没有测试。
HTTPS 使用自签名证书可以吗?(例如使用 openssl 自己生成一对)
同上。
参考资料
https://github.com/overleaf/toolkit/blob/master/doc/quick-start-guide.md
https://ziuch.com/article/self-hosted-overleaf#105da52b1a26809bbcb5d8294bc18757
https://jinli.io/p/%E8%87%AA%E5%BB%BA%E5%9C%A8%E7%BA%BFlatex%E7%BC%96%E8%AF%91%E9%A2%84%E8%A7%88%E6%9C%8D%E5%8A%A1overleaf%E5%BC%80%E6%BA%90%E7%A4%BE%E5%8C%BA%E7%89%88/
https://gofrp.org/zh-cn/docs/examples/vhost-http/
https://gofrp.org/zh-cn/docs/examples/https2http/
https://github.com/overleaf/docker-image/issues/20
https://github.com/overleaf/overleaf/wiki/HTTPS-reverse-proxy-using-Nginx
https://chat.deepseek.com/