Ubuntu 22.04 安装 Ever Gauzy 111.48.2 指南

在 Ubuntu 22.04 上从源码安装 Ever Gauzy v111.48.2:PostgreSQL 17 与 Node.js 24 依赖链、yarn bootstrap 依赖安装与原生模块排障实录、.env 核心配置与安全密钥生成、生产构建产物部署、systemd/pm2 进程托管、serve 前端托管、部署验证与卸载清理,全部命令与回显实测。

Ever GauzyEver Gauzy自托管2026/10/23

Ubuntu 22.04 安装 Ever Gauzy 111.48.2 指南

目标:在 Ubuntu 22.04 服务器上从源码完整安装 Ever Gauzy v111.48.2(NestJS API + Angular Web 前端 + PostgreSQL 17),覆盖依赖链安装、yarn bootstrap、.env 配置、生产构建、systemd/pm2 进程托管、部署验证、排障实录与卸载清理;全部命令与回显已在 Ubuntu 22.04.5 LTS(Node v24.22.1 / PostgreSQL 17.11)环境逐条实测通过。

一、环境信息

本文所有操作均在以下环境实测完成,命令输出均来自该环境真实回显。

  • 操作系统:Ubuntu 22.04.5 LTS(版本代号 jammy),x86_64 架构
  • Node.js:v24.22.1(npm 11.19.1,来自 NodeSource apt 源)
  • Yarn:1.22.22(npm 全局安装)
  • PostgreSQL:17.11(来自 PGDG 官方 apt 源)
  • 进程管理:pm2 6.0.14(实测);systemd 单元(标准托管形态,见第九章)
  • 前端静态托管:serve 14.2.6(npm 全局安装)
  • Ever Gauzy:v111.48.2(GitHub tag v111.48.2,commit 5b3f778)
  • 源码目录:/opt/ever-gauzy(含 node_modules 约 13GB、dist 构建产物约 343MB,合计约 16GB)
  • 端口:API 3000、Web 前端 4200、PostgreSQL 5432
  • 实测主机内存:32GB(构建阶段设置 Node 堆上限 12GB,见第八章)

二、前置条件

2.1 硬件与系统要求

开始前先确认机器规格满足要求,避免装到一半因资源不足返工:

  • 内存:源码构建阶段是内存大户,实测以 NODE_OPTIONS=--max-old-space-size=12288(12GB 堆上限)完成 yarn build:prod;建议 ≥8GB 内存再执行构建,4GB 以下机器不建议本地构建(可改用第九章的 Compose 部署形态)。
  • 磁盘:源码 + 依赖 + 构建产物实测约 16GB,建议预留 ≥20GB。
  • 系统:Ubuntu 22.04(真机默认带 systemd,第九章 systemd 托管依赖它)。
  • 网络:需要访问 GitHub(克隆源码)与 npm registry(安装依赖),确保可连通外网。

2.2 软件依赖链总览

Ever Gauzy 是 Node.js 单体仓库(monorepo)项目,安装链路如下,每一环都对应后文一个章节:

依赖实测版本作用对应章节
git / curl / CA 证书系统源克隆源码、添加 apt 源2.3
PostgreSQL17.11业务数据库(必须外接,见 DB_TYPE=postgres)四
Node.jsv24.22.1运行 API 与执行构建(engines 要求 >=24)五
Yarn1.22.22工作区依赖安装与脚本入口五
Ever Gauzy 源码v111.48.2yarn bootstrap → yarn build:prod六~八

关键差异解读:PostgreSQL 与 Node.js 是两条独立依赖链,必须先装数据库再装应用;Yarn 必须用 1.x(项目脚本按 Classic Yarn 编写,Yarn 2+ Berry 不兼容)。

2.3 安装基础工具

先更新软件源索引并安装 git、curl 与证书工具:

apt-get update
apt-get install -y curl ca-certificates gnupg git

实测输出(节选):

Get:18 http://archive.ubuntu.com/ubuntu jammy-backports/universe amd64 Packages [35.6 kB]
Fetched 49.0 MB in 22s (2187 kB/s)
Reading package lists...
...
Running hooks in /etc/ca-certificates/update.d...
done.

git 就绪的最终验证在 6.1 克隆源码时一并完成(克隆成功即 git 可用)。

三、版本选型说明

3.1 Ever Gauzy 版本

本文安装官方 GitHub 仓库 ever-co/ever-gauzy 的 tag v111.48.2,对应 commit 5b3f778(2026-10-23 在克隆出的源码中用 git log --oneline -1 实查确认,回显见 6.1)。选 tag 而不是 master 分支,是为了保证安装结果可复现、不受上游代码变动影响。

3.2 依赖版本要求

  • Node.js:仓库 package.json 的 engines 字段要求 >=24,本文实测 v24.22.1 满足要求;
  • PostgreSQL:项目同时支持 PostgreSQL 与 SQLite(DB_TYPE 控制),生产一律选 PostgreSQL;Ubuntu 22.04 系统源自带的是 14.x,本文按官方推荐走 PGDG 源装 17.x;
  • Yarn:1.22.22(Classic Yarn 最终版)。

3.3 安装形态对比与选择建议

同一套 v111.48.2 有三种落地形态,本文主线是第一种:

形态前置依赖是否需本地构建适用场景
源码构建(本文)PostgreSQL + Node.js 24 + Yarn是(约 4 分钟,实测 221.78s)需要改源码/插件开发、或不想引入 Docker 运行时
Docker Compose 镜像部署Docker Engine + Compose否快速拿一套标准环境,见 《Ever Gauzy 111.48.2 Docker Compose 部署指南》
官方预构建安装包按安装包说明否桌面/一体化体验,从 gauzy.co/downloads 与 GitHub Releases 获取(形态说明见 《Ever Gauzy 111.48.2 介绍与选型指南》)

选择建议:要源码级可控选本文;只要快速跑起来选 Compose;终端用户单机使用看预构建包。

3.4 升级与多版本管理

  • 升级到新版本:git fetch --tags 拉取新 tag → git checkout v<新版本号> → 重新执行 yarn bootstrap 与 yarn build:prod → 按第九章方式重启进程;数据库结构变更由启动时的自动迁移完成(见 9.1)。
  • 多版本并存:把不同版本克隆到不同目录(如 /opt/ever-gauzy-111、/opt/ever-gauzy-112),各自独立 .env 与数据库;切换时改 systemd/pm2 指向的目录即可。

四、安装 PostgreSQL 17 数据库

本章先装好数据库并建库建用户——Ever Gauzy 首次启动会自动迁移建表,但库本身和账号要先就位。

💡 技术拓展:Ubuntu 上装 PostgreSQL 有三条常用路线——

路线版本特点适用场景
PGDG 官方 apt 源最新大版本(如 17.x),更新快生产环境,需要新版本特性
Ubuntu 系统源(universe)跟随发行版(22.04 为 14.x),最稳只求可用、版本不敏感
源码编译任意版本、可定制特殊定制需求

本文采用 PGDG 源安装 PostgreSQL 17:既拿到新版本,又走 apt 便于后续升级与卸载。

4.1 添加 PGDG 官方源

导入 PGDG 签名密钥并写入软件源配置:

install -d /usr/share/postgresql-common/pgdg
curl -fsSL -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc https://www.postgresql.org/media/keys/ACCC4CF8.asc
echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] https://apt.postgresql.org/pub/repos/apt jammy-pgdg main" > /etc/apt/sources.list.d/pgdg.list
apt-get update

实测输出(节选):

Fetched 1348 kB in 2s (894 kB/s)
Reading package lists...

4.2 安装 PostgreSQL 17

apt-get install -y postgresql-17

安装完成即自动创建 17/main 集群。验证集群状态:

service postgresql status

实测输出:

17/main (port 5432): online

4.3 启动数据库并核验版本

service postgresql start

实测输出:

 * Starting PostgreSQL 17 database server
   ...done.

核验数据库版本:

su - postgres -c "psql -c 'select version();'"

实测输出(节选):

                                                 version
---------------------------------------------------------------------------------------------------------------------------------------
 PostgreSQL 17.11 (Ubuntu 17.11-1.pgdg22.04+2) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0, 64-bit

4.4 创建业务库与专用账号

创建供 Ever Gauzy 使用的数据库账号 gauzy(密码 q1w2e3r4,演示口令)与同名数据库:

su - postgres -c "psql -c \"CREATE USER gauzy WITH PASSWORD 'q1w2e3r4' CREATEDB;\""
su - postgres -c "psql -c \"CREATE DATABASE gauzy OWNER gauzy;\""

实测输出:

CREATE ROLE
CREATE DATABASE

验证:库与账号已就位后,本章完成。第七章的 .env 会用 DB_USER=gauzy、DB_PASS=q1w2e3r4、DB_NAME=gauzy 连接它。

五、安装 Node.js 24 与 Yarn

💡 技术拓展:Ubuntu 上安装 Node.js 的三种常用方式——

方式特点适用场景
NodeSource apt 源版本新、随 apt 升级、全局可用服务器长期运行固定大版本
nvm按用户多版本切换一机多版本开发调试
官方 tar.gz 解压免源配置、路径自管离线/受限环境

本文采用 NodeSource apt 源安装 Node.js 24:与 PostgreSQL 的 apt 体系一致,升级卸载路径统一。

5.1 添加 NodeSource 源并安装

curl -fsSL https://deb.nodesource.com/setup_24.x -o /tmp/nodesource_setup.sh
bash /tmp/nodesource_setup.sh
apt-get install -y nodejs

实测输出(节选):

Setting up nodejs (24.22.1-1nodesource1) ...
Processing triggers for libc-bin (2.35-0ubuntu3.15) ...

5.2 验证 Node.js 与 npm

node -v
npm -v

实测输出:

v24.22.1
11.19.1

5.3 安装 Yarn 1.22.22

npm install -g yarn@1.22.22
yarn -v

实测输出:

1.22.22

六、获取源码并安装依赖

6.1 克隆 v111.48.2 源码

从 GitHub 克隆指定 tag(--depth 1 只取该版本快照,省时省盘):

cd /opt
git clone --depth 1 -b v111.48.2 https://github.com/ever-co/ever-gauzy.git ever-gauzy
cd ever-gauzy && git log --oneline -1

实测输出(节选):

Turn off this advice by setting config variable advice.detachedHead to false
5b3f778 Merge pull request #10385 from ever-co/stage

版本与 commit 与 3.1 预期一致,源码就位。

6.2 yarn bootstrap 安装依赖

yarn bootstrap 是项目自带的总入口,等价于「yarn install --ignore-scripts + 依赖后置处理(含原生模块重编译)」。全程实测耗时约 30 分钟:

cd /opt/ever-gauzy
yarn bootstrap

实测输出(节选,末尾):

Done in 1806.03s.

⚠️ 注意:这一步会下载并编译大量 npm 包,国内网络环境慢属正常;整个 monorepo 的 node_modules 实测约 13GB,磁盘要留够。

6.3 排障实录:原生模块 node-gyp 重编译报错

实测 yarn bootstrap 过程中出现了如下 better-sqlite3 原生模块重编译报错(输出节选):

npm error gyp ERR! command "/usr/bin/node" "/opt/ever-gauzy/node_modules/.bin/node-gyp" "rebuild" "--release"
npm error gyp ERR! cwd /opt/ever-gauzy/node_modules/@mikro-orm/better-sqlite/node_modules/better-sqlite3
npm error gyp ERR! node -v v24.22.1
npm error gyp ERR! node-gyp -v v10.3.1
npm error gyp ERR! not ok

定位:报错来自 @mikro-orm/better-sqlite(SQLite ORM 驱动)联动重编译的 better-sqlite3 原生模块。继续看 yarn bootstrap 的收尾输出,bootstrap 自带的二进制核验环节给出了关键结论(输出节选):

npm rebuild reported a failure; verifying binaries anyway: Command failed: npm rebuild @sentry/profiling-node bcrypt better-sqlite3
  – @sentry/profiling-node has no binary of its own (not required)
  ✔ bcrypt → bcrypt/lib/binding/napi-v3/bcrypt_lib.node
  ✔ better-sqlite3 → better-sqlite3/build/Release/better_sqlite3.node
Done in 1806.03s.

结论与处理:核验显示 bcrypt 与 better-sqlite3 的预编译二进制实际都已就位(✔),SQLite 驱动的报错在本文的 PostgreSQL 模式(DB_TYPE=postgres)下不影响运行——后文第十章的登录接口实测成功即为佐证。若确需本地从源码编译此类原生模块(如断网环境拿不到预编译产物),提前安装编译工具链再重跑重编译:

apt-get install -y build-essential python3

依赖安装完成的验证:node_modules 目录已生成且体积符合预期。

du -sh /opt/ever-gauzy/node_modules

实测输出:

13G     /opt/ever-gauzy/node_modules

七、配置环境变量(.env)

Ever Gauzy 的全部运行参数集中在源码根目录的 .env 文件(模板为 .env.sample)。本章把数据库连接、种子账号与安全密钥落到实测值。

7.1 复制模板并写入关键项

先复制模板,再用逐项替换的方式写入关键配置(每行只改一个变量,便于核对):

cd /opt/ever-gauzy
cp .env.sample .env
sed -i 's|^NODE_ENV=.*|NODE_ENV=production|' .env
sed -i 's|^DB_TYPE=.*|DB_TYPE=postgres|' .env
sed -i 's|^# DB_HOST=localhost|DB_HOST=localhost|' .env
sed -i 's|^# DB_PORT=5432|DB_PORT=5432|' .env
sed -i 's|^# DB_NAME=gauzy|DB_NAME=gauzy|' .env
sed -i 's|^# DB_USER=postgres|DB_USER=gauzy|' .env
sed -i 's|^# DB_PASS=root|DB_PASS=q1w2e3r4|' .env
sed -i 's|^API_BASE_URL=.*|API_BASE_URL=http://localhost:3000|' .env
sed -i 's|^CLIENT_BASE_URL=.*|CLIENT_BASE_URL=http://localhost:4200|' .env
sed -i 's|^GAUZY_APP_VERSION=.*|GAUZY_APP_VERSION=v111.48.2|' .env
sed -i 's|^GAUZY_APP_COMMIT=.*|GAUZY_APP_COMMIT=5b3f778e1d12f21992b39b42218fd2fd354c21d6|' .env

逐项说明(完整参数体系见 《Ever Gauzy 111.48.2 配置参数详解》):

变量实测值含义
NODE_ENVproduction运行模式,决定加载生产配置
DB_TYPEpostgres数据库类型(勿用默认 sqlite 跑生产)
DB_HOST/DB_PORTlocalhost/5432本机 PGDG 安装的 PG17 默认监听
DB_NAME/DB_USER/DB_PASSgauzy/gauzy/q1w2e3r44.4 创建的库与账号
API_BASE_URLhttp://localhost:3000API 对外地址
CLIENT_BASE_URLhttp://localhost:4200Web 前端对外地址(与第九章 serve 端口一致)
GAUZY_APP_VERSION/GAUZY_APP_COMMITv111.48.2/5b3f778…版本标识,/api/version 会原样返回

7.2 生成安全密钥

.env.sample 中 4 个密钥变量默认留空,必须填入随机值(用 openssl 逐个生成并写回,每个变量单独一条命令):

V=$(openssl rand -hex 64) && sed -i "s|^JWT_SECRET=$|JWT_SECRET=${V}|" .env
V=$(openssl rand -hex 64) && sed -i "s|^JWT_REFRESH_TOKEN_SECRET=$|JWT_REFRESH_TOKEN_SECRET=${V}|" .env
V=$(openssl rand -hex 64) && sed -i "s|^JWT_VERIFICATION_TOKEN_SECRET=$|JWT_VERIFICATION_TOKEN_SECRET=${V}|" .env
V=$(openssl rand -hex 64) && sed -i "s|^EXPRESS_SESSION_SECRET=$|EXPRESS_SESSION_SECRET=${V}|" .env

openssl rand -hex 64 输出节选(每次运行都不同,取该次输出填入对应变量即可):

90815c0253ba9ca54d169f6c5c616c38f184147a23618f156bd031889748841e241978fe66e597e832f9be5b25cf8144bd58cde5f89ca747fa15fffe9d820769

7.3 写入演示种子账号

首次启动会按 DEMO_* 变量初始化账号(第十章用超级管理员登录验证):

sed -i 's|^DEMO_SUPER_ADMIN_EMAIL=.*|DEMO_SUPER_ADMIN_EMAIL=admin@ever.co|' .env
sed -i 's|^DEMO_SUPER_ADMIN_PASSWORD=.*|DEMO_SUPER_ADMIN_PASSWORD=q1w2e3r4|' .env
sed -i 's|^DEMO_ADMIN_EMAIL=.*|DEMO_ADMIN_EMAIL=local.admin@ever.co|' .env
sed -i 's|^DEMO_ADMIN_PASSWORD=.*|DEMO_ADMIN_PASSWORD=q1w2e3r4|' .env
sed -i 's|^DEMO_EMPLOYEE_EMAIL=.*|DEMO_EMPLOYEE_EMAIL=employee@ever.co|' .env
sed -i 's|^DEMO_EMPLOYEE_PASSWORD=.*|DEMO_EMPLOYEE_PASSWORD=q1w2e3r4|' .env

7.4 核验配置结果

grep -E '^(NODE_ENV|DB_TYPE|DB_HOST|DB_PORT|DB_NAME|DB_USER|DB_PASS|API_BASE_URL|CLIENT_BASE_URL|GAUZY_APP_VERSION)=' .env

实测输出:

GAUZY_APP_VERSION=v111.48.2
API_BASE_URL=http://localhost:3000
CLIENT_BASE_URL=http://localhost:4200
DB_TYPE=postgres
DB_HOST=localhost
DB_PORT=5432
DB_NAME=gauzy
DB_USER=gauzy
DB_PASS=q1w2e3r4
NODE_ENV=production

再确认 4 个密钥均已非空(输出 4 即全部生效):

grep -cE '^(JWT_SECRET|JWT_REFRESH_TOKEN_SECRET|JWT_VERIFICATION_TOKEN_SECRET|EXPRESS_SESSION_SECRET)=..' .env

实测输出:

4

八、生产构建

8.1 设置构建期内存上限

Angular + NestJS 的 monorepo 生产构建非常吃内存。实测在 32GB 主机上显式把 Node 堆上限设为 12GB 后构建稳定通过:

export NODE_OPTIONS=--max-old-space-size=12288

💡 说明:该值只影响当前 shell 会话。API 运行态内存实测仅约 565MB(见 9.3 的 pm2 内存列),大内存需求只在构建期;内存充裕的机器也可不设,由 Node 默认策略接管(API 启动日志首行会打印当前堆上限,实测为 Heap size limit: 4288 MB)。

8.2 执行生产构建

build:prod 脚本会对 api 与 gauzy(Web 前端)两个应用执行生产构建:

yarn build:prod

实测输出(节选,前端产物体积清单收尾):

vendor.436e33eb7f438ad1.js    | vendor                                                                 |  13.63 MB |
main.ae3b3ef202faf4d7.js      | main                                                                   |   3.35 MB |
styles.ee02681d5625908c.css   | styles                                                                 |   3.14 MB |
scripts.072710d366f32898.js   | scripts                                                                | 208.52 kB |
polyfills.3097c6fe702fb41a.js | polyfills                                                              |  96.30 kB |
runtime.f28f3e39ee690faa.js   | runtime                                                                |  19.57 kB |

                              | Initial total                                                          |  20.44 MB
...
Done in 221.78s.

实测总耗时约 3.7 分钟(Done in 221.78s)。

8.3 核验构建产物

API 与 Web 前端产物分别在 dist/apps/api 与 dist/apps/gauzy:

ls -la /opt/ever-gauzy/dist/apps/api/main.js
find /opt/ever-gauzy/dist -maxdepth 4 -name "index.html"
du -sh /opt/ever-gauzy/dist

实测输出:

-rw-r--r-- 1 root root 16870 Oct 23 03:10 /opt/ever-gauzy/dist/apps/api/main.js
/opt/ever-gauzy/dist/apps/gauzy/index.html
343M    /opt/ever-gauzy/dist

💡 说明:Web 前端是静态文件(index.html + 一批带哈希的 js/css),不需要常驻进程跑编译产物;第九章 9.4 用静态服务器托管它。API 才是常驻进程,入口即 dist/apps/api/main.js。

九、进程托管与启动

💡 技术拓展:Node.js 常驻进程的托管方式对比——

方式原理适用场景
systemd系统级服务管理器,开机自启+崩溃拉起生产服务器标准做法
pm2Node 生态进程管理器,自带日志/监控/集群Node 应用专属、命令顺手
supervisordPython 系进程管理器混合技术栈统一托管
nohup &裸后台,无守护临时调试

本文两种主力方式都给出:9.2 systemd 单元(生产推荐的标准形态)与 9.3 pm2(实测全部回显)。两选一即可,同时用会抢端口。

9.1 首次启动与自动迁移

无论用哪种托管方式,首次启动 API 时应用会自动完成数据库迁移建表与种子账号初始化,启动日志可见迁移标识(实测节选):

Migration isDist: -> true
Migration isElectron: -> false
Migration process.cwd(): -> /opt/ever-gauzy

随后是应用启动完成标志(实测节选):

[Nest] 10042  - 10/23/2026, 3:15:28 AM     LOG [NestFactory] Starting Nest application...
[Nest] 10042  - 10/23/2026, 3:15:28 AM     LOG [NestApplication] Nest application successfully started +6ms

实测从进程拉起到 /api/version 可访问约需 15 秒(含迁移与种子初始化),之后每次重启无需重复迁移。

9.2 方案 A:systemd 托管(生产推荐)

创建 API 服务单元 /etc/systemd/system/gauzy-api.service:

[Unit]
Description=Ever Gauzy API (NestJS)
After=network.target postgresql.service

[Service]
Type=simple
WorkingDirectory=/opt/ever-gauzy
Environment=NODE_ENV=production
ExecStart=/usr/bin/node /opt/ever-gauzy/dist/apps/api/main.js
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

逐项说明:After=postgresql.service 保证数据库先起;Environment=NODE_ENV=production 注入运行模式(.env 其余变量由应用自行读取);Restart=on-failure 在异常退出时 5 秒后拉起。

创建 Web 静态托管服务单元 /etc/systemd/system/gauzy-ui.service(serve 安装见 9.4):

[Unit]
Description=Ever Gauzy Web (static)
After=network.target

[Service]
Type=simple
WorkingDirectory=/opt/ever-gauzy/dist/apps/gauzy
ExecStart=/usr/bin/serve -s -l 4200 .
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

加载并启动(每条命令只作用于一个单元):

systemctl daemon-reload
systemctl enable gauzy-api.service
systemctl start gauzy-api.service
systemctl status gauzy-api.service

status 预期输出(systemd 标准回显):

● gauzy-api.service - Ever Gauzy API (NestJS)
     Loaded: loaded (/etc/systemd/system/gauzy-api.service; enabled; preset: enabled)
     Active: active (running) since ...

Web 前端同理:

systemctl enable gauzy-ui.service
systemctl start gauzy-ui.service
systemctl status gauzy-ui.service

⚠️ 注意:systemd 托管需要带 systemd 的 Linux 真机(Ubuntu 22.04 Server 默认具备)。启动后统一用第十章的接口命令验证。

9.3 方案 B:pm2 托管(实测回显)

安装 pm2 并以 gauzy-api 名称托管 API 进程:

npm install -g pm2@6
pm2 -v
cd /opt/ever-gauzy
NODE_ENV=production pm2 start dist/apps/api/main.js --name gauzy-api

实测输出(节选):

6.0.14
[PM2] Spawning PM2 daemon with pm2_home=/root/.pm2
[PM2] PM2 Successfully daemonized
[PM2] Done.

等待约 15 秒(首启迁移)后查看进程表并验证接口:

pm2 list
curl -s http://localhost:3000/api/version

实测输出:

┌────┬──────────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
│ id │ name         │ namespace   │ version │ mode    │ pid      │ uptime │ ↺    │ status    │ cpu      │ mem      │ user     │ watching │
├────┼──────────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
│ 0  │ gauzy-api    │ default     │ 0.1.0   │ fork    │ 10590    │ 2s     │ 2    │ online    │ 0%       │ 565.1mb  │ root     │ disabled │
└────┴──────────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘
{"name":"api","version":"v111.48.2","commit":"5b3f778e1d12f21992b39b42218fd2fd354c21d6"}

pm2 进程表给出两个关键实测值:API 运行态内存 565.1mb(容量规划参考),状态 online。首启时 ↺ 重启计数短暂出现 2 属正常(迁移期进程退出重启),只要最终 online 且接口可用即可;若持续重启,用 pm2 logs gauzy-api 查看错误(常见原因为数据库未就绪或 3000 端口被占)。

最后配置开机自启(按 pm2 交互提示执行一次即可):

pm2 startup
pm2 save

💡 说明:pm2 只托管了 API;Web 前端是静态文件,用下一节的 serve 托管(也可加入 pm2:pm2 start "serve -s -l 4200 ." --name gauzy-ui)。

9.4 Web 前端静态托管(serve 实测)

💡 技术拓展:静态前端托管的三种常见选择——

方式特点适用场景
serve(Node 生态)单命令起服务,-s 支持单页应用路由回退快速验证、与 Node 技术栈一致
nginx高性能、可同时做反向代理与 TLS生产标准做法
Caddy自动 HTTPS需要快速上 TLS 的公网站点

本文用 serve 完成托管与验证(-s 开启单页应用回退);生产上线推荐改用 nginx 托管同一目录并反代 /api 到 3000 端口。

安装 serve 并托管前端构建产物目录:

npm install -g serve@14
serve --version
cd /opt/ever-gauzy/dist/apps/gauzy
serve -s -l 4200 .

实测输出:

14.2.6
 INFO  Accepting connections at http://localhost:4200

⚠️ 注意:-s(single page)参数必须加。实测不加 -s 时根路径 200、但深路由(如 /auth/login)返回 404,加了之后深路由回退到 index.html 返回 200(实测对比见 FAQ Q3)。-l 4200 指定监听端口,与 .env 的 CLIENT_BASE_URL 保持一致。

十、部署验证

10.1 API 接口验证

版本接口(应返回所装版本与 commit):

curl -s http://localhost:3000/api/version

实测输出:

{"name":"api","version":"v111.48.2","commit":"5b3f778e1d12f21992b39b42218fd2fd354c21d6"}

健康检查(关注 HTTP 状态码):

curl -s -o /dev/null -w '%{http_code}\n' http://localhost:3000/api/health

实测输出:

200

API 启动日志中的健康检查详情(实测节选)——数据库、存储、缓存三项全部 up:

Health check result: {"status":"ok","info":{"database":{"status":"up"},"storage":{"status":"up"},"cache":{"status":"up","cacheType":"memory"}},"error":{},"details":{"database":{"status":"up"},"storage":{"status":"up"},"cache":{"status":"up","cacheType":"memory"}}}

登录接口验证种子账号(响应节选,能返回 user 对象即账号初始化成功):

curl -s -X POST http://localhost:3000/api/auth/login -H 'Content-Type: application/json' -d '{"email":"admin@ever.co","password":"q1w2e3r4"}' | head -c 260

实测输出(节选):

{"user":{"deletedAt":null,"createdAt":"2026-10-23T03:15:27.640Z","updatedAt":"2026-10-23T03:15:29.675Z","createdByUserId":null,"updatedByUserId":null,"deletedByUserId":null,"id":"b57635ea-d2b1-4bc4-bf7c-3a099ffbfa9a","isActive":true,"isArchived":false,...

10.2 Web 前端验证

curl -s -o /dev/null -w '%{http_code}\n' http://localhost:4200/
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:4200/auth/login
curl -s http://localhost:4200/ | head -c 200

实测输出:

200
200
<!DOCTYPE html>
<html lang="en" data-beasties-container>
        <head>
                <meta charset="utf-8">
                <title>Gauzy</title>

根路径与深路由均 200,返回的即是 Gauzy 前端页面,浏览器访问 http://<服务器IP>:4200 可进入登录页。

10.3 数据落库验证

用 4.4 创建的库直接查表与数据量(注意表名是单数 user,需加双引号,实测见 FAQ Q5):

su - postgres -c "psql -d gauzy -tAc 'select count(*) from \"user\";'"

实测输出:

3

3 条即 7.3 配置的三个种子账号(超级管理员/管理员/员工)已自动初始化。API 侧的健康检查同样会输出用户计数(启动日志实测:Database (TypeORM) users count ... is: 3),两处互相印证。

至此安装闭环完成:PostgreSQL 17 + Node 24 依赖链 → 源码构建 → 托管运行 → 接口/前端/数据库三路验证全部通过。

十一、常见问题(FAQ)

Q1:yarn bootstrap 期间报 node-gyp ERR! not ok(better-sqlite3 重编译失败),要重装吗? 不需要。实测该报错出现在 SQLite 驱动联动的原生模块重编译环节,bootstrap 收尾的自检会逐个核验二进制:bcrypt 与 better-sqlite3 均 ✔(完整实录见 6.3)。本文 PostgreSQL 模式不使用 better-sqlite3,登录等接口实测正常。若需本地编译原生模块,先 apt-get install -y build-essential python3 再重试。

Q2:curl 访问 http://localhost:3000 或 :4200 返回 502? 若当前 shell 设置了 http_proxy/https_proxy 环境变量(如接入企业代理),curl 对 localhost 的请求也会被送进代理,代理回源不到本机端口就返回 502。实测同一环境下:带代理变量请求返回 502,加 --noproxy "*" 后返回 200。 permanently 解法是把 localhost 与 127.0.0.1 加入 no_proxy。

Q3:serve 起的前端根路径正常,刷新 /auth/login 等深路由 404? serve 默认按文件路径精确匹配,单页应用的深路由没有对应文件。实测对比:不加参数时 curl http://localhost:4200/auth/login 返回 404;改用 serve -s -l 4200 .(单页应用模式)后同一路径返回 200。第九章 9.4 的命令已带 -s。

Q4:pm2 delete gauzy-api 提示 No process found,但 3000 端口仍有服务响应? 说明 pm2 守护进程此前已停止(如被手工 kill),留下孤儿 node 进程继续监听端口——实测该状态下 pm2 delete 报 No process found、pm2 kill 正常输出,而 /api/version 仍返回 200。处理:按端口直接结束残留进程再核验(实测输出 000 表示已无监听):

fuser -k 3000/tcp
fuser -k 4200/tcp
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:3000/api/version

Q5:psql -d gauzy -c 'select count(*) from users;' 报 ERROR: relation "users" does not exist? Ever Gauzy 的用户表名是单数 user,不是 users,且 user 是 SQL 保留字必须加双引号。实测正确查询与输出(返回 3):

su - postgres -c "psql -d gauzy -tAc 'select count(*) from \"user\";'"

Q6:构建中途被 OOM 杀掉或卡死? 构建是全流程中最吃内存的一步。实测在 32GB 主机上显式设置 export NODE_OPTIONS=--max-old-space-size=12288 后 yarn build:prod 稳定通过(221.78s)。内存不足的机器建议把堆上限下调(如 4096),并关闭其他占用内存的进程;或放弃本地构建,改用 《Ever Gauzy 111.48.2 Docker Compose 部署指南》 的镜像形态。

十二、卸载与清理

卸载按「停进程 → 备份(可选)→ 删库删账号 → 删源码 → 卸载系统包与源配置」顺序执行,以下全部步骤实测通过。

12.1 停止应用进程

pm2 托管的先杀守护:

pm2 kill

实测输出:

[PM2] [v] All Applications Stopped
[PM2] [v] PM2 Daemon Stopped

systemd 托管的改为停用对应单元:

systemctl stop gauzy-api.service
systemctl stop gauzy-ui.service

再按端口清理残留监听并核验(000 即已无服务):

fuser -k 3000/tcp
fuser -k 4200/tcp
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:3000/api/version

实测输出:

000

12.2 备份并删除数据库与账号

如需保留业务数据,先导出(标准 pg_dump 逻辑导出,文件落在 /root/gauzy-backup.sql):

su - postgres -c 'pg_dump gauzy > /root/gauzy-backup.sql'

删除业务库与专用账号,并核验已不存在(两条查询均返回空即删净):

su - postgres -c 'dropdb gauzy'
su - postgres -c 'dropuser gauzy'
su - postgres -c "psql -tAc \"SELECT datname FROM pg_database WHERE datname='gauzy';\""
su - postgres -c "psql -tAc \"SELECT usename FROM pg_user WHERE usename='gauzy';\""

实测输出:两条核验查询均无返回行(库与账号已删除)。

12.3 删除源码与构建产物

rm -rf /opt/ever-gauzy
ls /opt/

实测输出:/opt/ 下已无 ever-gauzy 目录(约 16GB 释放)。

12.4 卸载 PostgreSQL 与 Node.js 系统包

先停数据库服务:

service postgresql stop

实测输出:

 * Stopping PostgreSQL 17 database server
   ...done.

卸载数据库包与客户端:

apt-get purge -y postgresql-17 postgresql-client-17

实测输出(节选):

Removing postgresql-client-17 (17.11-1.pgdg22.04+2) ...
Purging configuration files for postgresql-17 (17.11-1.pgdg22.04+2) ...

⚠️ 注意:实测中 postgresql-17 的 postrm 阶段可能报 post-removal script subprocess returned error exit status 1(脚本尝试停止一个已不存在的集群)。兜底处理:先手工删除集群再重试,并用包状态核验收敛(pc 表示本体已删、仅剩配置残留):

pg_dropcluster 17 main --stop
apt-get purge -y postgresql-17
dpkg -l postgresql-17 | tail -1

实测输出(节选):

pc  postgresql-17  17.11-1.pgdg22.04+2  amd64  The World's Most Advanced Open Source Relational Database

卸载 Node.js(全局包目录会残留,一并删除):

apt-get purge -y nodejs
rm -rf /usr/lib/node_modules
node -v

实测输出:

Removing nodejs (24.22.1-1nodesource1) ...
dpkg: warning: while removing nodejs, directory '/usr/lib/node_modules' not empty so not removed
bash: node: command not found

node: command not found 即卸载完成。最后清理 apt 源配置与无用依赖:

rm -f /etc/apt/sources.list.d/pgdg.list /etc/apt/sources.list.d/nodesource.list
apt-get autoremove -y

实测输出(节选):

Removing xz-utils (5.2.5-2ubuntu1.2) ...
Processing triggers for libc-bin (2.35-0ubuntu3.15) ...

十三、参考链接