文档

手动部署 Desk

在 Ubuntu 以外的发行版上,或想自己完成全部设置时,可以按 Ubuntu 部署脚本执行的步骤操作。需要先把 Node.js 26.12.1 或更高版本安装为 /usr/bin/node。开始前请先阅读所有部署方式的共同要求。

1. 用户和目录

Bash
sudo useradd --system --home /opt/desk --shell /usr/sbin/nologin desk
sudo mkdir -p /opt/desk /var/lib/desk/data/{public,private} /etc/desk
sudo chown -R desk: /opt/desk /var/lib/desk

2. 应用

Bash
sudo -u desk git clone https://github.com/modelriver/desk.git /opt/desk
cd /opt/desk && sudo -u desk sh -c 'npm ci && npm run build'

3. 设置

Bash
sudo cp deploy/env.example /etc/desk/env && sudo chmod 600 /etc/desk/env
sudoedit /etc/desk/env

至少设置:

变量值
MODELRIVER_API_KEY你的项目 API 密钥
DATA_DIR/var/lib/desk/data
DATABASE_PATH/var/lib/desk/desk.db
NODE_ENVproduction
DESK_SECRET_KEYopenssl rand -base64 32 的输出
DESK_IDENTITY_SECRETopenssl rand -base64 48 的输出
APP_URLDesk 的地址,如 https://support.acme.com
TRUST_PROXY_HOPSDesk 前面的代理层数:只有 nginx 时为 1

4. 第一位管理员

Bash
sudo /opt/desk/deploy/create-admin.sh

5. 服务

Bash
sudo cp deploy/desk.service /etc/systemd/system/
sudo systemctl daemon-reload && sudo systemctl enable --now desk

Desk 监听 127.0.0.1:3000。

6. HTTPS

在前面放置 nginx 或 Caddy 提供 HTTPS,并转发到 127.0.0.1:3000。使用 Caddy 时,完整配置只有:

support.acme.com {
reverse_proxy 127.0.0.1:3000
}

TRUST_PROXY_HOPS 必须等于会追加 X-Forwarded-For 的代理层数(nginx 前面再加 Cloudflare 时为 2),这样限流才能识别真实的访客地址。如果你的代理把地址放在专门的请求头里,改为把 CLIENT_IP_HEADER 设为该请求头,例如 cf-connecting-ip。

设置邮件

推荐设置。提交和回复工单、账户查询的邮箱验证以及团队通知都需要邮件(没有邮件会怎样)。可使用 Resend、Postmark 或 Amazon SES,EMAIL_FROM 需使用邮件服务已验证的域名,SUPPORT_REPLY_TO 设为团队会查看的邮箱。

用 sudoedit /etc/desk/env 把设置添加到 /etc/desk/env:

Bash
EMAIL_PROVIDER=resend
RESEND_API_KEY=re_…
EMAIL_FROM="Acme Support <[email protected]>"
SUPPORT_REPLY_TO=support@acme.com

然后重启:sudo systemctl restart desk。

然后在 后台 → 设置 → Send a test email(发送测试邮件) 中检查。

日常运维

  • 日志: journalctl -u desk -f。
  • 修改设置: sudoedit /etc/desk/env,然后 sudo systemctl restart desk。
  • 备份: /var/lib/desk。
  • 更新:
Bash
cd /opt/desk
sudo -u desk sh -c 'git pull && npm ci && npm run build'
sudo systemctl restart desk

数据目录可以放在单独的仓库中,但不要提交 /etc/desk/env:其中有你的 API 密钥和其他密钥。