Umami 3.4 配置参数详解
系统梳理 Umami 3.4.0 全部配置参数:数据库连接、端口、APP_SECRET、采集开关与隐私模式等,含参数总览表与生产配置模板,运行时行为类参数均实测验证并照录回显。
Umami 3.4 配置参数详解
目标:系统梳理 Umami 3.4.0 的全部配置参数——每个参数的含义、引入版本、默认值、修改方式与实测验证手段;运行时行为类参数(APP_SECRET/TRACKER_SCRIPT_NAME/COLLECT_API_ENDPOINT/CLIENT_IP_HEADER/PORT/DISABLE_TELEMETRY/PRIVATE_MODE 等)均在 Ubuntu 22.04 LTS(x86_64)+ Umami 3.4.0 + PostgreSQL 16.15 环境逐项实测,实测回显逐条照录。
一、环境信息
- 操作系统:Ubuntu 22.04 LTS(x86_64)
- Umami:3.4.0(镜像
ghcr.io/umami-software/umami:postgresql-latest,服务内版本号实测3.4.0) - 数据库:PostgreSQL 16.15;Redis:未启用(可选组件)
- 服务监听:0.0.0.0:3000(实测实例对外端口 13000,另起 13001~13007 端口做参数对照组)
- 参考底稿:官方文档 Environment Variables 页(docs.umami.is,2026-10-17 抓取),逐项标注官方引入版本
- 管理账号:admin / q1w2e3r4(演示口令)
二、前置条件
- Umami 3.4.0 已部署并可访问(心跳
{"ok":true}),部署过程见《Umami Docker Compose 部署指南》; - 修改参数的方式:在编排文件
environment:段增删变量后docker compose up -d重建服务生效(环境变量驱动,无配置文件;直接docker run的用户等价改-e参数重建服务); - 本文多个验证项需要"同库双实例"对照:两实例连同一数据库、不同 APP_SECRET/端口,用于验证令牌隔离等行为。命令模式如下(实测用例):
docker run -d --name umami-envtest-a --network umami_default -p 13001:3000 \
-e DATABASE_URL='postgresql://umami:q1w2e3r4@umami-db:5432/umami' \
-e DATABASE_TYPE=postgresql \
-e APP_SECRET='EnvTestSecretA-0123456789abcdef' \
ghcr.io/umami-software/umami:postgresql-latest
实测回显(启动后心跳):
{"ok":true}
三、参数查看与修改方式
Umami 没有主配置文件,全部参数通过环境变量注入,分三类:
- 运行时变量:服务启动时读取,改后重启服务即生效(如 APP_SECRET、PORT、DISABLE_TELEMETRY);
- 构建时变量:只在构建镜像时生效(如 BASE_PATH、ALLOWED_FRAME_URLS、DATABASE_TYPE),官方文档明确标注"Build time variables are only recognized during the build process";用官方 Docker 镜像时此类变量多数已固化,需要自定义构建才能改;
- 数据库内配置:用户偏好(语言/时区)、网站设置、团队与角色等存库,在控制台或 API 修改,不属于环境变量。
修改与生效流程(Compose 部署):
cd /opt/umami-doc-lab
vi compose.yml # 在 umami 服务的 environment: 段增删变量
docker compose up -d # 重建服务生效
docker compose logs --tail 5 umami
实测回显(重建后正常拉起):
umami-app | ✓ Database is up to date.
umami-app | ▲ Next.js 16.3.4
umami-app | - Local: http://localhost:3000
umami-app | ✓ Ready in 0ms
验证参数是否生效的通用手段(下文逐参数演示):
- 端口/监听类:心跳与
curl -I直连新端口; - 鉴权类:跨实例用旧令牌请求 401 与否;
- 采集类:请求新脚本/新端点路径看 200/404;
- 隐私类:
/telemetry.js回显内容(正常返回像素注入 JS,关闭时返回/* telemetry disabled */)。
四、参数总览
运行时变量(官方文档口径 + 本文实测项打 ✅):
| 变量 | 版本 | 默认值 | 作用 | 实测 |
|---|---|---|---|---|
DATABASE_URL | v1.0.0 | 无(唯一必填) | 数据库连接串 | ✅ |
DATABASE_TYPE | v2.0.0 | 无 | 数据库类型,Docker 构建期必填 | ✅ |
APP_SECRET | v1.0.0 | 无(强烈建议设置) | 令牌签名密钥,每实例唯一 | ✅ |
PORT / HOSTNAME | v1.0.0 | 3000 / - | 监听端口/主机名 | ✅(PORT) |
CLIENT_IP_HEADER | v1.24.0 | 无(自动取连接 IP) | 指定存放客户端 IP 的头 | ✅ |
COLLECT_API_ENDPOINT | v1.34.0 | /api/send | 采集端点改名(防拦截) | ✅ |
TRACKER_SCRIPT_NAME | v1.26.0 | script.js | 统计脚本改名(防拦截) | ✅ |
DISABLE_TELEMETRY | v2.0.0 | 未设(开启遥测) | 关闭匿名遥测 | ✅ |
PRIVATE_MODE | v2.11.0 | 未设 | 切断全部外网请求 | ✅ |
SALT_ROTATION | v3.1.0 | month | 会话盐值轮换周期 | 官方口径 |
REDIS_URL | v3.0.1 | 未设(关闭) | 缓存/协调用 Redis | 官方口径 |
GEO_DATABASE_URL | v2.0.0 | 未设 | MaxMind 兼容 MMDB 下载地址 | 官方口径 |
IGNORE_IP | v1.0.0 | 未设 | 排除的 IP/CIDR 列表 | 官方口径 |
IGNORE_HOSTNAME | v1.0.0 | 未设 | 排除的主机名 | 官方口径 |
IGNORE_PATHS | v1.0.0 | 未设 | 排除的路径(通配) | 官方口径 |
REMOVE_TRAILING_SLASH | v1.26.0 | 未设 | 去除 URL 尾斜杠 | 官方口径 |
DISABLE_BOT_CHECK | v2.0.0 | 未设(排除机器人) | 关闭机器人识别 | 官方口径 |
DISABLE_LOGIN | v1.26.0 | 未设 | 关闭登录页 | 官方口径 |
DISABLE_UPDATES | v1.33.0 | 未设 | 关闭新版本检查 | 官方口径 |
DISABLE_UI | — | 未设 | 仅暴露采集接口(自用嵌入式) | 官方口径 |
DISABLE_ADMIN | — | 未设 | 关闭管理后台入口 | 官方口径 |
FORCE_SSL | v1.0.0 | 未设 | 全响应加 HSTS 头 | 官方口径 |
LOG_LEVEL | — | info | 日志级别 | 官方口径 |
LOG_QUERY | v2.0.0 | 未设 | 控制台打印 SQL(开发用) | 官方口径 |
DEBUG | v2.0.0 | 未设 | 指定模块日志(umami:auth 等) | 官方口径 |
ENABLE_TEST_CONSOLE | v2.0.0 | 未设 | /console 测试页手动打点 | 官方口径 |
FAVICON_URL | v2.18.0 | icons.duckduckgo.com | 站点图标服务地址 | 官方口径 |
CORS_MAX_AGE | v2.0.0 | 86400 | CORS 预检缓存秒数 | 官方口径 |
SKIP_LOCATION_HEADERS | v2.15.0 | 未设 | 忽略 CDN 地理头,强制用本地库 | 官方口径 |
TWO_FACTOR_ENCRYPTION_KEY | v3.3.0 | 未设 | 2FA 密钥(64 位 hex),启用 2FA 前必配 | 官方口径 |
USE_UUIDV7 | v3.0.2 | 未设(UUIDv4) | 标识改用 UUIDv7 | 官方口径 |
DIRECT_DATABASE_URL | v3.2.0 | 未设 | 迁移命令专用连接串(pooled 场景) | 官方口径 |
MCP_ENABLED | v3.4.0 | 未设(关闭) | 启用 /mcp 端点 | 官方口径 |
构建时变量(改这些需要自行构建镜像):
| 变量 | 版本 | 作用 |
|---|---|---|
ALLOWED_FRAME_URLS | v2.3.0 | 允许 iframe 嵌入本应用的外部 URL 列表 |
BASE_PATH | v1.9.0 | 子路径部署前缀(如 /umami),需反代配合 |
DEFAULT_CURRENCY / DEFAULT_LOCALE | v3.1.0 | 用户未选偏好时的默认币种/语言 |
BUILD_GEO / SKIP_BUILD_GEO | v3.0.0 / v3.1.0 | 构建期 GeoIP 库步骤开关 |
SKIP_DB_CHECK / SKIP_DB_MIGRATION | v2.0.0 | 跳过构建期库检查/迁移 |
💡 说明:表中"官方口径"表示含义与默认值以官方文档为准、未在本文环境单独复现;打 ✅ 的参数均附实测小节。
DISABLE_UI/DISABLE_ADMIN/LOG_LEVEL为官方仓库示例 compose 与镜像默认值中出现的口径。
关键差异与如何读这张表:先保证唯一必填的 DATABASE_URL,再按需求挑"安全三件套"(APP_SECRET/FORCE_SSL/CLIENT_IP_HEADER)与"防拦截两件套"(TRACKER_SCRIPT_NAME/COLLECT_API_ENDPOINT);隐私敏感环境加 PRIVATE_MODE=1;其余按需。
五、核心参数分类详解
本节按「数据库 → 安全 → 采集与追踪 → 隐私 → 服务器与日志 → 缓存与扩展」六类展开;每项给出:取值/默认值、修改方法、实测验证(命令 + 真实回显)。
5.1 数据库连接:DATABASE_URL / DATABASE_TYPE / DIRECT_DATABASE_URL
DATABASE_URL 是唯一必填参数,指向 PostgreSQL 或 MySQL 连接串;DATABASE_TYPE=postgresql|mysql 声明类型(官方口径:Docker 构建期必填)。启动日志可确认连接与迁移状态(实测):
umami-app | ✓ DATABASE_URL is defined.
umami-app | ✓ Database connection successful.
umami-app | ✓ Database version check successful.
umami-app | Datasource "db": PostgreSQL database "umami", schema "public" at "umami-db:5432"
umami-app | 26 migrations found in prisma/migrations
官方另有 DIRECT_DATABASE_URL(v3.2.0,供 Prisma 迁移命令使用的直连串——当 DATABASE_URL 指向 PgBouncer 等 pooled 连接时,迁移须走直连串)。
实测:密码含特殊字符时"未编码"与"URL 编码"两种写法对照(数据库用户 umami2,真实密码 p@ss:w0rd):
# 写法一:密码原样写(未编码)
docker run -d --name umami-envtest-bad --network umami_default -p 13009:3000 \
-e DATABASE_URL='postgresql://umami2:p@ss:w0rd@umami-db:5432/umami' \
-e DATABASE_TYPE=postgresql \
ghcr.io/umami-software/umami:postgresql-latest
实测回显(心跳 200,启动正常):
✓ DATABASE_URL is defined.
✓ Database connection successful.
✓ Ready in 0ms
{"ok":true}
# 写法二:URL 编码(@ → %40,: → %3A)
docker run -d --name umami-envtest-good --network umami_default -p 13010:3000 \
-e DATABASE_URL='postgresql://umami2:p%40ss%3Aw0rd@umami-db:5432/umami' \
-e DATABASE_TYPE=postgresql \
ghcr.io/umami-software/umami:postgresql-latest
实测回显(心跳 200,启动正常):
✓ DATABASE_URL is defined.
✓ Database connection successful.
✓ Ready in 0ms
{"ok":true}
结论:Prisma 按"最后一个 @"拆分凭据与主机,两种写法实测都能连通;但 URL 编码是官方与 URI 规范推荐写法(密码含 /、#、? 等歧义字符时未编码会破坏解析),生产统一用编码写法。最常见的连接失败是"连接串里的密码与库内真实密码不一致",实测错误形态(密码解析后与库不符):
✗
Invalid `prisma.$queryRaw()` invocation:
Raw query failed. Code: `28P01`. Message: `password authentication failed for user "umami"`
5.2 安全与令牌:APP_SECRET / FORCE_SSL / ALLOWED_FRAME_URLS / TWO_FACTOR_ENCRYPTION_KEY
APP_SECRET(v1.0.0):签发登录令牌与 cache 令牌的密钥,官方要求"每安装实例唯一",生成方式 openssl rand -hex 32。不设置时使用内置默认,多实例会互相认可对方令牌,属安全隐患。
实测验证(同库双实例、不同 APP_SECRET,令牌互不通用):
# A 实例(APP_SECRET=EnvTestSecretA-...,端口 13001)登录拿令牌
TOKEN_A=$(curl -s -X POST http://localhost:13001/api/auth/login \
-H 'Content-Type: application/json' \
-d '{"username":"admin","password":"q1w2e3r4"}' | python3 -c 'import sys,json;print(json.load(sys.stdin)["token"])')
echo "token_len=${#TOKEN_A}"
# 令牌在 A 实例可用
curl -s -o /dev/null -w 'A_token_on_A=%{http_code}\n' \
-H "Authorization: Bearer $TOKEN_A" http://localhost:13001/api/websites
# 同一令牌到 B 实例(APP_SECRET=EnvTestSecretB-...,端口 13002)
curl -s -w '\n' -o /dev/null -w 'A_token_on_B=%{http_code}\n' \
-H "Authorization: Bearer $TOKEN_A" http://localhost:13002/api/websites
实测回显:
token_len=624
A_token_on_A=200
A_token_on_B=401
结论:APP_SECRET 不同的实例间令牌互不认可(401);更换 APP_SECRET 会使该实例所有已签发令牌立即失效(运维上等价于"全员强制下线")。采集端点 /api/send 不受影响(无登录态)。
FORCE_SSL(v1.0.0):设 1 后所有响应带 Strict-Transport-Security 头,强制浏览器后续走 HTTPS(需前置反代终结 TLS)。ALLOWED_FRAME_URLS(v2.3.0,构建时):空格分隔的 URL 列表,允许这些站点 iframe 嵌入 Umami 控制台。TWO_FACTOR_ENCRYPTION_KEY(v3.3.0):64 位 hex(256 位),未配置时任何用户无法开启 2FA(v3.3.0 起功能存在)。
5.3 采集与追踪:TRACKER_SCRIPT_NAME / COLLECT_API_ENDPOINT / CLIENT_IP_HEADER
TRACKER_SCRIPT_NAME(v1.26.0):把统计脚本从默认 /script.js 改名(.js 后缀可不写,也支持带路径),用于绕过广告拦截器对 umami 关键字的规则。实测(B 实例设 TRACKER_SCRIPT_NAME=analytics):
curl -s -o /dev/null -w 'script.js_on_B=%{http_code}\n' http://localhost:13002/script.js
curl -s -o /dev/null -w 'analytics.js_on_B=%{http_code}\n' http://localhost:13002/analytics.js
curl -s -o /dev/null -w 'analytics_on_B=%{http_code}\n' http://localhost:13002/analytics
实测回显:
script.js_on_B=200
analytics.js_on_B=200
analytics_on_B=200
三个路径都 200——改名后新路径生效,但默认路径并不因此关闭(实测 /script.js 与 /analytics、/analytics.js 内容 MD5 完全一致:7edb400174f8178e695beb2ad82c40b4)。页面嵌码时改用新名:
<script defer src="http://<host>:13002/analytics.js" data-website-id="..."></script>
COLLECT_API_ENDPOINT(v1.34.0):把采集端点从默认 /api/send 改走自定义路由。实测(E 实例设 COLLECT_API_ENDPOINT=/collect-test):
curl -s -o /dev/null -w 'collect=%{http_code}\n' -X POST http://localhost:13007/collect-test \
-H 'Content-Type: application/json' \
-H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/131.0.0.0' \
-d '{"type":"event","payload":{"website":"bd69fdbf-f8bd-48c3-93d4-877c51c93fb4","hostname":"demo.example.com","language":"zh-CN","screen":"1920x1080","url":"/via-custom-endpoint"}}'
curl -s -o /dev/null -w 'api_send=%{http_code}\n' -X POST http://localhost:13007/api/send \
-H 'Content-Type: application/json' \
-H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/131.0.0.0' \
-d '{"type":"event","payload":{"website":"bd69fdbf-f8bd-48c3-93d4-877c51c93fb4","hostname":"demo.example.com","language":"zh-CN","screen":"1920x1080","url":"/x"}}'
实测回显:
collect=200
api_send=404
与脚本改名不同:端点改名后默认 /api/send 彻底关闭(404),浏览器脚本与自建上报都要改走新路由。/api/config(无认证)会回显隐私与开关类配置(实测 E 实例,PRIVATE_MODE=1 体现为 privateMode:true):
{"cloudMode":false,"privateMode":true,"sessionDeletionEnabled":true,"telemetryDisabled":false,"updatesDisabled":false}
CLIENT_IP_HEADER(v1.24.0):反代/CDN 场景下从指定请求头取客户端 IP;不设时 Umami 取 TCP 连接来源 IP(拿到的将是反代地址)。该参数影响会话识别(IP+UA+hostname 哈希)。实测(C 实例设 CLIENT_IP_HEADER=x-real-ip,同一 UA 连续上报,观察返回的 sessionId 前 8 位):
# 不同 x-real-ip → 不同会话
curl -s -X POST http://localhost:13003/api/send -H 'Content-Type: application/json' \
-H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/131.0.0.0" \
-H 'x-real-ip: 8.8.4.4' \
-d '{"type":"event","payload":{"website":"a9e10b5a-f4c0-41ec-834f-0775781b064a","hostname":"ip.example.com","language":"zh-CN","screen":"1920x1080","url":"/ip-a"}}'
实测回显(三条分别对应:不同头值→新会话;同头值→同会话;仅 x-forwarded-for 不同→同会话):
-- 同UA + 不同 x-real-ip --
session: a43558e2 visit: 2420aaf2
session: 76dd3e39 visit: 44cf78dc
-- 同UA + 相同 x-real-ip(重复8.8.4.4) --
session: a43558e2 visit: 2420aaf2
-- 同UA + 仅 x-forwarded-for(不同) --
session: a43558e2 visit: 2420aaf2
session: a43558e2 visit: 2420aaf2
结论:设 CLIENT_IP_HEADER=x-real-ip 后,会话标识只随 x-real-ip 变化(x-forwarded-for 被忽略);头值相同时同 IP+UA 判为同一会话。注意头名必须全小写,且要保证该头确实由可信反代注入(客户端可伪造该头时会影响统计真实性)。对应 stats 实测:5 PV / 4 visitors(两个 x-real-ip 各算访客,4 条 x-f-for 上报归属 8.8.4.4 会话)。
💡 技术拓展:反代传真实 IP 的常见头对比——
头 注入方 特点 X-Real-IPNginx 常用配置 单值,由最外层反代设置 X-Forwarded-For事实标准(多级链) 逗号分隔,可被客户端伪造首段 CF-Connecting-IPCloudflare CF 出口真实 IP,可信度取决于来源校验 PROXY协议HAProxy/部分 LB 传输层附加,需应用支持 本文实测选
x-real-ip:单值、语义明确,配合"仅信任反代注入"的网络策略最稳妥。
5.4 隐私与数据卫生:DISABLE_TELEMETRY / PRIVATE_MODE / IGNORE_IP / IGNORE_PATHS / REMOVE_TRAILING_SLASH / SALT_ROTATION
DISABLE_TELEMETRY=1(v2.0.0):关闭向官方遥测像素 https://i.umami.is/a.png?v=3.4.0 的匿名版本上报。实测对照:
curl -s http://localhost:13003/telemetry.js | head -c 120
实测回显(未关闭的实例,正常注入像素脚本,节选):
var i = document.createElement("script"); ...
curl -s http://localhost:13004/telemetry.js
实测回显(DISABLE_TELEMETRY=1 实例):
/* telemetry disabled */
PRIVATE_MODE=1(v2.11.0):切断应用所有对外网络请求(遥测、图标服务等全部停止;同套代码里 DISABLE_TELEMETRY || PRIVATE_MODE 命中即关闭遥测,实测 E 实例仅设 PRIVATE_MODE 时 /telemetry.js 同样返回 /* telemetry disabled */)。离线/内网部署必设。
IGNORE_IP(v1.0.0):逗号分隔的 IP/CIDR 排除列表,命中流量不入库(如 IGNORE_IP=192.168.0.1, 10.0.0.0/24)。IGNORE_HOSTNAME(v1.0.0)排除指定主机名,IGNORE_PATHS(v1.0.0)排除路径(官方支持通配,如 /admin*)。三项均在采集阶段过滤,改后无需迁移数据即生效。
REMOVE_TRAILING_SLASH=1(v1.26.0):上报 URL 去尾斜杠,把 /docs/ 与 /docs 归并为同一路径统计。
SALT_ROTATION(v3.1.0,默认 month):匿名会话盐值的轮换周期,可取 day/week/month/year/none。作用:轮换后同一访客(同 IP+UA)会生成新的会话标识,进一步降低长期跟踪能力;设 none 则不轮换(会话连续性最好,跨期归因更稳)。官方默认 month,即"月度轮换"。
5.5 服务器与日志:PORT / HOSTNAME / LOG_LEVEL / DISABLE_UPDATES / DISABLE_UI / DISABLE_ADMIN
PORT(v1.0.0,默认 3000):服务监听端口。实测(D 实例设 PORT=3001,宿主映射 -p 13004:3001):
curl -s http://localhost:13004/api/heartbeat
实测回显:
{"ok":true}
💡 说明:官方文档对
HOSTNAME/PORT的口径是"非 Docker 环境需用pnpm run start-env启动才读取这两项";官方 Docker 镜像的入口脚本会读取 PORT,实测 3001 监听成功。Compose 用户更推荐保持服务内 3000、改宿主侧-p映射即可。
DISABLE_UPDATES=1(v1.33.0):关闭控制台"有新版本"检查(离线环境建议,配合 PRIVATE_MODE 更彻底)。DISABLE_UI=1:只保留采集接口、不渲染控制台(把 Umami 当纯接收端时的极简形态)。DISABLE_ADMIN=1:隐藏管理后台入口。LOG_LEVEL:日志级别(info 默认);LOG_QUERY=1(v2.0.0)在开发模式打印 SQL;DEBUG(v2.0.0)按模块开日志(可选值 umami:auth、umami:clickhouse、umami:kafka、umami:middleware、umami:prisma,如 DEBUG=umami:*)。DISABLE_BOT_CHECK=1(v2.0.0)关闭机器人过滤(默认爬虫流量不入库)。DISABLE_LOGIN=1(v1.26.0)关闭登录页(用反代层做认证时配合)。
ENABLE_TEST_CONSOLE=1(v2.0.0):开启 /console 内部测试页(需管理员登录),可在页面手动触发 pageview/event,用于联调埋点。
5.6 缓存与扩展:REDIS_URL / GEO_DATABASE_URL / SKIP_LOCATION_HEADERS / FAVICON_URL / CORS_MAX_AGE / USE_UUIDV7 / MCP_ENABLED
REDIS_URL(v3.0.1,可选):配置后启用缓存与多实例协调特性(官方口径 redis://localhost:6379);不配置则相关特性关闭,单实例无需 Redis。GEO_DATABASE_URL(v2.0.0):MaxMind 兼容 MMDB 下载地址(如 GeoLite2-City.mmdb),用于 IP 地理定位;未配置且无 CDN 地理头时国家维度为空(实测 metrics?type=country 返回 [])。SKIP_LOCATION_HEADERS=1(v2.15.0):忽略 CDN 注入的地理头、强制用本地库(CDN 只给国家不给地区/城市时的正确姿势)。
FAVICON_URL(v2.18.0):站点图标服务,默认 https://icons.duckduckgo.com/ip3/{{domain}}.ico,可换 Google/Clearbit(注意:默认图标服务是外联请求,PRIVATE_MODE 下图标一并停用)。CORS_MAX_AGE(v2.0.0):CORS 预检缓存秒数,默认 86400(24 小时)。USE_UUIDV7=1(v3.0.2):新生成的标识改用 UUIDv7(按时间有序,索引更友好;已有派生标识不变)。MCP_ENABLED=1(v3.4.0):启用 /mcp 的 Model Context Protocol 端点,供 AI 客户端查询统计(默认关闭)。
六、生产配置模板
模板一:小站/内网(2GB 内存、单实例、PostgreSQL 同机):
environment:
DATABASE_URL: postgresql://umami:强口令@umami-db:5432/umami
DATABASE_TYPE: postgresql
APP_SECRET: <openssl rand -hex 32 生成>
FORCE_SSL: 1
DISABLE_TELEMETRY: 1
IGNORE_IP: 10.0.0.0/8,192.168.0.0/16
适用:日均 PV 10 万以内,关注隐私与离线;FORCE_SSL 需前置 HTTPS 反代。
模板二:多实例/大流量(16GB 内存、2 实例、独立 PG、前置 Nginx+Redis):
environment:
DATABASE_URL: postgresql://umami:强口令@pg-primary:5432/umami
DIRECT_DATABASE_URL: postgresql://umami:强口令@pg-primary:5432/umami
DATABASE_TYPE: postgresql
APP_SECRET: <所有实例保持一致,否则令牌互不认可>
REDIS_URL: redis://redis:6379
CLIENT_IP_HEADER: x-real-ip
GEO_DATABASE_URL: https://example.com/GeoLite2-City.mmdb
DISABLE_UPDATES: 1
LOG_LEVEL: info
适用:日均 PV 百万级、需要横向扩容;多实例必须统一 APP_SECRET(5.2 实测不同密钥令牌不互通),REDIS_URL 提供缓存与协调,GEO 库补全地理维度。
七、常见问题
Q1:改了 APP_SECRET 后用户全部掉线? 正常现象。令牌由 APP_SECRET 签发,换密钥即全部失效(实测同库双实例令牌 401 的同源行为),重新登录即可;采集上报不受影响。
Q2:设置了 TRACKER_SCRIPT_NAME 后 /script.js 还能访问? 能。脚本改名是"新增别名"(实测三条路径同内容 200),页面嵌码改用新名即可绕拦截器;而 COLLECT_API_ENDPOINT 是"替换"(实测旧端点 404)。两者语义不同,别混用预期。
Q3:CLIENT_IP_HEADER 设了但会话数不变? 检查三点:头名小写、请求确实带该头、值真的在变。实测中 x-forwarded-for 变化不影响会话(参数只认指定头);若该头由客户端可伪造,统计会被注入脏会话。
Q4:IGNORE_IP 排除了自己但统计还有内网流量?
确认写法(逗号分隔、CIDR 合法)且变量在 umami 服务实例上生效(docker compose up -d 重建过);另注意 IGNORE_IP 过滤的是采集入库,历史数据不会回溯删除。
Q5:SALT_ROTATION 改成 none 有什么影响? 同 IP+UA 的访客在跨月后不再生成新会话标识,跨期报表的"新访客"口径会变少;配合 IGNORE_IP 使用时无额外冲突。默认 month 是官方平衡隐私与统计口径的选择,无特殊需求不建议改。
Q6:MCP /mcp 端点开不了?
需 MCP_ENABLED=1 且为 v3.4.0+(该参数 v3.4.0 引入),改后重建服务;用 MCP 客户端连 http://<host>:<port>/mcp 验证。