Ubuntu 22.04 安装 Leantime 3.12.0 指南

在 Ubuntu 22.04 上用 apt 安装 Nginx、MariaDB 10.6 与 PHP 8.2.35,源码包部署 Leantime 3.12.0,涵盖权限、.env、Nginx/TLS 反代、systemd 定时任务与初始化向导全流程实测。

LeantimeLeantime项目管理PHPMySQL自动化运维2026/10/27

Ubuntu 22.04 安装 Leantime 3.12.0 指南

目标:在一台干净的 Ubuntu 22.04 LTS 服务器上,用 apt 安装 Nginx、MariaDB 与 PHP 8.2,部署 Leantime 3.12.0 官方发布包,完成权限、数据库、.env、Nginx 站点、systemd 定时任务与初始化向导,最终可从浏览器登录使用。本文所有命令与回显均在 Ubuntu 22.04.5 LTS(内网地址 10.89.61.10)实测通过。

一、环境信息

本机实测环境如下。Leantime 对 PHP 与数据库版本有硬性要求,版本不达标会在安装向导或页面渲染阶段直接报错,因此先列清楚版本基线。

  • 操作系统:Ubuntu 22.04.5 LTS(x86_64)
  • 服务器地址:10.89.61.10(示例,实际请替换为你的服务器 IP 或域名)
  • Web 服务:Nginx 1.18.0(Ubuntu 源)
  • 应用运行时:PHP 8.2.35(Ondřej Surý PPA,FPM + CLI)
  • 数据库:MariaDB 10.6.23(Ubuntu 22.04 官方源)
  • Leantime:v3.12.0(GitHub Releases 发布包,2026-10-15 构建)
  • 应用框架:Laravel 11.45.1(随发布包内置)
  • 安装目录:/opt/leantime
  • Web 文档根:/opt/leantime/public
  • 监听端口:80(HTTP)、8443(示例 TLS 反向代理)
  • 数据库名/账号:leantime / leantime
  • 实测日期:2026-10-27

版本核实依据:GitHub Releases 的 latest 为 v3.12.0,发布于 2026-10-15T23:11:05Z,资产包含 Leantime-v3.12.0.zip 与 Leantime-v3.12.0.tar.gz。

二、前置条件

开始前确认服务器满足以下条件,任何一项不满足都应在安装阶段先补齐。

  1. 一台可 SSH 登录的 Ubuntu 22.04 服务器,具备 root 或 sudo 权限,磁盘至少 2GB 可用(发布包解压后约 400MB,附件与备份另算)。
  2. 服务器可访问 Ubuntu 官方软件源与 ppa.launchpadcontent.net(安装 PHP 8.2 需要添加 Ondřej PPA)。
  3. 80/443 端口未被其他 Web 服务占用。检查方式:
ss -ltn | grep -E ':80 |:443 '

实测无输出表示端口空闲。若已有 Apache 或其它 Nginx 实例占用,请先停止:

systemctl stop apache2
systemctl disable apache2
  1. 规划好访问地址。本文用 http://10.89.61.10 作为示例;生产环境建议使用域名并配置 TLS,后文第七节给出反向代理写法。
  2. 记录好数据库密码。本文演示用 q1w2e3r4,生产环境请替换为强密码并妥善保存。

⚠️ 注意:Leantime 3.12.0 要求 PHP 8.2+、MySQL 8.0+ 或 MariaDB 10.6+。Ubuntu 22.04 自带 PHP 8.1,不满足要求,必须通过 Ondřej PPA 安装 8.2。

三、版本选型说明

Leantime 的版本号分三段:主版本(3)、次版本(12)、补丁(0)。从官方发布节奏可以看到当前版本迭代情况:

版本发布时间(官方发布)类型建议
3.12.02026-10-21当前最新稳定版新部署首选
3.11.02026-10-09功能版保守团队可用
3.10.42026-10-05补丁版仅用于修复已知问题
3.10.02026-09-24功能版不建议新装

选型建议:

  • 新部署一律选 3.12.0,它是当前最新稳定版,社区问题修复最全。
  • 若已有 3.10.x 实例,先看 3.11/3.12 的 Release Notes 是否涉及数据库结构变更,再决定升级窗口;升级步骤见第十二节。
  • 不要混用「GitHub 发布包」与其它分发渠道的版本号:发布包内置的 vendor/ 依赖已锁定,升级时必须整包替换,不能只覆盖部分目录。

💡 技术拓展:PHP 应用获取运行时的三种常见来源——

来源命令/方式版本上限适用场景
发行版官方源apt install php8.1-fpm固定(22.04 为 8.1)只要求发行版生命周期内稳定
第三方 PPAadd-apt-repository ppa:ondrej/php可拿到 8.2/8.3/8.4需要新版语言特性,Ubuntu 上最常见
源码编译./configure && make任意需要自定义扩展或极端版本

本文因 Leantime 要求 PHP 8.2+ 而 Ubuntu 22.04 官方源只有 8.1,采用第二种「Ondřej PPA」,兼顾版本与后续安全更新。

四、基础环境安装

本节完成 Nginx、MariaDB、PHP 8.2 及 Leantime 所需扩展的安装。先更新索引,再装基础工具,最后添加 PHP PPA。

4.1 更新软件索引并安装基础工具

apt-get update
DEBIAN_FRONTEND=noninteractive apt-get install -y software-properties-common ca-certificates curl unzip gnupg2

实测回显(输出节选):

Get:6 http://archive.ubuntu.com/ubuntu jammy-updates/universe amd64 Packages [1628 kB]
Get:7 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 Packages [4759 kB]
Get:8 http://security.ubuntu.com/ubuntu jammy-security/universe amd64 Packages [1325 kB]
Fetched 12.5 MB in 15s (820 kB/s)
Reading package lists...

4.2 添加 PHP 8.2 软件源

add-apt-repository -y ppa:ondrej/php
apt-get update

实测回显:

Adding repository.
Adding deb entry to /etc/apt/sources.list.d/ondrej-ubuntu-php-jammy.list
Adding disabled deb-src entry to /etc/apt/sources.list.d/ondrej-ubuntu-php-jammy.list
Adding key to /etc/apt/trusted.gpg.d/ondrej-ubuntu-php.gpg with fingerprint B8DC7E53946656EFBCE4C1DD71DAEAAB4AD4CAB6

确认候选版本:

apt-cache policy php8.2-fpm mariadb-server

实测回显:

php8.2-fpm:
  Installed: (none)
  Candidate: 8.2.35-1+ubuntu22.04.1+deb.sury.org+1
  Version table:
mariadb-server:
  Installed: (none)
  Candidate: 1:10.6.23-0ubuntu0.22.04.1
  Version table:

PHP 8.2.35 与 MariaDB 10.6.23 均满足 Leantime 的最低要求。

4.3 安装 Nginx、MariaDB 与 PHP 扩展

DEBIAN_FRONTEND=noninteractive apt-get install -y \
  nginx mariadb-server \
  php8.2-fpm php8.2-cli php8.2-mysql php8.2-mbstring php8.2-xml \
  php8.2-curl php8.2-gd php8.2-zip php8.2-bcmath php8.2-ldap \
  php8.2-intl php8.2-opcache

安装完成后校验版本:

php -v
nginx -v
mariadb --version

实测回显:

PHP 8.2.35 (cli) (built: Oct 21 2026 14:29:22) (NTS)
Copyright (c) The PHP Group
nginx version: nginx/1.18.0 (Ubuntu)
mariadb  Ver 15.1 Distrib 10.6.23-MariaDB, for debian-linux-gnu (x86_64) using  EditLine wrapper

校验 Leantime 需要的 PHP 扩展是否齐全:

php -m

实测回显(节选):

[PHP Modules]
bcmath calendar Core ctype curl date dom exif FFI fileinfo filter ftp gd gettext
hash iconv intl json ldap libxml mbstring mysqli mysqlnd openssl pcntl pcre PDO
pdo_mysql Phar posix random readline Reflection session shmop SimpleXML sockets
sodium SPL standard sysvmsg sysvsem sysvshm tokenizer xml xmlreader xmlwriter xsl
Zend OPcache zip zlib

对照官方依赖清单声明的扩展,bcmath、ctype、curl、dom、exif、fileinfo、ldap、mbstring、mysqli、openssl、pcntl、pdo_mysql、posix、simplexml、tokenizer、zip 全部存在,可以继续。

启动并设置开机自启:

systemctl enable --now mariadb nginx php8.2-fpm
systemctl is-enabled mariadb nginx php8.2-fpm

实测回显:

enabled
enabled
enabled

五、下载与解压 Leantime 发布包

本节给出官方两种包格式的下载方式:.zip(方案 A,主用)与 .tar.gz(方案 B,备用)。两者内容一致,选择一种即可。

5.1 方案 A:下载 zip 发布包

mkdir -p /opt/src
cd /opt/src
curl -L -o Leantime-v3.12.0.zip \
  https://github.com/Leantime/leantime/releases/download/v3.12.0/Leantime-v3.12.0.zip

⚠️ 网络说明:直连 GitHub Releases 当时速度约 25KB/s,5 分钟仅下载 7MB 后超时;改用内网代理 192.168.1.62:7897 后 5 秒完成。若你的服务器直连 GitHub 正常,可去掉 -x 参数;若持续失败,请改用可达的下载源或代理渠道,并核对 SHA256。

走代理的实测命令与回显:

curl -x http://192.168.1.62:7897 -L --max-time 300 \
  -o Leantime-v3.12.0.zip \
  https://github.com/Leantime/leantime/releases/download/v3.12.0/Leantime-v3.12.0.zip
ls -lh Leantime-v3.12.0.zip
100  119M  100  119M    0     0  23.0M      0  0:00:05  0:00:05 --:--:-- 29.6M
-rw-r--r-- 1 root root 120M Oct 27 15:05 Leantime-v3.12.0.zip

校验摘要:

sha256sum Leantime-v3.12.0.zip

实测回显:

86891cbee284c00a9716bc9c92cb72f070270a36db89255bafbb17b29ea58ce4  Leantime-v3.12.0.zip

5.2 方案 B:下载 tar.gz 发布包

cd /opt/src
curl -x http://192.168.1.62:7897 -L --max-time 120 \
  -o Leantime-v3.12.0.tar.gz \
  https://github.com/Leantime/leantime/releases/download/v3.12.0/Leantime-v3.12.0.tar.gz
sha256sum Leantime-v3.12.0.tar.gz
tar -tzf Leantime-v3.12.0.tar.gz | head -8

实测回显:

d9e93be5d98131e402efe8802b941c1ba1431ac117d26780aa7a65206aa873a2  Leantime-v3.12.0.tar.gz
./
./userfiles/
./userfiles/.gitkeep
./vendor/
./vendor/litesaml/
./vendor/litesaml/lightsaml/
./vendor/litesaml/lightsaml/src/
./vendor/litesaml/lightsaml/src/State/

5.3 解压到安装目录

zip 方案:

mkdir -p /opt/leantime
unzip -q Leantime-v3.12.0.zip -d /opt/leantime
ls /opt/leantime

tar.gz 方案(与 zip 二选一):

mkdir -p /opt/leantime
tar -xzf Leantime-v3.12.0.tar.gz -C /opt/leantime
ls /opt/leantime

实测回显:

app  bin  bootstrap  config  public  storage  userfiles  vendor

目录职责速查:

目录职责权限要求
public/唯一 Web 入口与前端资源Web 用户可读,文档根必须指向这里
config/.env 运行配置Web 用户可读;.env 建议 640
storage/日志、缓存、会话、上传Web 用户可写
userfiles/用户上传文件(本地存储模式)Web 用户可写
app/Plugins/插件目录Web 用户可写,否则插件会被清理
vendor/PHP 依赖包(含 Laravel 框架)只读,升级时整包替换

六、数据库与 .env 配置

6.1 创建数据库与专用账号

mysql <<'SQL'
CREATE DATABASE IF NOT EXISTS leantime CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS "leantime"@"localhost" IDENTIFIED BY "q1w2e3r4";
GRANT ALL PRIVILEGES ON leantime.* TO "leantime"@"localhost";
FLUSH PRIVILEGES;
SQL

验证:

mysql -e 'SHOW DATABASES LIKE "leantime"; SELECT user,host FROM mysql.user WHERE user="leantime";'

实测回显:

Database (leantime)
leantime
User	Host
leantime	localhost

字符集必须用 utf8mb4,否则中文项目名、任务描述、Wiki 内容会出现截断或乱码。

6.2 生成 .env 并填写数据库连接

cd /opt/leantime
cp config/sample.env config/.env

编辑 config/.env,至少修改以下 5 项(其余保持默认):

LEAN_APP_URL = 'http://10.89.61.10'
LEAN_DB_HOST = 'localhost'
LEAN_DB_USER = 'leantime'
LEAN_DB_PASSWORD = 'q1w2e3r4'
LEAN_DB_DATABASE = 'leantime'
LEAN_SESSION_PASSWORD = 'K7pQ2mX9vR4tL8wZ3nC6bF1hJ5sD0gY2'

逐项说明:

  • LEAN_APP_URL:应用对外基地址。邮件中的链接、跳转都依赖它;填错会导致密码重置链接指向错误域名。生产环境必须是 https:// 域名。
  • LEAN_DB_HOST:数据库地址,同机部署填 localhost 走本地连接。
  • LEAN_DB_USER / LEAN_DB_PASSWORD / LEAN_DB_DATABASE:与 6.1 创建的账号、库名一致。
  • LEAN_SESSION_PASSWORD:会话签名盐,必须替换为随机长字符串;泄露会导致会话可被伪造。可用 openssl rand -base64 32 生成。

修改后校验:

grep -nE '^LEAN_(APP_URL|DB_HOST|DB_USER|DB_PASSWORD|DB_DATABASE|SESSION_PASSWORD)' config/.env

实测回显:

6:LEAN_APP_URL = 'http://10.89.61.10'
17:LEAN_DB_HOST = 'localhost'                         # Database host
18:LEAN_DB_USER = 'leantime'
19:LEAN_DB_PASSWORD = 'q1w2e3r4'
20:LEAN_DB_DATABASE = 'leantime'
38:LEAN_SESSION_PASSWORD = 'K7pQ2mX9vR4tL8wZ3nC6bF1hJ5sD0gY2'

⚠️ 注意:config/sample.env 中 LEAN_APP_URL 默认为空,不填会导致安装向导生成的跳转使用请求 Host,反向代理场景下容易产生 http/https 混合内容。生产环境一定显式填写。

七、Nginx 站点与 PHP-FPM 配置

7.1 写入站点配置

cat > /etc/nginx/sites-available/leantime.conf <<'CONF'
server {
    listen 80;
    server_name 10.89.61.10 b1.leantime.local;
    root /opt/leantime/public;
    index index.php index.html;
    client_max_body_size 50m;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}
CONF
ln -sf /etc/nginx/sites-available/leantime.conf /etc/nginx/sites-enabled/leantime.conf
rm -f /etc/nginx/sites-enabled/default
nginx -t

实测回显:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

配置项说明:

  • root /opt/leantime/public:必须指向 public/,指向包根目录会暴露 .env 与 storage/。
  • try_files $uri $uri/ /index.php?$query_string:Leantime 使用前端控制器路由,所有非静态请求交给 index.php。
  • client_max_body_size 50m:附件上传上限,需与 PHP 的 upload_max_filesize、post_max_size 保持一致,否则大文件会被 Nginx 直接 413。
  • location ~ /\.(?!well-known).*:拒绝访问 .env、.git 等隐藏文件。
  • fastcgi_pass unix:/run/php/php8.2-fpm.sock:Ubuntu 的 PHP-FPM 默认 socket 路径,若自定义过 pool 请同步修改。

7.2 重载服务并验证首页

systemctl restart nginx php8.2-fpm
systemctl is-active nginx php8.2-fpm
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/auth/login

实测回显:

active
active
302
200

302 是未安装/未登录时跳转到登录页的正常表现,200 表示登录页已正常渲染。

7.3 TLS 反向代理(可选)

生产环境通常在 Nginx 前置一层 443 TLS 终止,再反代到本机 80。下面用自签证书在 8443 端口验证配置可用;正式环境请把证书换成 CA 签发证书(如 certbot)。

mkdir -p /etc/nginx/ssl
openssl req -x509 -nodes -newkey rsa:2048 -days 365 \
  -subj "/CN=pm.example.com" \
  -keyout /etc/nginx/ssl/leantime.key \
  -out /etc/nginx/ssl/leantime.crt
cat > /etc/nginx/sites-available/leantime-tls.conf <<'CONF'
server {
    listen 8443 ssl;
    server_name pm.example.com;
    ssl_certificate     /etc/nginx/ssl/leantime.crt;
    ssl_certificate_key /etc/nginx/ssl/leantime.key;
    client_max_body_size 50m;

    location / {
        proxy_pass http://127.0.0.1:80;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Real-IP $remote_addr;
    }
}
CONF
ln -sf /etc/nginx/sites-available/leantime-tls.conf /etc/nginx/sites-enabled/leantime-tls.conf
nginx -t
systemctl reload nginx
curl -sk -o /dev/null -w '%{http_code}\n' https://127.0.0.1:8443/auth/login

实测回显:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
200

关键点:反代时必须传 X-Forwarded-Proto https,并把 LEAN_APP_URL 设为 https://pm.example.com,否则生成的链接会退回 http,浏览器报混合内容错误。

八、权限、目录与 systemd 定时任务

8.1 设置属主与权限

chown -R www-data:www-data /opt/leantime
chmod -R 755 /opt/leantime/storage /opt/leantime/userfiles /opt/leantime/public /opt/leantime/app/Plugins /opt/leantime/config
chmod 640 /opt/leantime/config/.env
ls -ld /opt/leantime /opt/leantime/public /opt/leantime/storage /opt/leantime/config /opt/leantime/config/.env /opt/leantime/app/Plugins

实测回显:

drwxr-xr-x 10 www-data www-data  4096 Oct 27 15:05 /opt/leantime
drwxr-xr-x  2 www-data www-data  4096 Oct 15 23:10 /opt/leantime/app/Plugins
drwxr-xr-x  2 www-data www-data  4096 Oct 27 15:07 /opt/leantime/config
-rw-r-----  1 www-data www-data 14143 Oct 27 15:07 /opt/leantime/config/.env
drwxr-xr-x  7 www-data www-data  4096 Oct 15 23:10 /opt/leantime/public
drwxr-xr-x  4 www-data www-data  4096 Oct 15 23:10 /opt/leantime/storage

要点:storage/、userfiles/、app/Plugins/ 必须对 www-data 可写,否则会出现「安装成功但上传失败」「插件重启后消失」「日志写不进去」三类问题。

8.2 用 systemd timer 托管计划任务

Leantime 的定时任务(通知、提醒、清理)依赖 schedule:run。用 systemd timer 托管比 crontab 更易观测。

cat > /etc/systemd/system/leantime-scheduler.service <<'UNIT'
[Unit]
Description=Leantime scheduled jobs (schedule:run)
After=network.target mariadb.service

[Service]
Type=oneshot
User=www-data
WorkingDirectory=/opt/leantime
ExecStart=/usr/bin/php /opt/leantime/bin/leantime schedule:run
UNIT
cat > /etc/systemd/system/leantime-scheduler.timer <<'UNIT'
[Unit]
Description=Run Leantime scheduler every minute

[Timer]
OnCalendar=*-*-* *:*:00
Persistent=true

[Install]
WantedBy=timers.target
UNIT
systemctl daemon-reload
systemctl enable --now leantime-scheduler.timer
systemctl list-timers leantime-scheduler.timer --no-pager

实测回显:

Created symlink /etc/systemd/system/timers.target.wants/leantime-scheduler.timer → /etc/systemd/system/leantime-scheduler.timer.
NEXT                        LEFT     LAST PASSED UNIT                     ACTIVATES
Tue 2026-10-27 15:12:00 UTC 10s left n/a  n/a    leantime-scheduler.timer leantime-scheduler.service

1 timers listed.

手动触发一次,确认命令能正常执行:

systemctl start leantime-scheduler.service
systemctl is-active leantime-scheduler.timer

实测回显:

active

💡 说明:若不想用 systemd timer,等价写法是 * * * * * www-data /usr/bin/php /opt/leantime/bin/leantime schedule:run,两者选其一即可,不要同时启用。

九、初始化向导与登录验证

9.1 进入安装向导

浏览器访问 http://10.89.61.10/install。向导要求填写邮箱、名、姓、公司四项,提交后自动建表并创建第一个管理员账号(用户 ID 为 1)。

用 curl 复现该请求(表单字段与页面一致):

curl -s -c /tmp/cj.txt -i -X POST http://127.0.0.1/install \
  --data 'install=Install&email=admin@example.com&firstname=Admin&lastname=User&company=Quzuo%20Demo'

实测回显(节选):

HTTP/1.1 303 See Other
Location: http://10.89.61.10/auth/userInvite/Obn4udJc4Ylh3crc65IxNXu2LJLLrzcw

303 并跳转到 auth/userInvite/<token> 表示建表与首个账号创建成功。

9.2 完成账号激活与首次登录

首次账号处于「待激活」状态,需要通过邀请链接完成 5 步引导:设置密码 → 选择主题 → 选择配色 → 设置工作时间 → 完成。

设置密码(Leantime 要求至少 8 位且包含大写、小写、数字、特殊字符,因此演示密码用 Admin@q1w2e3r4):

TOK=Obn4udJc4Ylh3crc65IxNXu2LJLLrzcw
curl -s -i -c /tmp/cj.txt -b /tmp/cj.txt -X POST "http://127.0.0.1/auth/userInvite/$TOK" \
  --data-urlencode 'step=1' --data-urlencode 'saveAccount=1' \
  --data-urlencode 'name=Admin User' --data-urlencode 'jobTitle=Administrator' \
  --data-urlencode 'password=Admin@q1w2e3r4'

实测回显:

HTTP/1.1 303 See Other
Location: http://10.89.61.10/auth/userInvite/Obn4udJc4Ylh3crc65IxNXu2LJLLrzcw?step=2

依次完成第 2 步(主题)、第 3 步(配色)、第 4 步(工作时间)、第 5 步(完成):

curl -s -i -c /tmp/cj.txt -b /tmp/cj.txt -X POST "http://127.0.0.1/auth/userInvite/$TOK?step=2" \
  --data 'step=2&theme=default&themeFont=Roboto'
curl -s -i -c /tmp/cj.txt -b /tmp/cj.txt -X POST "http://127.0.0.1/auth/userInvite/$TOK?step=3" \
  --data 'step=3&colormode=light&colorscheme=themeDefault'
curl -s -i -c /tmp/cj.txt -b /tmp/cj.txt -X POST "http://127.0.0.1/auth/userInvite/$TOK?step=4" \
  --data 'step=4&daySchedule-workStart=&daySchedule-lunch=&daySchedule-workEnd='
curl -s -i -c /tmp/cj.txt -b /tmp/cj.txt -X POST "http://127.0.0.1/auth/userInvite/$TOK?step=5" \
  --data 'step=5'

实测每一步都返回 303 并进入下一 step,最后一步回显:

HTTP/1.1 303 See Other
Location: http://10.89.61.10/dashboard/home

9.3 验证登录与仪表盘

用全新会话登录,确认账号密码可用:

rm -f /tmp/lg.txt
PAGE=$(curl -s -c /tmp/lg.txt http://127.0.0.1/auth/login)
TOK=$(echo "$PAGE" | grep -o 'name="_token" value="[^"]*"' | sed 's/.*value="//;s/"//')
curl -s -i -c /tmp/lg.txt -b /tmp/lg.txt -X POST http://127.0.0.1/auth/login \
  --data-urlencode "_token=$TOK" \
  --data-urlencode "username=admin@example.com" \
  --data-urlencode "password=Admin@q1w2e3r4" \
  --data-urlencode "login=Login"
curl -s -o /dev/null -w '%{http_code}\n' -b /tmp/lg.txt http://127.0.0.1/dashboard/home

实测回显(节选):

HTTP/1.1 303 See Other
Location: http://10.89.61.10/dashboard/home
200

页面内容校验:

curl -s -b /tmp/lg.txt http://127.0.0.1/dashboard/home | grep -c 'My Work'

实测回显:

2

9.4 检查数据库与健康接口

mysql -N -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='leantime';"
curl -s http://127.0.0.1/healthCheck.php

实测回显:

38
Ok

38 张表说明安装向导已完整执行建表脚本;healthCheck.php 返回 Ok 表示 PHP 能连数据库、应用引导正常。

查看应用自身版本信息:

php /opt/leantime/bin/leantime about

实测回显(节选):

  Laravel Version .................................................... 11.45.1
  PHP Version ......................................................... 8.2.35
  Environment ..................................................... production
  Debug Mode ............................................................. OFF
  URL ............................................................ 10.89.61.10
  Timezone ............................................... America/Los_Angeles
  Leantime App Version ................................................ 3.12.0
  Leantime Db Version ................................................. 3.5.30

注意 Timezone 默认是 America/Los_Angeles,国内团队应在 .env 中显式设置时区(配置项与改法见配置参数篇),否则任务到期提醒会按美国西海岸时间触发。

十、方案对比与选择建议

两种包格式的差异只在传输与解压,运行时完全一致:

维度方案 A:zip方案 B:tar.gz
官方资产名Leantime-v3.12.0.zipLeantime-v3.12.0.tar.gz
实测大小120MB113MB
解压命令unzip -q ... -d /opt/leantimetar -xzf ... -C /opt/leantime
权限保留zip 不保留 Unix 权限位,需重新 chown/chmodtar 保留权限位,但仍建议统一 chown
依赖需要 unzip系统自带 tar
适用场景默认推荐,Windows 中转也方便极简系统(无 unzip)、需保留权限位
实测 SHA25686891cbee284c00a9716bc9c92cb72f070270a36db89255bafbb17b29ea58ce4d9e93be5d98131e402efe8802b941c1ba1431ac117d26780aa7a65206aa873a2

选择建议:能联网且系统有 unzip 就选方案 A;内网离线传输、或目标系统不方便装 unzip 时选方案 B。两者的安装目录、权限、配置步骤完全相同,切换方案不需要改动后续章节。

十一、常见问题(FAQ)

Q1:访问首页返回 500,日志提示 could not find driver 怎么办?

这是缺少 pdo_mysql 扩展。检查:

php -m | grep -E 'pdo_mysql|mysqli'

若无输出,安装 php8.2-mysql 并重启 PHP-FPM:

apt-get install -y php8.2-mysql
systemctl restart php8.2-fpm

Q2:安装向导能打开,但提交后提示数据库连接失败。

按顺序排查:数据库服务是否运行、账号能否登录、库是否存在。

systemctl is-active mariadb
mysql -uleantime -pq1w2e3r4 -e 'SELECT 1;'
mysql -e 'SHOW DATABASES LIKE "leantime";'

常见原因是 .env 中密码含特殊字符未加引号,或 LEAN_DB_HOST 写成了公网 IP 但数据库只监听 127.0.0.1。

Q3:上传附件报 413 Request Entity Too Large。

Nginx 与 PHP 两侧都要放宽:

# Nginx server 块内
client_max_body_size 50m;

# /etc/php/8.2/fpm/php.ini
upload_max_filesize = 50M
post_max_size = 52M

改完执行 systemctl reload nginx && systemctl restart php8.2-fpm。

Q4:页面样式错乱、JS 404。

确认 try_files 规则存在且静态目录可读:

curl -sI http://127.0.0.1/dist/js/app.js | head -3
ls -ld /opt/leantime/public/dist

若返回 404,多半是文档根指错(指到了包根目录)或 public/ 权限被改成 600。

Q5:忘记管理员密码。

Leantime 不提供默认后台重置入口,用 CLI 查看用户并重置:

php /opt/leantime/bin/leantime user:add --help

也可以直接在数据库里清空 pwReset 后走「忘记密码」流程;生产环境建议先备份 zp_user 表再操作。

Q6:定时任务没有执行,邮件提醒不来。

检查 timer 状态与最近一次执行日志:

systemctl list-timers leantime-scheduler.timer --no-pager
journalctl -u leantime-scheduler.service -n 20 --no-pager

LAST 列长期为 n/a 说明 timer 未触发;确认 OnCalendar 拼写、Persistent=true 与系统时间是否正确。

Q7:中文显示为乱码或保存后截断。

数据库、表、连接三层字符集必须统一为 utf8mb4:

mysql -e "SELECT @@character_set_database, @@collation_database;"
mysql -e "SHOW CREATE DATABASE leantime\G" | grep -i charset

建库时漏写 CHARACTER SET utf8mb4 是最常见原因,需重建库并重新安装。

十二、升级、卸载与清理

12.1 升级到新版本

升级原则:保留 config/.env 与 userfiles/,其余目录整包替换,然后访问 /update 执行数据库迁移。下面以当前版本 3.12.0 走一遍完整替换流程(同版本重装可用于演练);实际升级时先把命令中的 v3.12.0 换成 GitHub Releases 查询到的新 tag。

curl -s https://api.github.com/repos/Leantime/leantime/releases/latest | grep -m1 '"tag_name"'

实测回显:

  "tag_name": "v3.12.0",

下载发布包并备份配置:

cd /opt/src
curl -x http://192.168.1.62:7897 -L -o Leantime-v3.12.0.zip \
  https://github.com/Leantime/leantime/releases/download/v3.12.0/Leantime-v3.12.0.zip

备份与替换:

tar -czf /root/leantime-backup-$(date +%F).tar.gz /opt/leantime/config/.env /opt/leantime/userfiles
cd /opt/leantime
mv config/.env /tmp/leantime.env.bak
rm -rf app bin bootstrap config public storage vendor userfiles
unzip -q /opt/src/Leantime-v3.12.0.zip -d /opt/leantime
mv /tmp/leantime.env.bak config/.env
chown -R www-data:www-data /opt/leantime

然后浏览器访问 /update 完成数据库升级,并用 php bin/leantime about 核对 Leantime App Version 与 Db Version。

12.2 卸载

systemctl disable --now leantime-scheduler.timer
rm -f /etc/systemd/system/leantime-scheduler.service /etc/systemd/system/leantime-scheduler.timer
systemctl daemon-reload
rm -f /etc/nginx/sites-enabled/leantime.conf /etc/nginx/sites-available/leantime.conf
rm -f /etc/nginx/sites-enabled/leantime-tls.conf /etc/nginx/sites-available/leantime-tls.conf
systemctl reload nginx
rm -rf /opt/leantime /opt/src/Leantime-v3.12.0.zip /opt/src/Leantime-v3.12.0.tar.gz
mysql -e 'DROP DATABASE IF EXISTS leantime; DROP USER IF EXISTS "leantime"@"localhost";'

如需彻底移除运行时(确认没有其它 PHP 应用在用):

systemctl disable --now php8.2-fpm nginx mariadb
apt-get purge -y php8.2-fpm php8.2-cli php8.2-mysql nginx mariadb-server

十三、参考链接