OpenVPN + TLJH + isso 从 Debian 迁移到 Ubuntu
2026-03-26 完成了从 Debian (jhub.dtype.info) 到 Ubuntu (mail) 的服务迁移记录。
一、OpenVPN 迁移
1.1 备份与传输
在源服务器上备份配置:
1
| sudo tar -czvf openvpn-backup.tar.gz /etc/openvpn/
|
1.2 恢复时的问题与解决
| 问题 |
原因 |
解决方案 |
/etc/openvpn/server.conf 不存在 |
配置文件实际在 /etc/openvpn/server/server.conf |
创建符号链接 |
Cannot pre-load keyfile (tc.key) |
相对路径解析错误 |
改用绝对路径 /etc/openvpn/server/tc.key |
Cannot assign requested address |
local 10.146.0.3 是旧服务器 IP |
改为新服务器 IP 160.251.141.121 |
1.3 修复后的配置
1 2 3 4 5 6 7 8 9 10
| sudo ln -s /etc/openvpn/server/server.conf /etc/openvpn/server.conf
ca /etc/openvpn/server/ca.crt cert /etc/openvpn/server/server.crt key /etc/openvpn/server/server.key dh /etc/openvpn/server/dh.pem tls-crypt /etc/openvpn/server/tc.key crl-verify /etc/openvpn/server/crl.pem
|
1.4 NAT 转发配置
OpenVPN 客户端连接后无法上网,需要添加 NAT 规则:
1 2 3 4 5 6
| sudo iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
sudo apt install iptables-persistent sudo iptables-save > /etc/iptables/rules.v4
|
1.5 防火墙放行
1 2 3
| sudo ufw allow 1194/tcp sudo ufw allow 80/tcp sudo ufw allow 443/tcp
|
二、TLJH (The Littlest JupyterHub) 迁移
2.1 安装 TLJH
Ubuntu 上使用官方安装脚本:
1 2
| curl -sL https://raw.githubusercontent.com/jupyterhub/the-littlest-jupyterhub/main/bootstrap/bootstrap.py -o /tmp/bootstrap.py python3 /tmp/bootstrap.py
|
2.2 复制配置与状态
1 2
| ssh jhub "sudo tar -C /opt/tljh -czvf - config state" | ssh mail "sudo tar -xzvf - -C /opt/tljh/"
|
2.3 Traefik 配置问题
问题 1:端口 443 被 Tailscale Funnel 占用
1 2 3 4 5 6
| [entryPoints.http] address = "160.251.141.121:80"
[entryPoints.https] address = "160.251.141.121:443"
|
问题 2:traefik v3 不支持 toPort 参数(HTTP 重定向)
删除 traefik.toml 中的 toPort = 443 配置。
问题 3:缺少 HTTP 路由器定义
rules.toml 中需要显式定义路由器:
1 2 3 4
| [http.routers.router__2F] service = "service__2F" rule = "PathPrefix(`/`)" entryPoints = [ "https",]
|
2.4 防火墙放行
1 2
| sudo ufw allow 80/tcp sudo ufw allow 443/tcp
|
三、isso 评论系统迁移
3.1 安装 isso
1
| sudo pip3 install --break-system-packages isso gunicorn
|
3.2 创建 systemd 服务
1 2 3 4 5 6 7 8 9 10 11 12
| [Unit] Description=lightweight Disqus alternative
[Service] User=root Restart=always Environment="ISSO_SETTINGS=/etc/isso.conf" ExecStart=/usr/local/bin/gunicorn --bind 127.0.0.1:8000 --log-file /var/log/isso.log --preload isso.run
[Install] WantedBy=multi-user.target
|
3.3 配置文件与数据
1 2 3 4 5 6
| scp jhub:/etc/isso.conf mail:/tmp/ && ssh mail "sudo mv /tmp/isso.conf /etc/isso.conf"
scp jhub:/var/lib/isso/comments.db mail:/tmp/comments.db ssh mail "sudo mv /tmp/comments.db /var/lib/isso/comments.db"
|
3.4 Traefik 路由规则
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| [http.routers.isso] service = "isso" rule = "Host(`jhub.dtype.info`) && PathPrefix(`/isso/`)" entryPoints = [ "https",] middlewares = ["isso"]
[http.middlewares] [http.middlewares.isso.stripPrefix] prefixes = ["/isso"]
[http.services.isso.loadBalancer] passHostHeader = true [[http.services.isso.loadBalancer.servers]] url = "http://127.0.0.1:8000"
|
四、其他 Traefik 路由
4.1 LINE Webhook 转发
1 2 3 4 5 6 7 8 9 10
| [http.routers.line-webhook] service = "line-webhook" rule = "Host(`jhub.dtype.info`) && PathPrefix(`/line/`)" entryPoints = [ "https",]
[http.services.line-webhook.loadBalancer] passHostHeader = true [[http.services.line-webhook.loadBalancer.servers]] url = "http://100.94.198.8:18790"
|
五、服务状态
| 服务 |
端口 |
状态 |
| OpenVPN |
TCP 1194 |
✅ 运行中 |
| Traefik |
80/443 |
✅ 运行中 |
| JupyterHub |
15001 |
✅ 运行中 |
| isso |
8000 |
✅ 运行中 |
六、注意事项
- SSL 证书:acme.json 从旧服务器复制,Let’s Encrypt 证书可继续使用
- 客户端配置:OpenVPN 和 JupyterHub 客户端的
remote 地址需要更新为新服务器 IP
- DNS:确保
jhub.dtype.info 和 registry.dtype.info 指向新服务器 IP
- 二进制文件传输:使用
scp 而不是管道 cat,避免数据损坏
- iptables-persistent:替代 UFW 使用,更可靠地保存防火墙规则