Ubuntu 22.04 安装 Hi.Events v1.11.2 指南
目标:在 Ubuntu 22.04 服务器上从零安装 Hi.Events v1.11.2 活动票务平台,提供「源码部署(nginx + PHP-FPM + systemd + cron)」与「官方 Docker 镜像」两套方案:方案 A 面向真实服务器运维习惯,逐条命令实测并收录排障实录;方案 B 为快速路径,完整展开
Ubuntu 22.04 安装 Hi.Events v1.11.2 指南
目标:在 Ubuntu 22.04 服务器上从零安装 Hi.Events v1.11.2 活动票务平台,提供「源码部署(nginx + PHP-FPM + systemd + cron)」与「官方 Docker 镜像」两套方案:方案 A 面向真实服务器运维习惯,逐条命令实测并收录排障实录;方案 B 为快速路径,完整展开见部署指南篇章。全部命令与回显均在 Ubuntu 22.04.5 LTS(x86_64)实测通过。
一、环境信息
| 项目 | 实测值 |
|---|---|
| 操作系统 | Ubuntu 22.04.5 LTS(Jammy Jellyfish,x86_64) |
| Hi.Events 版本 | v1.11.2-beta(tag,git commit 2287e88) |
| PHP | 8.3.36(cli/fpm,ondrej PPA) |
| Composer | 2.10.3 |
| Laravel(框架版本实测) | Laravel Framework 12.34.0(php artisan --version) |
| PostgreSQL | 14.24(Ubuntu 官方仓库,满足官方 13+ 要求) |
| Redis | server 6.0.16(Ubuntu 官方仓库)+ phpredis 扩展 6.3.0 |
| Node.js | 20.20.2(NodeSource 20.x 源) |
| Yarn | 1.22.22(corepack) |
| nginx | 1.18.0(Ubuntu 官方仓库) |
| 服务端口 | Web 入口 80(nginx:/api 与 /storage)、前端页面 5678(SSR)、PostgreSQL 5432、Redis 6379 |
| 部署目录 | /opt/web/hi-events(backend/ 与 frontend/ 同仓两目录) |
二、前置条件
2.1 系统与权限
- 一台 Ubuntu 22.04 服务器,
root或具备sudo权限的账号; - 服务器可访问外网(GitHub 源码、PPA、NodeSource、Composer 包仓库);
- 内存 ≥ 2GB(前端
yarn build峰值内存较高,1GB 实例需加 swap)。
2.2 网络与软件源
方案 A 需要两个第三方软件源:
- ondrej/php PPA:提供 PHP 8.3(Ubuntu 22.04 官方仓库只有 PHP 8.1,不满足 Laravel 12 的 PHP 8.2+ 要求);
- NodeSource 20.x:提供 Node.js 20(22.04 官方仓库 Node 为 12.x,无法构建前端)。
2.3 端口占用检查
# ss -ltn | grep -E ':(80|5678|5432|6379)\s'
四个端口均应无输出(未被占用)。若 80 被 nginx 默认站点占用可先移除默认站点(见 4.7)。
三、版本选型说明
- Hi.Events 当前的稳定线为 v1.11.2-beta(GitHub Releases 2026-10-21 发布,v1 线最新补丁);v2 线处于
v2.0.0-rc.3候选阶段,不建议生产采用。本文以 tagv1.11.2-beta安装; - PHP 必须 8.3.x:Laravel 12 要求 PHP 8.2+,而官方镜像与迁移实测口径为 8.3(镜像内实测 PHP 8.3.36),源码部署对齐 8.3 减少偏差;
- PostgreSQL 官方唯一正式支持(13+,迁移自动创建
pg_trgm扩展);Ubuntu 22.04 仓库自带的 14.24 实测满足; - Redis 必装:缓存、队列、会话三类驱动均指向 redis;Ubuntu 22.04 仓库自带 6.0.16 实测可用,追求新特性可升级 7.x。
四、方案 A:源码部署(nginx + PHP-FPM + systemd,推荐生产)
4.1 方案说明
以真实服务器形态部署:后端 Laravel 走 PHP-FPM(nginx 反代 /api 与 /storage),前端构建后由 Node.js SSR 进程(5678 端口)提供页面,队列 Worker 与前端 SSR 由 systemd 常驻托管,调度器走 cron 每分钟触发。该形态与官方「Manual Setup」路线一致,便于深度定制。
访问拓扑(实测):用户浏览器访问 http://<服务器IP>:5678 看页面;页面内的 API 调用按 VITE_API_URL_CLIENT 配置直连 http://<服务器IP>/api(nginx 80)。
4.2 安装系统依赖
# apt update
# apt -y install curl git gnupg ca-certificates lsb-release nginx postgresql redis-server
# add-apt-repository ppa:ondrej/php -y
# apt -y install php8.3-fpm php8.3-cli php8.3-pgsql php8.3-redis php8.3-mbstring \
php8.3-xml php8.3-curl php8.3-zip php8.3-bcmath php8.3-intl php8.3-gd php8.3-opcache
安装 Composer:
# curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
# composer -V
Composer version 2.10.3 2026-08-27 13:34:23
安装 Node.js 20 与 Yarn:
# curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
# apt -y install nodejs
# node -v
v20.20.2
# corepack enable
# yarn -v
1.22.22
版本核对(实测回显):
# php -v | head -1
PHP 8.3.36 (cli) (built: Oct 21 2026 14:31:50) (NTS)
# psql --version
psql (PostgreSQL) 14.24 (Ubuntu 14.24-0ubuntu0.22.04.1)
# redis-server --version
Redis server v=6.0.16 sha=00000000:0 malloc=jemalloc-5.2.1 bits=64 build=d6ed09173b889769
# php -m | grep -E 'redis|pgsql|sodium'
pdo_pgsql
pgsql
redis
sodium
注意:
php8.3-sodium包在 PPA 中不存在,但无需安装——sodium 扩展已内置于 php8.3-common(上面php -m已可见)。php8.3-redis是必装项,原因见 7.1 排障实录。
4.3 创建数据库与账号
# sudo -u postgres psql -c "CREATE USER hievents WITH PASSWORD 'q1w2e3r4';"
CREATE ROLE
# sudo -u postgres psql -c "CREATE DATABASE hievents OWNER hievents;"
CREATE DATABASE
4.4 下载源码并安装后端依赖
# git clone --branch v1.11.2-beta https://github.com/HiEventsDev/Hi.Events.git /opt/web/hi-events
# cd /opt/web/hi-events/backend
# composer install --no-dev --optimize-autoloader
composer install 完成后生成 vendor/ 目录。核对关键依赖(composer.json 实测片段):"php": "^8.2"、"laravel/framework": "^12.0";依赖清单中没有 predis,redis 客户端完全依赖系统的 phpredis 扩展(php8.3-redis)。
4.5 生成密钥与配置 .env
# cd /opt/web/hi-events/backend
# cp .env.example .env
# php artisan key:generate
# php artisan jwt:secret --force
编辑 /opt/web/hi-events/backend/.env 关键键(实测值,10.89.59.10 换成你的服务器 IP):
APP_ENV=production
APP_DEBUG=false
APP_URL=http://10.89.59.10
APP_FRONTEND_URL=http://10.89.59.10:5678
LOG_CHANNEL=daily
DB_CONNECTION=pgsql
DB_HOST=localhost
DB_PORT=5432
DB_DATABASE=hievents
DB_USERNAME=hievents
DB_PASSWORD=q1w2e3r4
CACHE_DRIVER=redis
QUEUE_CONNECTION=redis
SESSION_DRIVER=redis
REDIS_HOST=localhost
REDIS_PORT=6379
两个高频错误:
REDIS_HOST必须是localhost(本机部署;redis是 Docker 服务名残留写法);DB_HOST为localhost(PostgreSQL 与应用同机)。
4.6 数据库迁移与软链
# php artisan migrate --force
# php artisan storage:link
迁移会自动创建 pg_trgm 扩展(迁移目录内置 extensions.sql:CREATE EXTENSION IF NOT EXISTS pg_trgm;)并建立全部表结构。验证(实测回显):
# php artisan migrate:status | head -8
Migration name .............................................. Batch / Status
2020_01_25_113926_initial_db ....................................... [1] Ran
2024_05_16_222520_update_homepage_background_settings .............. [1] Ran
2024_06_16_143927_add_locale_to_users .............................. [1] Ran
2024_06_16_192150_add_locale_to_attendees .......................... [1] Ran
2024_06_16_192151_add_locale_to_orders ............................. [1] Ran
2024_07_11_223142_add_description_to_questions_table ............... [1] Ran
# php artisan migrate:status | grep -c Ran
102
目录属主修正(关键步骤):以上 artisan 命令以 root 执行,必须把运行时目录归还给 www-data,否则 FPM 运行期写日志/缓存将失败(真实事故见 7.2):
# chown -R www-data:www-data /opt/web/hi-events/backend/storage /opt/web/hi-events/backend/bootstrap/cache
4.7 配置 nginx 与 PHP-FPM
创建 /etc/nginx/sites-available/hi-events.conf(实测文件原文):
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /opt/web/hi-events/backend/public;
index index.php;
client_max_body_size 20M;
location /storage {
alias /opt/web/hi-events/backend/storage/app/public;
access_log off;
expires max;
add_header Cache-Control "public";
}
location ^~ /api/ {
rewrite ^/api(/.*)$ /index.php$1 break;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
fastcgi_param REQUEST_URI $1;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
location / {
return 404;
}
}
要点:nginx 只承接 /api(rewrite 剥掉前缀转 index.php)与 /storage(静态资源别名),页面由 SSR 进程提供;若 80 已被默认站点占用,删除 /etc/nginx/sites-enabled/default 再启用本配置。
# ln -s /etc/nginx/sites-available/hi-events.conf /etc/nginx/sites-enabled/
# rm -f /etc/nginx/sites-enabled/default
# nginx -t && systemctl reload nginx
4.8 构建前端与 SSR
# cd /opt/web/hi-events/frontend
# cp .env.example .env
编辑 /opt/web/hi-events/frontend/.env(实测值):
VITE_API_URL_CLIENT=http://10.89.59.10/api
VITE_API_URL_SERVER=http://10.89.59.10/api
VITE_FRONTEND_URL=http://10.89.59.10:5678
安装依赖并构建(构建脚本依次执行文案抽取/编译、SSR 客户端与服务端构建,产物落在 dist/client 与 dist/server):
# yarn install
# yarn build
构建完成后 server.js(前端目录根)即为 SSR 入口,默认监听 5678。SSR 进程对任意路径都会渲染页面壳(实测对 /api/... 路径同样返回 HTML 页面而非 JSON),因此 API 请求必须走 nginx 80,.env 中两个 VITE_API_URL_* 指向 http://<服务器IP>/api 即是此意。
4.9 systemd 托管队列 Worker 与前端 SSR
创建 /etc/systemd/system/hievents-queue.service(实测文件原文):
[Unit]
Description=Hi.Events queue worker
After=network.target redis-server.service postgresql.service
[Service]
User=www-data
Group=www-data
Restart=always
RestartSec=3
WorkingDirectory=/opt/web/hi-events/backend
ExecStart=/usr/bin/php8.3 artisan queue:work --queue=default,webhook-queue --sleep=3 --tries=3 --timeout=60
[Install]
WantedBy=multi-user.target
创建 /etc/systemd/system/hievents-frontend.service(实测文件原文):
[Unit]
Description=Hi.Events frontend SSR server
After=network.target
[Service]
User=www-data
Group=www-data
Restart=always
RestartSec=3
WorkingDirectory=/opt/web/hi-events/frontend
Environment=NODE_ENV=production
ExecStart=/usr/bin/node server.js
[Install]
WantedBy=multi-user.target
启用并启动(实测状态):
# systemctl daemon-reload
# systemctl enable --now hievents-queue hievents-frontend
# systemctl status hievents-queue --no-pager | head -8
● hievents-queue.service - Hi.Events queue worker
Loaded: loaded (/etc/systemd/system/hievents-queue.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2026-10-23 09:49:05 UTC; 18min ago
Main PID: 20954 (php8.3)
Tasks: 1 (limit: 94371)
Memory: 42.5M
CPU: 370ms
# systemctl status hievents-frontend --no-pager | head -8
● hievents-frontend.service - Hi.Events frontend SSR server
Loaded: loaded (/etc/systemd/system/hievents-frontend.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2026-10-23 09:49:06 UTC; 18min ago
Main PID: 20960 (node)
Tasks: 11 (limit: 94371)
Memory: 86.7M
队列 Worker 日志出现业务任务执行记录即为正常(实测样例):
Oct 23 10:07:03 php8.3[20954]: 2026-10-23 10:07:03 HiEvents\Jobs\Message\SendScheduledMessagesJob 2.04ms DONE
Oct 23 10:07:03 php8.3[20954]: 2026-10-23 10:07:03 HiEvents\Jobs\Waitlist\ProcessExpiredWaitlistOffersJob RUNNING
4.10 配置调度器 cron
创建 /etc/cron.d/hievents-scheduler(实测文件原文,每分钟以 www-data 触发 Laravel 调度):
* * * * * www-data cd /opt/web/hi-events/backend && /usr/bin/php8.3 artisan schedule:run >> /dev/null 2>&1
4.11 安装验证
# systemctl is-active nginx php8.3-fpm postgresql redis-server hievents-queue hievents-frontend
active active active active active active
# curl -s -o /dev/null -w '%{http_code}\n' http://localhost:5678/
200
# curl -s -X POST http://localhost/api/auth/login \
-H 'Accept: application/json' -H 'Content-Type: application/json' \
-d '{"email":"admin@example.com","password":"q1w2e3r4"}'
{"token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0L2F1dGgvbG9naW4iLCJpYXQiOjE3OTI3NTAwNzcsImV4cCI6MTc5MzM1NDg3NywibmJmIjoxNzkyNzUwMDc3LCJqdGkiOiJZNnBoR21UTHlBclpBT2ZlIiwic3ViIjoiMSIsInBydiI6ImI1YjFhZjFhZWY1MWUyMmU1Y2JlMzk0YzM3NDU3MjJhYjgwYWQ2Y2MiLCJhY2NvdW50X2lkIjoxLCJyb2xlIjoiQURNSU4ifQ.dTjNLiJeGk2TCFjUSiA6iJunXHjsGc-ADRicTXrymQI","token_type":"bearer","expires_in":604800}
首次使用:浏览器访问
http://<服务器IP>:5678注册管理员账号,再登录后台创建组织者与活动。注意curl http://localhost/(nginx 80 根路径)返回 404 属预期——80 只服务/api与/storage,页面在 5678。
日常维护命令建议以 www-data 身份执行,避免再次制造属主事故:
# sudo -u www-data php artisan migrate:status
五、方案 B:官方 Docker 镜像部署(快速路径)
5.1 方案说明
官方 daveearley/hi.events-all-in-one:v1.11.2-beta 镜像把 nginx、PHP-FPM、队列 Worker、调度器、前端 SSR 五进程打包为一体(supervisord 托管),并内置 /startup.sh 自动执行迁移与缓存清理,适合快速起栈与体验验证;生产亦可使用(官方生产推荐分离镜像,见部署指南篇章)。
5.2 部署要点
核心三步(完整展开与持久化/备份/恢复实测见《Hi.Events v1.11.2 Docker Compose 部署指南》):
- 生成
APP_KEY与JWT_SECRET,准备.env; - 按官方
docker/all-in-one/docker-compose.yml拉起all-in-one + postgres:17-alpine + redis:7-alpine三服务栈; - 首启自动建表,浏览器访问映射端口注册管理员即可使用。
与方案 A 的差异:方案 B 无需手工处理 PHP 扩展、密钥生成之外的任何系统配置,但运行形态锁定为镜像内编排,深度定制(改 nginx 配置、独立扩缩容)不如方案 A 灵活。
六、方案对比与选择建议
| 维度 | 方案 A:源码部署 | 方案 B:官方镜像 |
|---|---|---|
| 安装耗时 | 约 30~60 分钟(含前端构建) | 10 分钟级 |
| 依赖管理 | 手工(PHP 8.3 PPA + Node 20 + 扩展 + 数据库) | 镜像内置 |
| 升级方式 | git 拉新 tag + composer + migrate | 换镜像 tag 自动迁移 |
| 定制能力 | 完全(nginx/PHP/进程编排均可改) | 受镜像约束 |
| 故障面 | 系统依赖链较宽(见 7.1~7.3 实录) | 集中在镜像与数据卷 |
| 适合场景 | 生产长期运行、深度定制、内网环境 | 快速验证、中小规模生产 |
选择建议:生产环境且团队有 PHP 运维经验选方案 A;快速验证或无 PHP 运维经验选方案 B;方案 B 后续需要深度定制时可平滑切换方案 A(数据用 pg_dump 迁移)。
七、常见问题与排障实录
7.1 实录一:HTTP 500 排障长链(php8.3-redis 缺失 → REDIS_HOST 错值 → 日志权限)
症状:方案 A 安装完成后,访问页面返回 HTTP 500 空白;storage/logs/laravel.log 中出现 Class "cache" does not exist。
排查 1(第一层原因):composer.json 依赖里没有 predis,redis 客户端依赖系统 phpredis 扩展,而安装时漏装了 php8.3-redis,CACHE_DRIVER=redis 无法实例化导致报错。补装:
# apt -y install php8.3-redis
# systemctl reload php8.3-fpm
排查 2(第二层原因):仍 500。检查 .env 发现 REDIS_HOST=redis——这是官方 Docker 栈的服务名写法,本机部署应为 localhost。改为 localhost 后,用 php artisan serve(CLI 内置服务器)验证后端已恢复:未带令牌的 API 请求返回 401 JSON(正常业务响应)。但 FPM 路径依旧 500。
排查 3(进程干扰插曲):怀疑残留的 artisan serve 进程占用干扰,执行 pkill -f 'artisan serve' 时命中了命令自身导致会话被杀(exit 143)。正确写法用正则隔开:
# pkill -f 'artisan\s+serve'
排查 4(真凶定位):CLI 正常而 FPM 异常,指向运行用户差异。在 FPM 环境放置探针脚本直接调用 Laravel Kernel 捕获真实异常,得到:
The stream or file "/opt/web/hi-events/backend/storage/logs/laravel.log"
could not be opened in append mode: Permission denied
根因:4.5~4.6 的全部 artisan 命令均以 root 执行,storage/logs/laravel.log 属主为 root,www-data 启动期写日志失败,异常在框架启动期雪崩为 500(与 redis 无关的独立问题,但被前两层修复掩盖)。
修复:
# chown -R www-data:www-data storage bootstrap/cache
修复后 FPM 立即恢复:未带令牌请求返回 401 JSON,带令牌返回业务数据(见 4.11 验证回显)。
教训沉淀:① php8.3-redis 是必装依赖,漏装的表现是 Class "cache" does not exist;② 本机部署 REDIS_HOST=localhost,redis 是 Docker 服务名;③ artisan 维护命令一律 sudo -u www-data 执行,或收尾统一 chown -R www-data:www-data storage bootstrap/cache;④ CLI 正常而 FPM 异常时,用 FPM 探针脚本看真实异常,不要停在日志表象。
7.2 实录二:hievents-frontend 服务启动失败(5678 被占用)
症状:systemctl status hievents-frontend 显示 failed,日志提示端口 5678 被占用。
定位:ss -ltnp | grep 5678 发现一个手工 nohup node server.js 起的残留进程。
处理:
# pkill -f 'node server[.]js'
# systemctl restart hievents-frontend
# systemctl is-active hievents-frontend
active
教训:手工验证进程先收尾,再交给 systemd 托管;server.js 中的 [.] 写法避免 pkill 自匹配。
7.3 实录三:php8.3-sodium 包不存在
安装依赖时若按 apt install php8.3-sodium 会报 Unable to locate package——ondrej PPA 无此包,sodium 扩展已内置于 php8.3-common(php -m | grep sodium 可验证),无需单独安装。
7.4 其他 FAQ
Q1:yarn build 内存不足被杀:构建峰值内存较高,1GB 实例添加 2GB swap 后重试,或改在构建机构建后同步 dist/ 产物。
Q2:访问 5678 出现页面但登录后 API 报跨域/网络错误:.env 中 VITE_API_URL_CLIENT 必须指向 nginx 80 的 /api(与 APP_URL 同主机),并确认浏览器能直连 80 端口;SSR 端口不代理 API。
Q3:php artisan migrate 报连接拒绝:检查 DB_HOST/DB_PORT/DB_USERNAME/DB_PASSWORD 与 4.3 创建的账号一致;PostgreSQL 默认监听 localhost,本机部署无需改 pg_hba.conf(peer 改 md5 的场景仅出现在跨机连接)。
Q4:队列 Worker 停止后订单邮件不发:订单邮件与 Webhook 走异步队列(default 与 webhook-queue 双队列),hievents-queue 服务必须常驻;Restart=always 已含自动拉起,人工重启用 systemctl restart hievents-queue。
八、卸载与清理
8.1 停用服务与移除配置
# systemctl disable --now hievents-queue hievents-frontend
Removed "/etc/systemd/system/multi-user.target.wants/hievents-queue.service".
Removed "/etc/systemd/system/multi-user.target.wants/hievents-frontend.service".
# rm -f /etc/systemd/system/hievents-queue.service /etc/systemd/system/hievents-frontend.service
# systemctl daemon-reload
# rm -f /etc/cron.d/hievents-scheduler
# rm -f /etc/nginx/sites-enabled/hi-events.conf /etc/nginx/sites-available/hi-events.conf
# nginx -t && systemctl reload nginx
8.2 删除数据库与文件
# sudo -u postgres psql -c 'DROP DATABASE hievents;' -c 'DROP USER hievents;'
DROP DATABASE
DROP ROLE
# rm -rf /opt/web/hi-events
依赖包(PHP 8.3、Node.js、PostgreSQL、Redis、nginx)按需保留或用 apt purge 卸载;若卸载 PostgreSQL 前有备份需求,先用 pg_dump 导出。
九、参考链接
- 官方部署文档(Manual Setup 口径):https://hi.events/docs/getting-started/deploying
- GitHub 仓库:https://github.com/HiEventsDev/Hi.Events
- GitHub Releases:https://github.com/HiEventsDev/Hi.Events/releases
- 本专栏关联篇章:《Hi.Events v1.11.2 介绍与选型指南》《Hi.Events v1.11.2 Docker Compose 部署指南》《Hi.Events v1.11.2 配置参数详解》《Hi.Events v1.11.2 API 使用详解》