avatar

蜗牛札记

记录技术、生活与一点点折腾

  • 首页
  • PetBoxX
  • 工具软件
  • NAS 折腾
  • Linux 运维
  • VPS & 网络
  • 关于
主页 将 Python Web 小工具部署到 VPS:以 TCC5110 LVDS 寄存器生成器为例
文章

将 Python Web 小工具部署到 VPS:以 TCC5110 LVDS 寄存器生成器为例

发表于 最近 更新于 最近
作者 Snailszzy
47~60 分钟 阅读

背景

最近做了一个 TCC5110 LVDS Timing Register Generator 小工具,用来根据 LCD/LVDS panel timing spec 自动生成 Telechips TCC5110 的寄存器配置,包括 register list、C header、CSV 和 report。

这个工具最开始是本地运行的 Python Web UI:

python3 tcc5110_lvds_webui.py

默认只监听本机:

http://127.0.0.1:8765/

本地使用没有问题,但如果希望团队里的其他 FAE、RD 或客户支持同事也能远程访问,就需要把它部署到 VPS 上,并通过域名和 HTTPS 对外提供服务。

最终部署后的访问地址是:

https://lvds.snailszzy.top/

本文记录完整部署过程。

是否还需要 Python 后端?

需要。

这个工具并不是一个纯静态 HTML 页面。Web UI 只是负责收集参数,真正的寄存器生成逻辑在 Python 文件中:

tcc5110_lvds_reg_generator.py

Web UI 点击 “生成寄存器配置” 后,会向后端接口发送请求:

POST /generate

后端再调用 Python 生成器,返回 report、register list、C header、CSV 等结果。

所以部署时有两种路线:

  1. 保留 Python 后端,直接把现有工具部署到服务器
  2. 把生成逻辑重写成 JavaScript,改成纯前端工具

这次选择第一种。原因是风险更低、维护更简单,而且现有生成逻辑已经验证过,不需要重新实现一套算法。

整体架构

部署后的结构如下:

用户浏览器
    |
    | HTTPS
    v
Cloudflare DNS / CDN
    |
    | HTTPS
    v
VPS 上的 Caddy
    |
    | Docker 内网 HTTP
    v
tcc5110-lvds Python 容器
    |
    v
tcc5110_lvds_webui.py + tcc5110_lvds_reg_generator.py

其中:

  • Cloudflare 负责 DNS 和公网访问入口
  • Caddy 负责 HTTPS 证书和反向代理
  • Docker 负责运行 Python Web 工具
  • Python 后端负责实际寄存器计算

准备部署目录

先把需要部署的文件整理到一个独立目录:

tcc5110_lvds_reg_generator_deploy/
├── Dockerfile
├── docker-compose.yml
├── DEPLOY.md
├── README.md
├── examples/
├── tcc5110_lvds_reg_generator.py
└── tcc5110_lvds_webui.py

核心文件是:

tcc5110_lvds_webui.py
tcc5110_lvds_reg_generator.py

其中 tcc5110_lvds_webui.py 需要支持在容器中监听 0.0.0.0,否则容器外部访问不到服务。

启动参数设计为:

python3 tcc5110_lvds_webui.py --host 0.0.0.0 --port 8765 --no-browser

本地运行时可以继续使用:

python3 tcc5110_lvds_webui.py

服务器运行时不需要自动打开浏览器,所以加 --no-browser。

修改 Web UI 的监听地址

原始版本通常只监听:

ThreadingHTTPServer(("127.0.0.1", args.port), Handler)

这适合本地工具,但不适合 Docker 容器部署。

可以增加 --host 参数:

ap.add_argument("--host", default="127.0.0.1")
ap.add_argument("--port", type=int, default=8765)
ap.add_argument("--no-browser", action="store_true",
                help="不自动打开浏览器")
args = ap.parse_args()

srv = ThreadingHTTPServer((args.host, args.port), Handler)

这样本地默认仍然安全地监听 127.0.0.1,而容器部署时可以指定:

--host 0.0.0.0

处理多人使用时的自动保存问题

原始 Web UI 有一个服务端自动保存:

webui_autosave.json

这在本地使用很好,但多人远程访问时会有问题:

  • A 同事填的参数会保存到服务器
  • B 同事打开页面时可能看到 A 的参数
  • 多人同时使用会互相覆盖

所以部署版建议把自动保存改成浏览器本地 localStorage。

前端定义一个本地保存 key:

const STORAGE_KEY = "tcc5110_lvds_webui_state_v1";

保存:

localStorage.setItem(STORAGE_KEY, JSON.stringify(rawState()));

恢复:

const s = JSON.parse(localStorage.getItem(STORAGE_KEY) || "{}");

这样每个用户、每个浏览器各自保存自己的表单状态,不会互相影响。

编写 Dockerfile

这个工具只依赖 Python 标准库,不需要安装额外 Python package,所以 Dockerfile 很简单:

FROM python:3.10-slim

ENV PYTHONDONTWRITEBYTECODE=1 \
    PYTHONUNBUFFERED=1

WORKDIR /app
COPY . /app

EXPOSE 8765
CMD ["python3", "tcc5110_lvds_webui.py", "--host", "0.0.0.0", "--port", "8765", "--no-browser"]

几点说明:

  • python:3.10-slim 足够使用
  • EXPOSE 8765 表示容器内部服务端口
  • --host 0.0.0.0 让服务可以被 Docker 网络访问
  • --no-browser 避免服务器尝试打开浏览器

编写 docker-compose.yml

当前 VPS 上已经有一个 Halo 博客和 Caddy 容器,它们在 Docker 网络:

halo-blog_halo-net

为了让 Caddy 可以通过容器名访问这个工具,需要把工具容器也加入同一个网络:

services:
  tcc5110-lvds:
    build: .
    container_name: tcc5110-lvds
    restart: unless-stopped
    networks:
      - halo-blog_halo-net

networks:
  halo-blog_halo-net:
    external: true

这样 Caddy 可以直接反向代理到:

tcc5110-lvds:8765

上传文件到 VPS

本地部署目录:

/Users/telechips/Documents/FAE AI Improment/tcc5110_lvds_reg_generator_deploy/

VPS 目标目录:

/home/ubuntu/tcc5110-lvds-webui/

上传命令:

ssh myvps2 'mkdir -p /home/ubuntu/tcc5110-lvds-webui'

rsync -az --delete \
  '/Users/telechips/Documents/FAE AI Improment/tcc5110_lvds_reg_generator_deploy/' \
  myvps2:/home/ubuntu/tcc5110-lvds-webui/

在 VPS 上构建并启动容器

登录 VPS:

ssh myvps2

进入部署目录:

cd /home/ubuntu/tcc5110-lvds-webui

构建并启动:

docker compose up -d --build

查看容器状态:

docker ps --filter name=tcc5110-lvds

正常情况下可以看到:

tcc5110-lvds   Up ...

查看日志:

docker logs --tail=80 tcc5110-lvds

正常日志类似:

TCC5110 LVDS Timing Register Generator Web UI 运行中: http://127.0.0.1:8765/  (Ctrl+C 退出)

这里显示 127.0.0.1 只是程序打印的展示 URL,不影响容器内实际监听 0.0.0.0。

配置 Caddy 反向代理

VPS 上原来已有 Halo 博客:

blog.snailszzy.top

Caddy 配置文件路径:

/home/ubuntu/halo-blog/Caddyfile

先备份:

cp /home/ubuntu/halo-blog/Caddyfile \
   /home/ubuntu/halo-blog/Caddyfile.bak.$(date +%Y%m%d%H%M%S)

然后添加 lvds.snailszzy.top:

lvds.snailszzy.top {
    reverse_proxy tcc5110-lvds:8765
    encode gzip
    header {
        X-Content-Type-Options nosniff
        X-Frame-Options DENY
    }
}

如果希望旧地址也兼容,可以在 blog.snailszzy.top 下保留 /lvds/ 路径代理:

blog.snailszzy.top {
    redir /lvds /lvds/

    handle_path /lvds* {
        reverse_proxy tcc5110-lvds:8765
    }

    handle {
        reverse_proxy halo:8090
    }

    encode gzip
    header {
        X-Content-Type-Options nosniff
        X-Frame-Options DENY
    }
}

lvds.snailszzy.top {
    reverse_proxy tcc5110-lvds:8765
    encode gzip
    header {
        X-Content-Type-Options nosniff
        X-Frame-Options DENY
    }
}

验证 Caddy 配置:

docker exec caddy caddy validate --config /etc/caddy/Caddyfile

重新加载:

docker exec caddy caddy reload --config /etc/caddy/Caddyfile

配置 Cloudflare DNS

域名 snailszzy.top 使用 Cloudflare DNS。

在 Cloudflare 后台添加记录:

Type: CNAME
Name: lvds
Target: blog.snailszzy.top
Proxy status: Proxied
TTL: Auto

也可以使用 A 记录:

Type: A
Name: lvds
IPv4: 138.2.111.81
Proxy status: Proxied
TTL: Auto

推荐使用 CNAME 指向 blog.snailszzy.top,这样如果以后 VPS IP 变化,只需要维护 blog 的解析。

DNS 生效后检查:

dig +short lvds.snailszzy.top A

如果返回 Cloudflare 的 IP,例如:

104.21.x.x
172.67.x.x

说明 Cloudflare 代理记录已经生效。

验证服务

验证页面:

curl -sS https://lvds.snailszzy.top/ | head

应返回 HTML:

<!doctype html>
<html lang="zh">

验证生成接口:

curl -sS -X POST https://lvds.snailszzy.top/generate \
  -H 'Content-Type: application/json' \
  --data-binary @examples/hsd123jpw2_a00_full_panel.json

返回中应包含:

{
  "ok": true,
  "n_regs": 46,
  "frame_rate": 59.999224565756826,
  "scope": "full_panel"
}

也可以用 Python 简单解析:

curl -sS -X POST https://lvds.snailszzy.top/generate \
  -H 'Content-Type: application/json' \
  --data-binary @examples/hsd123jpw2_a00_full_panel.json \
| python3 -c 'import json,sys; d=json.load(sys.stdin); print(d.get("ok"), d.get("n_regs"), round(d.get("frame_rate",0),3), d.get("scope"), len(d.get("warnings",[])))'

期望输出:

True 46 59.999 full_panel 0

问题 1:点击按钮提示 Access Denied

部署过程中遇到过一个问题:

请求失败: SyntaxError: Unexpected token 'A', "Access Denied" is not valid JSON

原因是访问旧路径时少了最后的 /:

https://blog.snailszzy.top/lvds

页面中的相对请求 generate 会被浏览器解析成:

https://blog.snailszzy.top/generate

这个路径属于原来的 Halo 博客,不是 LVDS 工具,所以返回:

Access Denied

前端再把这个纯文本当 JSON 解析,就出现了错误。

解决方法有两个:

  1. Caddy 把 /lvds 重定向到 /lvds/
  2. 前端明确请求 /lvds/generate 或在独立域名下请求 generate

Caddy 配置:

redir /lvds /lvds/

前端也可以根据路径选择接口:

const GENERATE_URL = window.location.pathname === "/lvds" ||
                     window.location.pathname.startsWith("/lvds/")
                     ? "/lvds/generate" : "generate";

这样不管用户打开 /lvds 还是 /lvds/,按钮都不会请求到错误路径。

问题 2:lvds.snailszzy.top 提示 SSL handshake failed

切换到独立子域名时,浏览器曾提示:

SSL handshake failed

这个问题发生在 Cloudflare 已经把 lvds.snailszzy.top 代理到源站,但源站 Caddy 还没有成功申请 lvds.snailszzy.top 证书时。

检查 Caddy 日志:

docker logs --tail=160 caddy

一开始可以看到类似:

DNS problem: NXDOMAIN looking up A for lvds.snailszzy.top

说明 Caddy 申请证书时 DNS 还没有生效。

DNS 生效后,强制 Caddy 重新加载:

docker exec caddy caddy reload --config /etc/caddy/Caddyfile

然后继续查看日志:

docker logs --since=2m caddy

正常情况下会看到:

authorization finalized
validations succeeded; finalizing order
certificate obtained successfully

证书文件也会出现在:

/data/caddy/certificates/acme-v02.api.letsencrypt.org-directory/lvds.snailszzy.top/

之后再访问:

https://lvds.snailszzy.top/

就可以正常打开。

更新工具

以后如果修改了 Python 代码或 Web UI,只需要重新上传并重建容器:

rsync -az --delete \
  '/Users/telechips/Documents/FAE AI Improment/tcc5110_lvds_reg_generator_deploy/' \
  myvps2:/home/ubuntu/tcc5110-lvds-webui/

ssh myvps2
cd /home/ubuntu/tcc5110-lvds-webui
docker compose up -d --build

如果只改了 Caddyfile:

docker exec caddy caddy validate --config /etc/caddy/Caddyfile
docker exec caddy caddy reload --config /etc/caddy/Caddyfile

安全建议

当前工具是公开访问的。如果只是内部团队使用,建议后续加一层访问控制。

可选方案:

  1. Cloudflare Access
  2. Caddy basic_auth
  3. 限制公司 VPN 或固定 IP 访问

如果只是临时给团队使用,Caddy basic_auth 最简单。

示例:

lvds.snailszzy.top {
    basic_auth {
        user JDJhJDE0JEF4YW1wbGVIYXNo
    }
    reverse_proxy tcc5110-lvds:8765
}

密码 hash 可以用 Caddy 生成:

docker exec -it caddy caddy hash-password

总结

这次部署的关键点有三个:

  1. 这个工具不是纯前端,仍然需要 Python 后端执行寄存器生成逻辑
  2. Docker + Caddy 是比较轻量、稳定、容易维护的部署方式
  3. 独立子域名部署比挂在博客路径下更干净,最终推荐使用 https://lvds.snailszzy.top/

最终访问地址:

https://lvds.snailszzy.top/

后续如果还要部署类似的小工具,可以复用这套模式:

Python Web UI -> Docker 容器 -> Caddy 反向代理 -> Cloudflare DNS -> HTTPS 域名访问
工具软件
许可协议:  CC BY 4.0
分享

相关文章

6月 15, 2026

将 Python Web 小工具部署到 VPS:以 TCC5110 LVDS 寄存器生成器为例

背景 最近做了一个 TCC5110 LVDS Timing Register Generator 小工具,用来根据 LCD/LVDS panel timing spec 自动生成 Telechips TCC5110 的寄存器配置,包括 register list、C header、CSV 和 rep

12月 18, 2023

网址集锦

各款iPad 机型以及发售年限。 https://support.apple.com/zh-cn/HT201471 Mario 壁纸 https://www.pinterest.com/pin/605030531217190315/ Mr.renedeer,学习tutor https://githu

8月 29, 2023

Sublime Text4 4152 安装激活

本文来源于 https://songxwn.com/Sublime_Text4_4152/ 介绍 此教程用于Windows/Liunx/Ubuntu 下Sublime Text4 4152版本的安装和激活。 无需安装其他软件,无需下载替换文件。 官网: https://www.sublimetext

下一篇

上一篇

智能爬宠箱报警系统说明

最近更新

  • 将 Python Web 小工具部署到 VPS:以 TCC5110 LVDS 寄存器生成器为例
  • 智能爬宠箱报警系统说明
  • PetBoxX ESP32 安全冗余机制设计与测试手册
  • PetBoxX 恒温区风扇控制的演变:固定 PWM、hold_ready 重置,与动态微调
  • PetBoxX 育雏系统:温湿度分阶段管理与自动喷雾设计

热门标签

Halo PetBox PetBoxX

目录

©2026 蜗牛札记. 保留部分权利。

使用 Halo 主题 Chirpy