本文以 Ubuntu 24.04、systemd、Nginx 和单台服务器为标准生产环境。
项目同时运行定时调度器和 HTTP 回调服务,因此生产环境只能启动一个
lark-push 进程。不要使用 Gunicorn 多 worker,也不要在多台服务器上同时
启动 scheduler,否则同一任务可能被重复发送。
- 代码:
/opt/lark-push - Python 虚拟环境:
/opt/lark-push/.venv - 密钥配置:
/etc/lark-push/lark-push.env - 运行状态:
/var/lib/lark-push/state.json - 后台渠道配置:
/var/lib/lark-push/managed_recipients.json - 服务账户:
lark-push - 应用监听:
127.0.0.1:3000 - 公网入口:Nginx HTTPS
生产环境推荐设置 LARK_ADMIN_READ_ONLY=true。任务变更通过功能分支、
Pull Request 和部署完成,避免管理页直接修改仓库文件导致服务器工作树变脏。
- Ubuntu 24.04 或提供 Python 3.12 以上版本的兼容 Debian 系统
- Python 3.12 以上
- 一个指向服务器的域名,例如
lark-push.example.com - 服务器可以访问 GitHub、PyPI、飞书开放平台和 ZenMux API
- GitHub 仓库
tenlywu/lark-push的只读 Deploy Key - 飞书应用 ID、Secret、接收者 ID 和回调配置
安装系统依赖:
sudo apt update
sudo apt install -y git python3 python3-venv nginx certbot python3-certbot-nginx创建服务账户和目录:
sudo useradd \
--system \
--create-home \
--home-dir /var/lib/lark-push \
--shell /usr/sbin/nologin \
lark-push
sudo install -d -o lark-push -g lark-push -m 0750 /opt/lark-push
sudo install -d -o root -g lark-push -m 0750 /etc/lark-push
sudo install -d -o lark-push -g lark-push -m 0750 /var/lib/lark-push生成专用于该仓库的 SSH Key:
sudo -u lark-push install -d -m 0700 /var/lib/lark-push/.ssh
sudo -u lark-push ssh-keygen \
-t ed25519 \
-N '' \
-C 'lark-push production deploy key' \
-f /var/lib/lark-push/.ssh/id_ed25519
sudo -u lark-push ssh-keyscan github.com \
| sudo -u lark-push tee /var/lib/lark-push/.ssh/known_hosts >/dev/null
sudo -u lark-push chmod 0600 /var/lib/lark-push/.ssh/known_hosts
sudo cat /var/lib/lark-push/.ssh/id_ed25519.pub将公钥添加到 GitHub 仓库:
Settings -> Deploy keys -> Add deploy key
只需要读取权限,不要勾选写权限。验证连接:
sudo -u lark-push ssh -T git@github.comGitHub 会返回认证成功但不提供 shell,这是正常结果。
克隆代码并安装依赖:
sudo -u lark-push git clone \
git@github.com:tenlywu/lark-push.git \
/opt/lark-push
sudo -u lark-push python3 -m venv /opt/lark-push/.venv
sudo -u lark-push /opt/lark-push/.venv/bin/python -m pip install --upgrade pip
sudo -u lark-push /opt/lark-push/.venv/bin/python -m pip install \
-r /opt/lark-push/requirements.txt创建生产配置:
sudo install \
-o root \
-g lark-push \
-m 0640 \
/opt/lark-push/.env.example \
/etc/lark-push/lark-push.env
sudo editor /etc/lark-push/lark-push.env生产环境至少需要调整以下内容:
LARK_APP_ID='cli_xxx'
LARK_APP_SECRET='xxx'
LARK_RECIPIENTS_JSON='{"personal":{"receive_id_type":"open_id","receive_id":"ou_xxx","label":"Personal"},"group":{"receive_id_type":"chat_id","receive_id":"oc_xxx","label":"Group"}}'
LARK_ADMIN_PASSWORD='replace-with-a-strong-password'
LARK_ADMIN_SESSION_SECRET='replace-with-a-random-secret'
ZENMUX_MANAGEMENT_API_KEY='xxx'
LARK_CALLBACK_HOST=127.0.0.1
LARK_CALLBACK_PORT=3000
LARK_HTTP_TIMEOUT_SECONDS=15
LARK_REPORT_TIMEZONE=Asia/Shanghai
LARK_WEB_THREADS=8
LARK_ADMIN_READ_ONLY=true
LARK_SESSION_COOKIE_SECURE=true
LARK_TASKS_DIR=/opt/lark-push/tasks
LARK_STATE_FILE=/var/lib/lark-push/state.json
LARK_MANAGED_RECIPIENTS_FILE=/var/lib/lark-push/managed_recipients.json可通过以下命令生成 session secret:
openssl rand -hex 32配置文件不得提交到 Git,也不要复制到工单或聊天记录。
使用真实生产配置做只读校验。该命令不会启动 scheduler,也不会发送消息:
sudo -u lark-push bash -c '
set -a
source /etc/lark-push/lark-push.env
set +a
exec /opt/lark-push/.venv/bin/python -m lark_push.check_config
'成功时会输出任务数、启用任务数和渠道数,不会输出任何密钥。
统一验证脚本使用测试凭据、临时运行目录和全部禁用的任务副本,不会调用真实 飞书发送接口,也不会修改生产状态:
cd /opt/lark-push
sudo -u lark-push env \
PYTHON_BIN=/opt/lark-push/.venv/bin/python \
bash scripts/verify.sh成功标志:
service smoke: ok
verification: ok
任何一步失败都不要启动或重启生产服务。
sudo install \
-o root \
-g root \
-m 0644 \
/opt/lark-push/deploy/systemd/lark-push.service \
/etc/systemd/system/lark-push.service
sudo systemctl daemon-reload
sudo systemctl enable --now lark-push
sudo systemctl status lark-push --no-pager检查本机健康状态:
curl --fail --silent http://127.0.0.1:3000/healthz | python3 -m json.tool查看日志:
sudo journalctl -u lark-push -n 200 --no-pager
sudo journalctl -u lark-push -f首次启动会根据任务状态执行 bootstrap。启用中的任务如果没有现存状态,可能 立即发送卡片,因此必须先确认任务配置、接收者和生产环境变量正确。
先复制模板并替换域名:
sudo cp \
/opt/lark-push/deploy/nginx/lark-push.conf \
/etc/nginx/sites-available/lark-push.conf
sudo sed -i \
's/lark-push.example.com/你的实际域名/g' \
/etc/nginx/sites-available/lark-push.conf
sudo ln -s \
/etc/nginx/sites-available/lark-push.conf \
/etc/nginx/sites-enabled/lark-push.conf
sudo nginx -t
sudo systemctl reload nginx
sudo certbot --nginx -d 你的实际域名
sudo nginx -t
sudo systemctl reload nginx公网验证:
curl --fail --silent https://你的实际域名/healthz | python3 -m json.tool
curl --fail --silent \
-H 'Content-Type: application/json' \
-d '{"challenge":"deploy-check"}' \
https://你的实际域名/feishu/callback在飞书开放平台将回调地址配置为:
https://你的实际域名/feishu/callback
/admin 应仅允许可信网络访问。推荐通过 VPN、Nginx IP allowlist 或额外的
SSO/访问网关限制入口,不应只依赖应用密码暴露在公网。
记录当前版本并备份运行状态:
cd /opt/lark-push
sudo -u lark-push git status --short
sudo -u lark-push git rev-parse HEAD
sudo install -d -o root -g lark-push -m 0750 /var/backups/lark-push
sudo tar -C /var/lib \
-czf "/var/backups/lark-push/lark-push-$(date +%Y%m%d-%H%M%S).tar.gz" \
lark-push工作树必须为空。然后拉取、安装和验证:
sudo -u lark-push git -C /opt/lark-push pull --ff-only
sudo -u lark-push /opt/lark-push/.venv/bin/python -m pip install \
-r /opt/lark-push/requirements.txt
cd /opt/lark-push
sudo -u lark-push env \
PYTHON_BIN=/opt/lark-push/.venv/bin/python \
bash scripts/verify.sh验证成功后重启:
sudo systemctl restart lark-push
sudo systemctl status lark-push --no-pager
curl --fail --silent http://127.0.0.1:3000/healthz | python3 -m json.tool
sudo journalctl -u lark-push -n 100 --no-pager切换到升级前记录的提交:
sudo systemctl stop lark-push
sudo -u lark-push git -C /opt/lark-push switch --detach 升级前提交SHA
sudo -u lark-push /opt/lark-push/.venv/bin/python -m pip install \
-r /opt/lark-push/requirements.txt
sudo systemctl start lark-push如果需要恢复运行状态:
sudo systemctl stop lark-push
sudo tar -C /var/lib -xzf /var/backups/lark-push/对应备份文件.tar.gz
sudo chown -R lark-push:lark-push /var/lib/lark-push
sudo systemctl start lark-push恢复到主分支:
sudo -u lark-push git -C /opt/lark-push switch mainsudo systemctl status lark-push --no-pager
sudo journalctl -u lark-push -n 200 --no-pager
sudo -u lark-push test -r /etc/lark-push/lark-push.env重点检查必填环境变量、JSON 格式、任务引用的渠道以及运行目录权限。
- 检查任务
enabled。 - 检查任务
channel.target_refs是否存在于渠道配置。 - 查看
state.json中是否已有活动消息。 - 检查飞书应用权限和应用可见范围。
- 查看 ZenMux API Key 是否有效。
- 查看 systemd 日志中的 Lark API 错误。
立即检查是否有多个实例:
pgrep -af 'python.*-m lark_push'
systemctl status lark-push生产环境只能运行一个实例。不要同时保留手工启动进程、多个 systemd unit、 容器副本或 Gunicorn workers。
生产默认 LARK_ADMIN_READ_ONLY=true,这是预期行为。任务应在 Git 分支中修改
并通过正常发布流程部署。若临时允许管理页写入,会直接修改仓库中的 tasks/
文件并造成工作树变脏,不推荐在生产使用。
停止服务,备份损坏文件,再从最近备份恢复。直接删除 state.json 会导致服务
认为没有活动消息,下一次启动可能重新发送所有启用任务。
/etc/lark-push/lark-push.env权限保持0640 root:lark-push。- Deploy Key 保持只读。
- 定期轮换飞书 Secret、ZenMux Key、管理密码和 session secret。
- 定期备份
/var/lib/lark-push,并测试恢复流程。 - 仅通过 HTTPS 暴露回调与管理页面。
- 升级必须使用
git pull --ff-only,禁止服务器上直接开发或强制覆盖工作树。