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

# 修改 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
# 添加 NAT 伪装
sudo iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE

# 永久保存(安装 iptables-persistent)
sudo apt install iptables-persistent
sudo iptables-save > /etc/iptables/rules.v4

1.5 防火墙放行

1
2
3
sudo ufw allow 1194/tcp   # OpenVPN
sudo ufw allow 80/tcp # HTTP
sudo ufw allow 443/tcp # HTTPS

二、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
# 从 jhub 传输整个目录
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
# 解决:修改 traefik.toml 只监听 eth0 IP
[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
# /etc/systemd/system/isso.service
[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 避免二进制文件损坏)
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
# /opt/tljh/state/rules/isso.toml
[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
# /opt/tljh/state/rules/line.toml
[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 ✅ 运行中

六、注意事项

  1. SSL 证书:acme.json 从旧服务器复制,Let’s Encrypt 证书可继续使用
  2. 客户端配置:OpenVPN 和 JupyterHub 客户端的 remote 地址需要更新为新服务器 IP
  3. DNS:确保 jhub.dtype.inforegistry.dtype.info 指向新服务器 IP
  4. 二进制文件传输:使用 scp 而不是管道 cat,避免数据损坏
  5. iptables-persistent:替代 UFW 使用,更可靠地保存防火墙规则

Comments