跳转到内容

CMS 服务器安装

这是在站点上搭建 CMS 服务器的步骤。本文按无需专业知识也能照做的方式编写 — 安装文件会自行检查准备情况,并直接安装所需的组件。

开始之前 — 把收到的东西集中放到一处

Section titled “开始之前 — 把收到的东西集中放到一处”

请把收到的东西全部放进 Windows PC 的 C:\treet。如果没有这个文件夹,新建即可。

收到的安装包是这样的 — 请整个文件夹原样拷贝过去。

C:\treet\
읽어주세요.md ← 🔴 **请先阅读。**里面写有本现场的各项值
목록.md ← 包含的文件及其 sha256
TreeT_코드서명_공개인증서.cer ← 🔴 每台终端**安装前**都要登记
check-install.ps1 ← 检测安装是否正确的脚本
설치파일\ ← 终端用的安装文件(+ Android APK)
CMS\treet-cms-offline-<版本>.tar.gz ← CMS 安装包
매뉴얼\ ← 本文档的离线副本
키오스크셋팅\ ← 终端 PC 优化脚本

(읽어주세요.md = 请先阅读,목록.md = 清单,설치파일 = 安装文件,매뉴얼 = 手册,키오스크셋팅 = 终端设置。)

在这里再下载一个文件一起放好 — 这个我们不提供:

ubuntu-26.04.x-live-server-amd64.iso ← 装在虚拟机上的 Ubuntu(从 ubuntu.com 下载)

第一次安装的话,请先看一遍这张地图再开始。从上到下走一遍就完成了。

做什么耗时由谁完成
准备把收到的东西集中到 C:\treet(见上文)5 分钟人工
0创建虚拟机并安装 Ubuntu30~60 分钟人工
0-e🔴 扩展磁盘 — Ubuntu 只使用了一半1 分钟人工
1把安装包移到虚拟机里5~10 分钟人工
2运行 sudo bash install.sh1 分钟人工
3检查准备情况自动安装文件
4回答三个问题1 分钟人工
5记下管理员密码1 分钟人工
6确认实际能打开自动(几分钟)安装文件
7开启备份 — 自动 · 只需确认1 分钟安装文件
7-b在这台电脑上安装 Watchdog — CMS 虚拟机停止时重新启动5 分钟人工
8准备远程访问需要时人工
9互联网地址、证书 + 管理员入口20 分钟人工(令牌、浏览器授权)+ 脚本

CMS 运行在 Ubuntu 虚拟机中。如果是 Windows PC,先创建这台虚拟机。

0-a. 开启 Hyper-V 并创建外部交换机

Section titled “0-a. 开启 Hyper-V 并创建外部交换机”

在控制面板 → 程序 → 启用或关闭 Windows 功能中勾选 Hyper-V 并重启。

重启后,先于虚拟机创建外部交换机。终端要连接到这台虚拟机,虚拟机就必须 连接到这台 PC 的物理网卡上。

通过界面: Hyper-V 管理器 → 虚拟交换机管理器 → 新建虚拟网络交换机 → 外部 → 名称 TreeT-External → 选择这台 PC 实际使用的网卡。 ⚠️ 如果是通过界面创建的,创建后务必单独执行下面命令中的 ③ 检查并补全 DNS(使用固定 IP 时 DNS 会丢失)。

通过命令(管理员 PowerShell) — 连丢失的 DNS 也一并处理:

Terminal window
# ① 确认网卡名称 — 与终端连在同一网络的那块网卡(通常为"以太网",韩文系统为"이더넷")
Get-NetAdapter -Physical | Format-Table Name, InterfaceDescription, Status, LinkSpeed
# ② 填入上面列表中的 Name
$Switch = "TreeT-External"
$Nic = "이더넷"
# 创建前先记下当前设置 — 如果是固定 IP,创建交换机时只有 DNS 会丢失
$Static = (Get-NetIPInterface -InterfaceAlias $Nic -AddressFamily IPv4).Dhcp -eq "Disabled"
$Dns = (Get-DnsClientServerAddress -InterfaceAlias $Nic -AddressFamily IPv4).ServerAddresses
"고정 IP: $Static · 지금 DNS: $($Dns -join ', ')"
# 创建交换机 — 已存在则跳过(⚠️ 网络会中断几秒)
if (-not (Get-VMSwitch -Name $Switch -ErrorAction SilentlyContinue)) {
New-VMSwitch -Name $Switch -NetAdapterName $Nic -AllowManagementOS $true | Out-Null
}
# ③ 检查并补全 DNS — 新适配器的 DNS 为空时补上
# 固定 IP 时 DNS 不会跟过来;即使是自动 IP,也有无法立即获取到的情况。
# 所以无论固定还是自动,**只要为空**就补上。
$vEth = "vEthernet ($Switch)"
for ($i = 0; $i -lt 10 -and -not (Get-DnsClientServerAddress -InterfaceAlias $vEth -AddressFamily IPv4).ServerAddresses; $i++) { Start-Sleep 2 }
if (-not (Get-DnsClientServerAddress -InterfaceAlias $vEth -AddressFamily IPv4).ServerAddresses) {
if (-not $Dns) {
# 如果原本 DNS 就是空的,则填入路由器(网关)和公共 DNS
$Gw = (Get-NetIPConfiguration -InterfaceAlias $vEth).IPv4DefaultGateway.NextHop
$Dns = @($Gw, "8.8.8.8") | Where-Object { $_ }
}
Set-DnsClientServerAddress -InterfaceAlias $vEth -ServerAddresses $Dns
Clear-DnsClientCache
}
# ④ 确认 — 两项都要有输出
Get-VMSwitch $Switch | Format-Table Name, SwitchType, NetAdapterInterfaceDescription
Get-DnsClientServerAddress -InterfaceAlias $vEth -AddressFamily IPv4 | Format-Table InterfaceAlias, ServerAddresses
Resolve-DnsName ubuntu.com -Type A | Select-Object -First 1 Name, IPAddress

Hyper-V 管理器 → 新建 → 虚拟机。

项目值为什么是这个值
代数第 2 代UEFI 启动。Ubuntu 26.04 默认使用第 2 代
内存6 GB(关闭动态内存)实测空闲时 214 MB,但安装、数据库导入和视频转换需要余量
处理器4 核视频转换会占用 CPU — 在这里投入最能感受到效果
硬盘120 GB · 动态扩展程序本身很小(约 200 MB),但媒体和图片会不断累积。因为是动态扩展,一开始不会占满 120 GB
网络TreeT-External(0-a 中创建的外部交换机)终端需要连接到这台虚拟机
安全启动模板Microsoft UEFI 证书颁发机构如果保持默认(Windows),Ubuntu 将无法启动

🔵 如果是用上面的命令创建的,镜像已经挂载且虚拟机已经启动 — 请直接进入 0-d。

如果是用向导创建的:把下载好的 ubuntu-26.04.x-live-server-amd64.iso 挂载到虚拟机设置中的 SCSI 控制器 → DVD 驱动器,然后启动。

可以一路保持默认,但只需注意两处 — **固定 IP(+DNS)**和 OpenSSH。

① 网络 — 给虚拟机分配固定 IP

终端会通过这个地址连接 CMS,安装 CMS 时这个地址也会写入证书。地址一变,终端就会断开,所以 使用固定 IP。

先确定地址 — 必须与主机 PC 在同一网段、是未被使用的地址,并且在路由器自动分配的范围(DHCP) 之外。在主机上用 ipconfig 确认网段和路由器(默认网关)。

示例值
主机 PC192.168.0.4
路由器(网关)192.168.0.1
分配给这台虚拟机的地址192.168.0.10(按现场实际情况)

在安装界面中 — Network configuration → eth0 → Edit IPv4 → Manual:

栏目值
Subnet192.168.0.0/24
Address192.168.0.10
Gateway192.168.0.1
Name servers192.168.0.1, 8.8.8.8
Search domains留空

如果已经装完了 — 在虚拟机中设置。请先确认网卡名称(通常为 eth0)。

Terminal window
ip -br link
Terminal window
sudo tee /etc/netplan/60-treet-static.yaml > /dev/null <<'EOF'
network:
version: 2
ethernets:
eth0:
dhcp4: false
addresses: [192.168.0.10/24]
routes:
- to: default
via: 192.168.0.1
nameservers:
addresses: [192.168.0.1, 8.8.8.8]
EOF
sudo chmod 600 /etc/netplan/60-treet-static.yaml
sudo netplan try

🔵 netplan try 在应用后如果 120 秒内不按 Enter 就会恢复原状 — 即使填错导致断网也是安全的。 按下 Enter 后进行确认:

Terminal window
ip -4 addr show eth0 | grep inet
resolvectl query ubuntu.com

② 勾选 Install OpenSSH server

与其在虚拟机画面上直接打字,从另一台 PC 远程连接进来操作要方便得多。 移动安装包时也要用到它。

安装完成后重启,登录后用下面的命令确认设定的固定 IP 是否已生效。

Terminal window
ip -4 addr show | grep inet

0-e. 🔴 安装后务必立即 — 扩展磁盘

Section titled “0-e. 🔴 安装后务必立即 — 扩展磁盘”

**Ubuntu 安装程序只使用磁盘的一半。**即使分配了 120 GB,实际可用空间也只有约 58 GB。

Terminal window
sudo lvextend -l +100%FREE /dev/ubuntu-vg/ubuntu-lv
sudo resize2fs /dev/ubuntu-vg/ubuntu-lv
df -h /

df -h / 显示 100 GB 以上就说明成功了。

完成到这里后,进入下面的第 1 步。

把安装包中的 CMS\treet-cms-offline-<版本>.tar.gz 这一个文件移到虚拟机中, 并在那里解压。在虚拟机中存放的位置应为固定的本地路径。例:/home/用户/

移好后在虚拟机中解压。

Terminal window
cd ~
tar xzf treet-cms-offline-*.tar.gz
cd treet-cms-offline

在文件夹中运行以下命令。

Terminal window
sudo bash install.sh

之所以用 sudo 运行,是因为安装文件会直接安装尚未准备好的项目(例如 Docker)。

3. 安装文件先进行检查(看一眼即可)

Section titled “3. 安装文件先进行检查(看一眼即可)”

🔵 **这里您无需操作。**安装文件会自行检查 — 下面只是告诉您它检查什么, 方便遇到问题时回来查阅。

如有不足,会在屏幕上提示该怎么做。

检查项目有问题时
操作系统如果不是 Ubuntu 26.04 LTS 会提示(仍可继续)
名称解析(DNS)无法解析时,会连同原因一起提示 — 参阅下文
互联网连接内网隔离环境下属正常(但必须已装有 Docker)
Docker没有则自动安装
时钟时间偏差很大时会提示
磁盘 · 内存不足时阻止安装
端口已被其他程序占用时阻止安装
文件权限在无法保证权限的位置会提示(仍可继续)— 参阅下文

检查通过后,只会问下面三个问题。其余都会自动设置。

① 本站点的名称

1) 이 사이트의 이름 (영문 소문자·숫자·하이픈).
추천: kjr7zbs ← 지금 사용 가능한 이름입니다
>

(提示内容:本站点的名称〔小写英文字母、数字、连字符〕,推荐:kjr7zbs ← 当前可用的名称。)

直接使用推荐的名称也可以(按回车)。这个名称用于区分与设备之间收发的 信号。

② 访问此 CMS 的地址

2) 이 CMS 에 접속할 주소입니다 — 재생기가 이 주소로 붙습니다.
여러 개면 쉼표로 나열하세요. [192.168.0.5]
>

(提示内容:访问此 CMS 的地址 — 播放器将连接此地址。有多个时用逗号分隔。)

方括号中是自动检测到的本机地址。正确的话直接按回车即可。

③ 从外部网络进入的地址

3) 바깥 망에서 이 CMS 로 들어오는 주소가 있으면 적으세요 — 공유기 포워딩 주소(여러 개면 쉼표).
이름으로 붙는 것이 먼저입니다. 이름이 안 풀리는 망(폐쇄망 · 이중 NAT 바깥)에서 쓰는 IP 만 적으세요. 없으면 엔터.
>

(提示内容:如有从外部网络进入此 CMS 的地址 — 路由器转发地址,请填写;有多个时用逗号分隔。优先用名称连接,只填写在名称无法解析的网络中使用的 IP。没有则按回车。)

大多数情况下直接按回车(留空)。只有在经过两层路由器等结构中,外部网络的设备或中继装置必须通过**路由器的转发地址(IP)**连接此 CMS 时才填写。填写的地址会写入 CMS 证书。 安装后需要更改时,无需重新安装,可在管理界面中更改 — 请联系负责人。

安装完成后,会显示一次管理员初始密码。

6. 安装程序自行确认(看一眼即可)

Section titled “6. 安装程序自行确认(看一眼即可)”

🔵 最后会出现一屏检查结果 —— 本机四项设置(时区设为站点时间 · Docker 开机自动启动 · Hyper-V 下的 KVP 守护进程 · 备份计划)的结果,以及 CMS 状态地址 · 下次计划时间 · 本机地址。带 ⚠️ 的行,请照该行给出的命令执行(即使没做成,安装也已成功)。

最后,安装文件会确认画面是否真的能打开。因为有时容器已经启动,画面却 打不开,所以它检查的不是”命令已结束”,而是”确实有响应”。

설치 검증 (실제로 응답하는지 — 최초 설치는 DB 초기화로 몇 분 걸립니다)...
✓ 컨테이너 web 동작
✓ 컨테이너 laravel 동작
✓ 컨테이너 db 동작
✓ 컨테이너 guacd 동작 (원격제어)
✓ 컨테이너 guacamole 동작 (원격제어)
✓ CMS 응답 확인 (HTTP 200)

(输出内容:安装验证 — 各容器运行中〔web、php、db、guacd 与 guacamole 为远程控制〕,CMS 响应确认〔HTTP 200〕。首次安装因数据库初始化需要几分钟。)

显示到这里后,就可以在浏览器中通过 http://<本机地址>:8080 访问了。

🔵 安装程序会自动完成这一步 —— 每天 03:40(站点时间)· 保留 14 天 · 位于安装文件夹的 backup/。下面的步骤用于确认已开启或更改保存位置(重新安装也没关系)。

Terminal window
sudo bash docker/install-backup-timer.sh

每天凌晨把设置、证书、数据库打包备份,保留 14 天。

请手动运行一次,确认确实生成了文件。

Terminal window
sudo systemctl start treetweb-backup-site.service
ls -la backup/

7-b. 在这台电脑上安装 Watchdog —— CMS 停止时重新启动

Section titled “7-b. 在这台电脑上安装 Watchdog —— CMS 停止时重新启动”

CMS 运行在这台电脑的虚拟机中。该虚拟机一旦停止,现场的画面管理会整体中断, 而虚拟机无法自己报告这一点。因此由 外部(这台 Windows 电脑)上的 Watchdog 来守护。

  1. 用与播放电脑相同的方法安装 Watchdog —— 参见现场部署中的 Watchdog 安装。 安装过程中询问 CMS 地址时,填写这台虚拟机的地址(例:http://192.168.0.5:8080)。

  2. 无需做其他事情。 Watchdog 启动后,会自行找到与 CMS 地址 IP 相同的虚拟机 并纳入守护。

  3. ⚠️ 但虚拟机内必须运行 Hyper-V 集成工具,Watchdog 才能看到该虚拟机的 IP(安装程序会自动安装 —— 需要联网)。在这台 Windows 电脑(管理员 PowerShell)上确认:

    Terminal window
    Get-VMNetworkAdapter -VMName treet-cms | Select-Object -ExpandProperty IPAddresses

    如果没有显示虚拟机地址(例:192.168.0.5)而是空的,请在虚拟机内安装并启动集成工具(需要联网):

    Terminal window
    sudo apt install -y linux-cloud-tools-$(uname -r)
    sudo udevadm trigger --subsystem-match=misc --action=add
    sudo systemctl restart hv-kvp-daemon

    用上面的命令能看到地址即可。10 分钟内 CMS 日志会出现 “已将本机 Hyper-V 虚拟机 ‘treet-cms’ 识别为 CMS 并纳入守护”。

    🔵 Watchdog 会自己提示这种状态 —— 虚拟机在运行但看不到 IP 时,CMS 日志的守护行会写 ”… Hyper-V 看不到 IP:虚拟机内需要运行 hv-kvp-daemon … “。看到这一行就执行上面三行。

🔵 如果电脑上已经安装了 Watchdog,就不必再装 —— 播放器和 CMS 在同一台电脑上的现场就是这样。那个 Watchdog 也会一起守护 CMS。

开启后会这样:

出现这种情况时Watchdog 会
虚拟机关机或暂停重新启动它(每 3 分钟检查一次)
CMS 超过 3 分钟无响应记录到 CMS 日志,恢复后留下一行 “几点到几点(N 分钟)无响应”
虚拟机在运行,但只有 CMS 无响应只报告 —— Watchdog 无法操作虚拟机内部的程序

8. 远程连接的方法(这是两回事)

Section titled “8. 远程连接的方法(这是两回事)”

这里经常被混淆,所以分开说明。

安装文件不会安装它。安装 Ubuntu 时勾选 Install OpenSSH server 就是为了这个 (参阅 0-d)。

如果当时没勾选,现在安装即可。

Terminal window
sudo apt install -y openssh-server
systemctl status ssh

连不上时,依次检查以下各项。

检查命令 · 位置
SSH 是否在运行systemctl status ssh
本机地址ip -4 addr show | grep inet
🔴 虚拟机是否使用外部交换机Hyper-V 管理器 → 虚拟机设置 → 网络适配器。如果是内部/专用交换机,外部无法连接
防火墙sudo ufw status(默认是关闭的)

8-b. 要查看设备画面 — 用远程控制功能

Section titled “8-b. 要查看设备画面 — 用远程控制功能”

这是在 CMS 管理后台中用浏览器查看终端画面的功能。 安装后即已开启 — 无需另行操作。

CMS 一侧已准备就绪,但输出画面的一端在设备上。 请在每台终端 PC 上安装并运行 VNC 服务器(UltraVNC)。

在设备上值
VNC 服务器UltraVNC(设置为安装后自动启动)
端口5900(保持默认)
密码无需设定 —— 每次点击按钮时,该 PC 的 Watchdog 都会设置一次性密码(自 CMS 2026.9.725 · Watchdog 2026.9.153 起)

CMS 一侧大多数情况下留空即可(设备上报的 IP · 5900)。只有地址或端口不同时, 才在管理后台的 设备管理 → 设备页面 → 编辑基本信息 → “远程连接” 栏中填写 地址[:端口] —— 不填写密码。

9. 互联网地址与证书 — 同时搭建两个入口

Section titled “9. 互联网地址与证书 — 同时搭建两个入口”

站点有两个入口。默认配置是两个都要。

地址由谁使用如何进入
https://<站点>.treetsites.com:8443设备 · 上传大视频 · 日常管理路由器 → 直达 CMS(公共证书)
https://admin-<站点>.treetsites.com仅限管理员 — 路由器端口被封时的应急入口Cloudflare 隧道

在虚拟机中:

Terminal window
sudo ./cert-check.sh # 是否为公共证书 · 距到期还有几天
sudo ./install-tunnel.sh --check # 隧道服务 · 外部响应

然后在 Windows 浏览器中直接打开这两个地址 — 两者都应显示锁形图标, 不应出现警告界面。🔵 如果在站点内部网络中打不开第一个地址, 说明路由器阻止了回流到自己公网 IP 的访问(发夹/NAT 回环)— 请用手机流量 确认,或使用管理员入口。

时间服务器 —— CMS 为设备提供时间

Section titled “时间服务器 —— CMS 为设备提供时间”

安装 CMS 时会同时启动 时间服务器(NTP)。没有关闭它的开关 —— 设备一打开时间同步就必须能收到时间。 同一内网的设备通过 UDP 123 端口从这台 CMS 获取时间。即使在连不上互联网时间服务器的封闭网络中,设备之间也会对齐到这台 CMS 的时钟。

要做的事原因
如果开启了 CMS VM 的防火墙,请放行 来自内网的 UDP 123被拦截时设备收不到时间
路由器上 不要对外开放公开的时间服务器会被用于攻击
不要在 CMS VM 上 另外安装 其他时间服务器程序(chrony · ntpd)它们会争用 123 端口,导致 CMS 的时间服务器无法启动 —— 这种情况下安装前检查会拦下并提示。Ubuntu 默认的对时(timesyncd)没有问题

CMS 自身的时钟由 VM 负责(Hyper-V 集成服务的时间同步 · Ubuntu 默认的对时)。

走到这里,以下各项都应该已经完成。只要有一项不行,就回到对应的步骤。

确认方法不行时
管理后台能打开在浏览器中访问 http://<本机地址>:8080第 6 步
能以管理员登录使用第 5 步记下的密码第 5 步
备份已开启systemctl list-timers | grep treetweb第 7 步
确实生成了备份文件ls -la backup/第 7 步
站点地址能无警告打开https://<站点>.treetsites.com:8443第 9 步
管理员入口能打开https://admin-<站点>.treetsites.com9-d

安装只做到搭好 CMS 为止。要让屏幕上出现内容,还需要三件事。

  1. 在终端 PC 上安装播放器(TreeTview),并在该 PC 上按 F8 填写此 CMS 地址。 🔴 仅安装是连不上的 — 播放器出厂带着开发默认值(127.0.0.1)。 填好地址后,它才会自动注册并出现在设备列表中(设备证书也会 自动签发)。→ 现场部署 ⚠️ 填好后请亲眼查看播放器日志中的 [사이트설정] 확인(站点设置 确认)行。仅出现在列表中是 不够的 — 跳过这一确认,后面出问题时将无从查找原因。
  2. 上传内容并排播 — 决定在哪块屏幕、什么时候、播放什么。
  3. 在每台设备上安装 UltraVNC — 远程控制在 CMS 一侧已经开启, 设备上只需有输出画面的一端即可(8-b)。

使用方法见管理后台文档 — 设备注册、排播、远程控制都按界面顺序 写明了。

转入正式运营时 — 把更新通道设为 stable

Section titled “转入正式运营时 — 把更新通道设为 stable”

刚安装完的 CMS 被视为 尚未运营(开发阶段)。此时也会接收 开发版(仍在测试的应用 · CMS 版本)。 连接好所有设备、完成编排、所有设置都完成后,转入正式运营 —— 从此只接收 测试完成并正式发布的版本(stable)。

  1. 打开安装文件夹中的 .env: sudo nano .env
  2. 删除 #TREET_UPDATE_CHANNEL=stable 这一行 开头的 #。如果没有这一行,就在末尾新加一行 TREET_UPDATE_CHANNEL=stable。
  3. 保存后重新启动 CMS: sudo docker compose up -d
TREET_UPDATE_CHANNEL这台 CMS
(空 — 默认)**尚未运营。**也接收开发版
stable**运营中。**只接收已晋级(stable)的版本 —— 应用更新列表 · CMS 更新包 · 手动上传的安装包都一样

与首次安装方法相同 — 拿到新的安装包,在其中重新运行 install.sh。 并没有单独的更新流程。

Terminal window
# 在虚拟机中,在解压新安装包的文件夹里
sudo bash install.sh

有哪些变化,请通过安装包中的 읽어주세요.md 和版本号确认。升级后 请重新检查上文*“确认是否全部完成”*中的四项 — 尤其是管理后台能否打开。

重新搭建同一站点时,必须先有备份文件。

Terminal window
bash docker/restore-site.sh <备份文件> # 把设置、证书放回原位
sudo bash install.sh # 安装
bash docker/restore-site.sh <备份文件> --db-only # 导入数据
Terminal window
docker compose logs --tail 50 web laravel # 最近的日志(要看定时任务,再加上 laravel-scheduler media-worker)
docker compose ps # 哪些在运行
sudo bash docker/preflight.sh # 重新检查准备情况