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 使用,更可靠地保存防火墙规则

Ubuntu Server + BCM4360 Wi-Fi + SSH + Tailscale + Claude Code + 免密 sudo

下面按这次针对我的 MacBook Pro (Retina, 13-inch, Late 2013 / A1502) 实际操作的顺序,整理成一份完整的关键命令清单。

1. 在 macOS 上确认机器和 USB

1
2
3
system_profiler SPHardwareDataType
diskutil list
diskutil info /dev/disk4

我的机器确认是:

1
2
3
MacBookPro11,1
MacBook Pro (Retina, 13-inch, Late 2013)
Model A1502

2. Ubuntu 安装后确认网络接口

1
2
ip link
ls /sys/class/net

最初只有:

1
lo

连接手机 USB 网络共享后出现:

1
enxXXXXXXXXXXXX

3. 用手机 USB 网络临时联网

1
2
sudo ip link set enxXXXXXXXXXXXX up
sudo dhcpcd enxXXXXXXXXXXXX

确认 IPv4:

1
ip -4 addr show enxXXXXXXXXXXXX

确认路由:

1
ip route

测试 Internet:

1
ping -c 4 8.8.8.8

4. 安装 BCM4360 驱动

确认内核:

1
uname -r

这次是:

1
6.8.0-100-generic

确认驱动版本:

1
apt policy bcmwl-kernel-source | grep Candidate

安装:

1
2
sudo apt update
sudo apt install bcmwl-kernel-source

5. 让 wl 接管 BCM4360

这台 Mac 的 BCM4360 最初被 b43/bcma 路径占用。

卸载 b43

1
sudo modprobe -r b43

加载 Broadcom 专有驱动:

1
sudo modprobe wl

确认:

1
lsmod | grep '^wl'

最终出现:

1
wl 6438064 0

并且内核日志出现:

1
2
wlan0: Broadcom BCM43a0 B02.11 Hybrid Wireless Controller 6.30.223.271
wl 0000:03:00.0 wlp3s0: renamed from wlan0

说明成功。

6. 启用 Wi-Fi

1
sudo ip link set wlp3s0 up

确认:

1
ip link show wlp3s0

7. 扫描 Wi-Fi

如果没有 iw

1
sudo apt install iw

扫描:

1
sudo iw dev wlp3s0 scan | grep SSID

8. 配置 NetworkManager

1
2
sudo apt install network-manager
sudo systemctl enable --now NetworkManager

查看:

1
nmcli device status

连接 Wi-Fi:

1
nmcli device wifi connect "我的SSID" password "我的WiFi密码"

确认:

1
nmcli device status

以及:

1
ping -c 4 8.8.8.8

此时就可以拔掉手机 USB 网络共享。

9. 安装并启动 SSH

1
sudo systemctl enable --now ssh

确认:

1
systemctl is-active ssh

应该得到:

1
active

查看 Wi-Fi/LAN IP:

1
hostname -I

从另一台电脑:

1
ssh seii@192.168.1.8

如果因为重装系统出现:

1
WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!

执行:

1
ssh-keygen -R 192.168.1.8

然后重新:

1
ssh seii@192.168.1.8

10. 安装 Tailscale

1
curl -fsSL https://tailscale.com/install.sh | sh

登录:

1
sudo tailscale up

查看:

1
2
tailscale status
tailscale ip

11. 安装 Claude Code

1
curl -fsSL https://claude.ai/install.sh | bash

确认:

1
claude --version

启动:

1
claude

12. 设置 seii 免密 sudo

1
sudo visudo -f /etc/sudoers.d/seii

加入:

1
seii ALL=(ALL) NOPASSWD: ALL

保存时如果看到:

1
File Name to Write: /etc/sudoers.d/seii.tmp

直接按:

1
Enter

然后:

1
Ctrl + X

检查:

1
sudo visudo -c

测试:

1
2
sudo -k
sudo whoami

应该直接输出:

1
root

现在这台 A1502 的状态已经是:Ubuntu Server + BCM4360 Wi-Fi + SSH + Tailscale + Claude Code + 免密 sudo。后续就可以基本脱离 HDMI 外接显示器,通过 SSH/Tailscale 管理这台 MacBook。

Comments

2026-03-26