ClipCascade 安装部署指南
Ubuntu 22.04 裸机部署 ClipCascade 服务端 v3.3.1 全流程实测:Java 21 环境、专用账户、systemd 单元、首次登录改密闭环、nginx HTTPS+WebSocket 反向代理与排障速查。
ClipCascade 安装部署指南
本文在 Ubuntu 22.04 服务器上以 systemd 裸机方式部署 ClipCascade 服务端 v3.3.1,覆盖 Java 21 环境、专用系统账户、环境变量文件、开机自启、HTTPS 反向代理与首次登录加固全流程。文中全部命令与回显均在真实服务器上逐条实测。
选型背景与产品定位见 《ClipCascade 介绍与选型指南》;部署完成后要精细化调整服务端行为,请转到 《ClipCascade 配置参数详解》;日常运维与客户端命令行见 《ClipCascade 常用 CLI 命令详解》。
一、部署规划
| 项目 | 本文取值 | 说明 |
|---|---|---|
| 操作系统 | Ubuntu 22.04(64 位) | 服务端只依赖 Java 21+,其他发行版同理 |
| 服务端版本 | v3.3.1 | 官方 Releases 最新稳定版(发布于 2026-10-25) |
| 运行账户 | clipcascade(系统用户,无登录 shell) | 最小权限运行 |
| 安装目录 | /opt/clipcascade | 存放服务端 JAR |
| 数据目录 | /var/lib/clipcascade | 工作目录,内含数据库 database/ 与日志 logs/ |
| 配置文件 | /etc/clipcascade/clipcascade.env | systemd EnvironmentFile |
| 监听端口 | 8080(HTTP 服务) | 由 CC_PORT 控制,本文另配 nginx 443 对外 |
| 默认管理员 | admin / admin123 | 首次登录后必须立即修改(本文实测演示) |
服务端形态说明:官方对外分发的服务端产物是一个独立 JAR(ClipCascade-Server-JRE_21.jar),内嵌 Web 服务与 WebSocket 端点,任意满足 Java 21+ 的环境可直接运行;官方仓库另附带打包部署样例文件供偏好的读者取用,但本文遵循裸机 + systemd 的生产服务器视角展开。
二、安装 Java 21
ClipCascade 服务端要求 Java 21 或更高版本。Ubuntu 22.04 官方源即可满足:
apt update
apt install -y openjdk-21-jre-headless
java -version
实测回显:
openjdk version "21.0.12.1" 2026-08-18
OpenJDK Runtime Environment (build 21.0.12.1+1-1-22.04.4-Ubuntu)
OpenJDK 64-Bit Server VM (build 21.0.12.1+1-22.04.4-Ubuntu, mixed mode, sharing)
三、创建运行账户与目录
useradd --system --home-dir /var/lib/clipcascade --create-home --shell /usr/sbin/nologin clipcascade
mkdir -p /opt/clipcascade /etc/clipcascade
mkdir -p /var/lib/clipcascade/database /var/lib/clipcascade/logs
chown -R clipcascade:clipcascade /var/lib/clipcascade
说明:数据库目录 /var/lib/clipcascade/database 用于存放内置 H2 数据库文件(默认加密),日志目录存放滚动日志。若后续切换 PostgreSQL,可将两者迁移至独立存储。
四、下载服务端 JAR
从官方 GitHub Releases 下载 v3.3.1 的服务端包(网络受限环境可为下载命令追加代理参数,如 -x http://192.168.1.62:7897):
cd /opt/clipcascade
curl -L -o ClipCascade-Server-JRE_21.jar \
https://github.com/Sathvik-Rao/ClipCascade/releases/download/v3.3.1/ClipCascade-Server-JRE_21.jar
ls -l ClipCascade-Server-JRE_21.jar
实测回显:
-rw-r--r-- 1 root root 77894246 Oct 28 03:34 ClipCascade-Server-JRE_21.jar
JAR 约 74 MiB,为内置 JRE 21 目标的自包含服务端。若官方发布页后续提供 SHA256 校验值,建议下载后核对。
五、编写环境变量文件
ClipCascade 的全部服务端行为通过 CC_ 前缀环境变量控制,均非必填(不配置则走内置默认值)。本文先落一份贴近默认值的基础配置:
cat > /etc/clipcascade/clipcascade.env <<'EOF'
CC_PORT=8080
CC_MAX_MESSAGE_SIZE_IN_MiB=1
CC_P2P_ENABLED=false
CC_SIGNUP_ENABLED=false
CC_ALLOWED_ORIGINS=*
CC_SESSION_TIMEOUT=525960m
CC_SERVER_LOGGING_LEVEL=INFO
EOF
chown root:clipcascade /etc/clipcascade/clipcascade.env
chmod 640 /etc/clipcascade/clipcascade.env
逐项含义与更多变量(数据库、防暴力破解、外部消息代理等共 37 个)见 《ClipCascade 配置参数详解》。此处两点安全取向:
CC_SIGNUP_ENABLED=false:关闭自助注册,用户一律由管理员创建,防止公共实例被陌生人占用;CC_ALLOWED_ORIGINS:若有固定域名,建议改为https://clipcascade.example.com收紧 WebSocket 跨域。
六、编写 systemd 单元
cat > /etc/systemd/system/clipcascade.service <<'EOF'
[Unit]
Description=ClipCascade Clipboard Sync Server
After=network.target
[Service]
Type=simple
User=clipcascade
Group=clipcascade
WorkingDirectory=/var/lib/clipcascade
EnvironmentFile=/etc/clipcascade/clipcascade.env
ExecStart=/usr/bin/java -Xms256m -Xmx512m -jar /opt/clipcascade/ClipCascade-Server-JRE_21.jar
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now clipcascade
实测要点:-Xms256m -Xmx512m 将堆内存限制在 512MB,单人/小团队规模绰绰有余(实测进程常驻内存约 400MB);WorkingDirectory 指向 /var/lib/clipcascade,使相对路径的 H2 数据库落在 ./database/ 下。
启动后确认状态:
systemctl status clipcascade --no-pager -l
实测回显(节选):
● clipcascade.service - ClipCascade Clipboard Sync Server
Loaded: loaded (/etc/systemd/system/clipcascade.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2026-10-28 03:35:28 UTC; 25min ago
Main PID: 4006 (java)
Tasks: 49 (limit: 2932)
Memory: 398.2M
CPU: 13.654s
CGroup: /system.slice/clipcascade.service
└─4006 /usr/bin/java -Xms256m -Xmx512m -jar /opt/clipcascade/ClipCascade-Server-JRE_21.jar
观察启动日志确认内嵌 Web 服务就绪:
journalctl -u clipcascade -n 5 --no-pager -o cat
实测回显(节选):
2026-10-28T04:05:22.313Z INFO 4773 --- [ClipCascade] [ main] c.a.clipcascade.ClipCascadeApplication : Started ClipCascadeApplication in 3.405 seconds (process running for 3.69)
2026-10-28T04:05:26.656Z INFO 4773 --- [ClipCascade] [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2026-10-28T04:05:26.657Z INFO 4773 --- [ClipCascade] [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 1 ms
冷启动到可用约 4 秒。
七、健康检查与版本核实
ClipCascade 内置两个免认证探活端点:
curl -s http://127.0.0.1:8080/health; echo
curl -s http://127.0.0.1:8080/ping; echo
实测回显:
OK
pong
再核实服务端自报版本:
curl -s http://127.0.0.1:8080/server-version; echo
实测回显:
{"version":"3.3.0"}
排障实录:
/server-version与发布版本不一致 现象:从 Releases 下载的是 v3.3.1 包,/server-version却自报3.3.0。 原因:服务端界面/API 的版本常量随构建打入,可能滞后于发布标签(官方 API 文档也明确提示"deployed builds may differ")。 结论:判断真实版本以下载来源的 Release 标签为准,/server-version只能作为参考;该差异不影响功能与 API 兼容性。
八、首次登录与立即改密
浏览器访问 http://<服务器IP>:8080(经反代后为你的 HTTPS 域名),默认凭据登录:
- 用户名:
admin - 密码:
admin123
登录页默认开启 CAPTCHA,输入验证码后进入控制面板。官方强烈建议首次登录后立即修改默认口令,本文以新建账号演示完整的"首登—改密—旧口令失效"闭环(管理员 admin 在本实验机已按同样流程改密为 q1w2e3r4)。
登录协议细节:客户端提交的密码是原始口令的 SHA3-512 小写十六进制摘要(服务端再以 BCrypt 落库)。这正是下文脚本对密码先做摘要再提交的原因——直接提交明文也能建号,但会与官方客户端的登录约定不兼容。
第一步:管理员创建测试账号 user2,初始口令 admin123:
# cc_chgpass.py —— 首登改密闭环实测
import hashlib
import json
from html.parser import HTMLParser
from urllib.parse import urlsplit
import requests
class CsrfParser(HTMLParser):
token = None
def handle_starttag(self, tag, attrs):
attrs = dict(attrs)
if tag == "input" and attrs.get("name") == "_csrf":
self.token = attrs.get("value")
base = "http://localhost:8080"
def sha3(raw):
return hashlib.sha3_512(raw.encode("utf-8")).hexdigest()
def login(user, pwd):
s = requests.Session()
p = CsrfParser()
p.feed(s.get(base + "/login", timeout=15).text)
r = s.post(base + "/login", data={"username": user, "password": sha3(pwd), "_csrf": p.token},
allow_redirects=False, timeout=15)
print(f"login {user} -> {r.status_code} {r.headers.get('Location', '')}")
assert r.status_code == 302 and urlsplit(r.headers.get("Location", "")).path == "/"
return s
admin = login("admin", "q1w2e3r4")
csrf = admin.get(base + "/csrf-token", timeout=15).json()
admin.headers[csrf["headerName"]] = csrf["token"]
r = admin.post(base + "/admin/register-user",
json={"username": "user2", "password": sha3("admin123"), "role": "USER", "enabled": True},
timeout=15)
print("create user2:", r.status_code, r.text)
实测回显:
login admin -> 302 http://localhost:8080/
create user2: 200 User registered successfully
第二步:user2 用初始口令登录并改密为 q1w2e3r4:
u2 = login("user2", "admin123")
print("whoami:", json.dumps(u2.get(base + "/whoami", timeout=15).json()))
csrf2 = u2.get(base + "/csrf-token", timeout=15).json()
u2.headers[csrf2["headerName"]] = csrf2["token"]
r = u2.put(base + "/update-password", json={"newPassword": sha3("q1w2e3r4")}, timeout=15)
print("PUT /update-password ->", r.status_code, r.text)
实测回显:
login user2 -> 302 http://localhost:8080/
whoami: {"role": "USER", "username": "user2"}
PUT /update-password -> 200 Password updated successfully
第三步:验证旧口令立即失效、新口令可登录:
s = requests.Session()
p = CsrfParser()
p.feed(s.get(base + "/login", timeout=15).text)
r = s.post(base + "/login", data={"username": "user2", "password": sha3("admin123"), "_csrf": p.token},
allow_redirects=False, timeout=15)
print("old pwd login ->", r.status_code, r.headers.get("Location", ""))
login("user2", "q1w2e3r4")
实测回显:
old pwd login -> 302 http://localhost:8080/login?error
login user2 -> 302 http://localhost:8080/
re-login with new password ok
改密即时生效,无需重启服务;被修改账号的既有会话与 WebSocket 连接会被服务端自动吊销。
创建正式用户的两种方式:一是管理面板 Users 页面点 Add User(填用户名/初始口令/角色);二是上文所示 POST /admin/register-user API。重复创建同名账号会失败:
POST /admin/register-user -> 400 User already exists or invalid user
另外,CC_SIGNUP_ENABLED=false 时自助注册页被整体关闭:访问 /signup 会直接 302 跳回首页(实测回显:signup redirect -> http://127.0.0.1:8080/)。
九、nginx 反向代理(HTTPS + WebSocket)
生产环境建议统一走 HTTPS 域名入口。ClipCascade 有两个 WebSocket 握手端点(P2S 的 /clipsocket 与 P2P 的 /p2psignaling),反代必须为它们配置 HTTP/1.1 升级头,否则客户端能登录但剪贴板不流动。
server {
listen 80;
server_name _;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name _;
ssl_certificate /etc/nginx/ssl/clipcascade.crt;
ssl_certificate_key /etc/nginx/ssl/clipcascade.key;
ssl_protocols TLSv1.2 TLSv1.3;
client_max_body_size 128m;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /clipsocket {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
location /p2psignaling {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}
三个容易踩的坑:
client_max_body_size:nginx 默认 1MiB,会先于服务端拦下超限的图片/文件消息,需与CC_MAX_MESSAGE_SIZE_IN_MiB联动放大(上文取 128m)。proxy_read_timeout:长连接心跳间隔约 20 秒,默认 60 秒读超时会让空闲连接频繁重建,建议 3600s 起。- 通配证书:若走 Cloudflare Tunnel 等隧道,WebSocket 同样开箱即用,无需额外配置(官方 README 确认)。
十、客户端接入(Linux 侧速览)
各平台客户端在官方 Releases 页下载:Windows MSI、macOS 双架构 ZIP、Android APK;Linux 提供源码包 ClipCascade_Linux.zip(含 GUI 托盘与终端 CLI 双形态)。客户端登录时填服务器地址与端口,端到端加密默认开启——所有设备保持一致的加密开关、盐值与迭代数(默认迭代 664937、盐为空)。
Linux 客户端依赖安装中有一个著名的命名空间坑:发行版仓库装的 python3-pycryptodomex 提供的是 Cryptodome 命名空间,而客户端代码 import Crypto,首次启动会报 ModuleNotFoundError: No module named 'Crypto'。修复办法是为它建一个软链接(完整排障过程见 《ClipCascade 常用 CLI 命令详解》排障实录一节):
ln -s /usr/lib/python3/dist-packages/Cryptodome /usr/lib/python3/dist-packages/Crypto
启动参数(--gui、--xmode、--polling)与日常使用命令同样在 CLI 篇展开。若还需要文件级多机同步,可搭配 《Ubuntu 22.04 安装 Syncthing 指南》。
十一、升级与回滚
- 停服:
systemctl stop clipcascade; - 备份当前 JAR 与数据:
cp /opt/clipcascade/ClipCascade-Server-JRE_21.jar{,.bak}与cp -a /var/lib/clipcascade/database /var/lib/clipcascade/database.bak; - 下载新版本 JAR 覆盖
/opt/clipcascade/; systemctl start clipcascade后看journalctl -u clipcascade -f与/health;- 回滚即恢复
.bak文件重启。数据库加密口令(CC_SERVER_DB_PASSWORD)在版本间保持不变,勿在升级时顺手修改。
十二、卸载
systemctl disable --now clipcascade
rm /etc/systemd/system/clipcascade.service && systemctl daemon-reload
rm -rf /opt/clipcascade /etc/clipcascade /var/lib/clipcascade
userdel clipcascade
数据目录删除前如需留档,先打包 /var/lib/clipcascade/database。
十三、排障速查
| 现象 | 诊断 | 处置 |
|---|---|---|
systemctl start 后 /health 不通 | journalctl -u clipcascade -n 50 看是否 Java 版本低于 21 | 安装 openjdk-21-jre-headless |
改了 clipcascade.env 不生效 | 环境变量在进程启动时读取 | systemctl restart clipcascade 后复查 |
| 8080 被其他进程占用 | `ss -ltnp | grep 8080` |
登录一直 302 /login?error | 口令错误或 BFA 锁定 | 查 /admin/bfa-snapshot(管理员),确认锁定时间;默认单 IP 失败 30 次锁 60 秒 |
| 能登录但剪贴板不同步 | 反代未放行 WebSocket 升级 | 检查 /clipsocket 的 Upgrade/Connection 头与 proxy_read_timeout |
| 大图片/文件发送失败 | nginx 或服务端任一处限值过小 | 调大 client_max_body_size 与 CC_MAX_MESSAGE_SIZE_IN_MiB |
更多日常运维命令与客户端 CLI,见 《ClipCascade 常用 CLI 命令详解》。