Shlink 5.1.8 配置参数详解

Shlink 5.1.8 配置参数详解:67 项环境变量全清单分组总览、四级加载机制与 _FILE secret 注入,域名/短码/数据库/跳转/统计/缓存/删除保护九大维度逐项实测。

ShlinkPHP自托管Docker2026/10/30

Shlink 5.1.8 配置参数详解

本文基于 shlinkio/shlink 5.1.8 实测(2026-10-30,四组单容器实验栈逐项验证配置项行为,全部命令与回显均为真实运行结果;配置项清单与默认值溯源自 v5.1.8 源码 module/Core/src/Config/EnvVars.php)。

一、环境信息与实验说明

  • 服务版本:shlinkio/shlink:5.1.8(REST 健康端点实测返回 "version":"5.1.8");
  • 实验形态:四组 SQLite 单容器实例(免数据库依赖,最快暴露配置行为),另起一个 redis:7 容器专测 Redis 缓存配置;
  • 端口规划:8136/8137/8138/8139 分别对应 A/B/C/D 四组实验实例(宿主常用端口已被占用时的高位映射做法同系列部署篇);
  • 取证口径:应用层环境变量全集从 v5.1.8 源码 EnvVars 枚举逐项核对(67 项),另含 RoadRunner 运行时层 5 项与 Docker 镜像层内置变量;行为语义以「源码定义 + 实测回显」双重印证。

二、配置加载机制与查看方式

2.1 四级加载优先级

Shlink 5.1.8 的配置加载逻辑(源码 EnvVars::loadFromEnv())按以下顺序取值,前者命中即止:

  1. 环境变量:容器 -e / Compose environment: 注入,最高优先级;
  2. <变量名>_FILE secret 文件:任意配置项都支持追加 _FILE 后缀(如 DB_PASSWORD_FILE=/run/secrets/db_pass),Shlink 读取文件内容作为该变量的值——这是官方为 Docker secrets 场景设计的通道,数据库口令等敏感项建议走此路,避免明文出现在编排文件;
  3. 交互安装器落盘值:宿主机直装时 shlink-installer init 把应答写入本地配置文件,容器形态下 entrypoint 以 --no-interaction 执行安装器,主要消费默认值与环境变量;
  4. 内置默认值:EnvVars::defaultValue() 硬编码,如 DB_DRIVER 默认 sqlite、MEMORY_LIMIT 默认 512M、TRACK_ORPHAN_VISITS 默认 true、CORS_ALLOW_ORIGIN 默认 *、CORS_MAX_AGE 默认 3600、LOGS_FORMAT 默认 console、CACHE_NAMESPACE 默认 Shlink。

两个与数据库端口相关的联动默认值值得注意:DB_DRIVER=postgres 时 DB_PORT 默认 5432,mssql 时默认 1433,其余驱动默认 3306;DB_HOST 未设置时回落取 DB_UNIX_SOCKET(Unix socket 连接场景)。

2.2 查看与修改方式

读取某个生效值(entrypoint 内部也是用它做启动分支判断的):

$ docker exec shlink-cfg-a shlink env-var:read DEFAULT_SHORT_CODES_LENGTH
8

未设置的变量读取结果为空(实测未设 GEOLITE_LICENSE_KEY 的 D 组实例返回空行)。修改方式只有一种:改环境变量后重建容器(Compose 下改 environment: 后 docker compose up -d 会自动重建),Shlink 无配置热更新,短链数据在数据库/数据卷中不受重建影响。

💡 技术拓展:12-Factor 应用的「配置进环境变量」原则把配置与代码彻底分离,Shlink 是 PHP 服务里执行得最彻底的一类——全部 67 项应用配置无一落配置文件,这让 secrets 文件、Compose 变量替换、kubectl env 等通道都能直接复用;代价是配置校验延迟到启动时(如 Redis 地址写错要等启动日志报错)。传统 PHP 应用常用的 config.php 静态文件模式则相反,改文件即生效但难进版本管理与密钥管理。两者取舍上,容器化部署场景环境变量模式优势明显。

三、参数总览(67 项应用配置分组)

以下分组清单与 v5.1.8 源码 EnvVars 枚举一一对应,共 67 项;加粗为本文有实测的项。

分组变量默认值说明
域名与访问DEFAULT_DOMAIN空生成短链的默认域名(可含端口),容器形态下必配
域名与访问IS_HTTPS_ENABLEDtrue短链是否以 https:// 输出
域名与访问BASE_PATH空子路径部署前缀(如 /s)
域名与访问TIMEZONE服务器时区影响统计时间戳
域名与访问SHORT_URL_TRAILING_SLASHfalse访问侧允许短码带尾斜杠命中
域名与访问SHORT_URL_MODEstrict短码大小写策略:strict/loose
域名与访问MULTI_SEGMENT_SLUGS_ENABLEDfalse自定义短码允许多段斜杠
域名与访问REDIRECT_EXTRA_PATH_MODEdefault短码后附加路径处理:default/append/ignore
域名与访问AUTO_RESOLVE_TITLEStrue创建时自动抓取目标页标题
短码DEFAULT_SHORT_CODES_LENGTH5随机短码长度(最小 4)
数据库DB_DRIVERsqlitesqlite/postgres/mysql/mssql
数据库DB_NAMEshlink库名
数据库DB_USER / DB_PASSWORD空认证三元组
数据库DB_HOST / DB_PORT按驱动回落主机与端口(端口随驱动默认)
数据库DB_UNIX_SOCKET空Unix socket 连接
数据库DB_USE_ENCRYPTIONfalseMSSQL 加密连接
跳转行为REDIRECT_STATUS_CODE302301/302/307/308
跳转行为DEFAULT_INVALID_SHORT_URL_REDIRECT空无效短码兜底跳转(空=404)
跳转行为DEFAULT_REGULAR_404_REDIRECT空常规 404 兜底跳转
跳转行为DEFAULT_BASE_URL_REDIRECT空访问域名根路径兜底跳转
跳转行为REDIRECT_CACHE_LIFETIME30跳转缓存 TTL(秒)
跳转行为REDIRECT_CACHE_VISIBILITYprivate缓存响应头 public/private
统计与隐私TRACK_ORPHAN_VISITStrue记录孤儿访问
统计与隐私DISABLE_TRACK_PARAM空带此 query 参数的访问不计数
统计与隐私DISABLE_TRACKINGfalse全局关闭统计
统计与隐私DISABLE_IP_TRACKINGfalse不记录 IP 与地理
统计与隐私DISABLE_REFERRER_TRACKINGfalse不记录来源页
统计与隐私DISABLE_UA_TRACKINGfalse不记录 User-Agent
统计与隐私ANONYMIZE_REMOTE_ADDRtrueIP 落库前匿名化
统计与隐私DISABLE_TRACKING_FROM空按 IP/网段关闭统计(逗号分隔)
缓存REDIS_SERVERS空Redis 地址(tcp://host:port,逗号分隔多台)
缓存REDIS_SENTINEL_SERVICE空Sentinel 服务名
缓存REDIS_SERVERS_USER / REDIS_SERVERS_PASSWORD空Redis 认证
缓存REDIS_PUB_SUB_ENABLEDfalse启用 Redis 发布订阅(多实例实时更新)
缓存CACHE_NAMESPACEShlink缓存键命名空间
实时更新MERCURE_ENABLED设了公共 Hub 即启用Mercure 推送开关
实时更新MERCURE_PUBLIC_HUB_URL / MERCURE_INTERNAL_HUB_URL空公共/内部 Hub 地址
实时更新MERCURE_JWT_SECRET空Hub 签名密钥
实时更新REAL_TIME_UPDATES_TOPICS空推送主题过滤
消息队列RABBITMQ_ENABLEDfalse启用 RabbitMQ 实时更新
消息队列RABBITMQ_HOST / RABBITMQ_PORT空 / 5672地址端口
消息队列RABBITMQ_USER / RABBITMQ_PASSWORD / RABBITMQ_VHOST空 / 空 / /认证与虚拟主机
消息队列RABBITMQ_USE_SSLfalseSSL 连接
集成MATOMO_ENABLEDfalse推送访问到 Matomo
集成MATOMO_BASE_URL / MATOMO_SITE_ID / MATOMO_API_TOKEN空Matomo 对接三件套
GeoIPGEOLITE_LICENSE_KEY空GeoLite2 许可证 Key
GeoIPSKIP_INITIAL_GEOLITE_DOWNLOADfalse跳过启动时下载
APIINITIAL_API_KEY空首次启动预置 API Key
删除保护DELETE_SHORT_URL_THRESHOLD15访问数达到阈值的短链删除需确认
RobotsROBOTS_ALLOW_ALL_SHORT_URLSfalse允许爬虫收录短链
RobotsROBOTS_USER_AGENTS空自定义 robots UA 列表
CORSCORS_ALLOW_ORIGIN*REST API 跨域来源
CORSCORS_ALLOW_CREDENTIALSfalse跨域携带凭据
CORSCORS_MAX_AGE3600预检缓存秒数
运维杂项APP_ENVprodprod/dev/test
运维杂项MEMORY_LIMIT512MPHP 内存上限
运维杂项LOGS_FORMATconsole日志格式
运维杂项TRUSTED_PROXIES空信任的反代 IP/网段(逗号分隔)

除上表外,RoadRunner 运行时层还有 5 个变量直接作用于 .rr.yml 模板:PORT(监听端口,默认 8080,Docker 镜像 EXPOSE 8080 与映射目标一致)、ADDRESS(监听地址,默认 0.0.0.0)、WEB_WORKER_NUM(HTTP worker 数,默认 0=自动按 CPU)、TASK_WORKER_NUM(任务 worker 数)、LOGS_FORMAT(与应用层同名共用)。日常部署只需关注 PORT,容器场景端口映射的宿主侧才是常改的那一端。

四、域名与访问参数详解

4.1 DEFAULT_DOMAIN 与 IS_HTTPS_ENABLED(必配项)

DEFAULT_DOMAIN 决定生成短链的域名部分,官方 Docker 镜像把它列为必配三项之一。它只影响生成侧,不影响跳转侧——跳转统计记录的是真实请求 Host(这个错位行为在系列 FAQ 篇 Q1 有完整复盘)。IS_HTTPS_ENABLED 决定生成短链的 scheme,置于反代之后做 TLS 终结时应改为 true。

实测:A 组实例设 DEFAULT_DOMAIN=surl-cfga.localhost:8136 + IS_HTTPS_ENABLED=false,生成的短链严格按这两个值拼接:

$ docker exec shlink-cfg-a shlink short-url:create -n https://www.quzuo.net/
Processed long URL: https://www.quzuo.net/
Generated short URL: http://surl-cfga.localhost:8136/QCOMq3md

-n 是跳过长 URL 可达性检查(离线环境创建短链必备,参数详解见 《Shlink 5.1.8 REST API 与 CLI 命令详解》)。

4.2 SHORT_URL_TRAILING_SLASH(访问侧语义,易误解项)

这是 5.x 里最容易误解的配置:它不改变生成结果(生成侧源码 ShortUrlStringifier 固定输出 scheme://domain/code,无尾斜杠分支),真正的语义在访问匹配侧——启用后,短码路径尾部多出的 / 会被中间件裁掉再匹配短码。

两组对比实测(A 组 SHORT_URL_TRAILING_SLASH=true,B 组默认 false):

# B 组(默认 false):带尾斜杠访问直接 404
$ curl -s -o /dev/null -w 'HTTP %{http_code}\n' http://localhost:8137/jmAHb/
HTTP 404

# A 组(true):带尾斜杠访问正常跳转
$ curl -s -o /dev/null -w 'HTTP %{http_code} -> %{redirect_url}\n' http://localhost:8136/QCOMq3md/
HTTP 302 -> https://www.quzuo.net/

结论:短链一旦对外发布(印刷物料、公众号文章等场景用户可能手滑带上尾斜杠),把该项设为 true 是零成本的容错;纯线上分享场景保持默认即可。

4.3 TIMEZONE 与统计时间戳

TIMEZONE 未设置时回落服务器时区(容器内默认 UTC)。对照实测:未设该变量的 C 组实例,访问记录时间为 2026-10-30T06:52:59+00:00;系列部署篇设 TIMEZONE=Asia/Shanghai 后同样操作记录为 +08:00 时区。做统计报表按天聚合时,这个变量决定「一天」的边界,国内业务建议显式设为 Asia/Shanghai。

4.4 其余访问类参数

  • BASE_PATH:子路径部署(如挂在 https://example.com/s/ 下)时设前缀,短链与 REST API 路径都会加上前缀;独立域名部署保持默认空值;
  • SHORT_URL_MODE=loose:短码改为大小写不敏感匹配(随机短码字符集同时缩为纯小写数字,见 5.2),适合短码会被口头转述、电话下单等大小写易混场景;
  • MULTI_SEGMENT_SLUGS_ENABLED=true:自定义短码允许带斜杠(如 campaign/2026/q4),把短链当路径聚合页用;
  • REDIRECT_EXTRA_PATH_MODE:控制短码后附加路径的语义——default 附加路径不匹配短链(当 404 处理)、append 把附加路径拼到目标长 URL 后(适合把短链当目录前缀跳转到文档深层页面)、ignore 忽略附加路径照常跳转;
  • AUTO_RESOLVE_TITLES=false:关闭创建时自动抓取目标页标题(内网目标地址抓取会拖慢创建速度时关掉)。

五、短码生成参数详解

5.1 DEFAULT_SHORT_CODES_LENGTH(实测 8 位)

随机短码长度,默认 5,源码硬编码下限 MIN_SHORT_CODES_LENGTH = 4(设更小值按 4 处理)。A 组实测设 8:

$ docker exec shlink-cfg-a shlink short-url:create -n https://shlink.io
Processed long URL: https://shlink.io
Generated short URL: http://surl-cfga.localhost:8136/dwYfJKTl

生成码 dwYfJKTl 恰为 8 位,且第二组对照 QCOMq3md 同样 8 位——长度稳定生效。对照 B 组(未设置,默认 5)生成 jmAHb。

长度选择上有明确的量化依据:默认字符集 62 个字符(大小写字母+数字),5 位码理论空间 62⁵ ≈ 9.16 亿,对绝大多数自托管场景绰绰有余;调大到 8 位(62⁸ ≈ 2.18 万亿)只在两类场景有意义——防短码枚举爬虫、或对短码随机性有合规要求。代价仅是短链多 3 个字符。

5.2 短码字符集(版本差异,5.x 不可配)

注意版本差异:旧版 Shlink 提供 SHORT_CODE_CHARS 环境变量自定义字符集,5.1.8 已移除该变量(源码 EnvVars 枚举中不存在)。现在字符集由 SHORT_URL_MODE 决定,写死在源码里:

模式字符集说明
strict(默认)0-9a-zA-Z(62 字符)大小写敏感
loose0-9a-z(36 字符)大小写不敏感匹配,生成也只用小写

5.3 自定义短码的约束

自定义 slug(customSlug 参数或 CLI --custom-slug)不受 DEFAULT_SHORT_CODES_LENGTH 约束,可长可短;启用 MULTI_SEGMENT_SLUGS_ENABLED 后可含斜杠。冲突时 REST API 返回 400,加 findIfExists: true 改为复用既有短链(实测细节见系列 API 篇)。

六、数据库参数详解

6.1 驱动选择与连接三元组

DB_DRIVER 默认 sqlite(零依赖起步,数据文件在容器内 /etc/shlink/data/database.sqlite),可选 postgres/mysql/mssql。生产推荐 PostgreSQL 或 MySQL,驱动与端口默认值联动(postgres→5432、mssql→1433、mysql→3306),库内网标准端口时 DB_PORT 可省略。

连接 postgres 驱动的完整配置(实测可用形态,与系列部署篇一致):

environment:
  DB_DRIVER: "postgres"
  DB_HOST: "shlink-db"       # compose 服务名
  DB_PORT: "5432"
  DB_NAME: "shlink"
  DB_USER: "shlink"
  DB_PASSWORD: "q1w2E3r4"
  • DB_HOST 不设时回落 Unix socket(DB_UNIX_SOCKET),适合同宿主机直装形态;
  • DB_USE_ENCRYPTION=true 仅对 MSSQL 有意义(驱动层加密连接);
  • 敏感项走 secret 文件:DB_PASSWORD_FILE=/run/secrets/shlink_db_pass,Shlink 读文件内容作口令,编排文件与进程列表均不再出现明文。

6.2 形态取舍

SQLite 只适合个人低流量(并发写入能力弱、统计查询慢),且数据必须挂卷持久化;PostgreSQL 形态的编排、健康检查与备份链路已在 《Shlink 5.1.8 Docker Compose 部署指南》 全量实测。数据层日常操作命令可参照 《PostgreSQL 18 常用 CLI 命令与工具详解》。

七、跳转行为参数详解

7.1 REDIRECT_STATUS_CODE(实测 301)

跳转状态码,可选 301/302/307/308,默认 302。C 组实测设 301:

$ curl -s -o /dev/null -w 'HTTP %{http_code} -> %{redirect_url}\n' http://localhost:8138/RO7Vl
HTTP 301 -> https://www.quzuo.net/

选型依据:302(默认)表示临时跳转,浏览器不缓存,每次点击都会回到 Shlink 记录统计,依赖统计的场景保持默认;301 永久跳转,浏览器与中间代理会缓存跳转结果,后续点击可能不再经过 Shlink(统计缩水),仅适合确定不再变更目标且不追求统计的短链;307/308 保留原请求方法,用于把短链指到 POST 接口(如把支付回调地址变短)。注意该值是全局的,下一节的兜底跳转也会沿用。

7.2 三个 404 场景兜底跳转

三个变量分别接管三类「没找到」流量,未设置时一律 404:

变量接管场景典型用法
DEFAULT_INVALID_SHORT_URL_REDIRECT短码不存在/已失效把失效短链导流到活动页或首页,挽回流量
DEFAULT_REGULAR_404_REDIRECT不匹配任何短链规则的普通 404导流到站点首页
DEFAULT_BASE_URL_REDIRECT直接访问短链域名根路径把裸短域名导流到品牌页

C 组实测 DEFAULT_INVALID_SHORT_URL_REDIRECT=https://www.quzuo.net/:访问不存在的短码不再 404,而是按全局状态码跳转:

$ curl -s -o /dev/null -w 'HTTP %{http_code} -> %{redirect_url}\n' http://localhost:8138/no-such-code
HTTP 301 -> https://www.quzuo.net/

对照系列 API 篇默认行为(未设兜底时 GET /no-such-code 返回 404 并记入 orphan visits)。

7.3 跳转缓存

REDIRECT_CACHE_LIFETIME(默认 30 秒)+ REDIRECT_CACHE_VISIBILITY(默认 private)控制跳转响应的浏览器缓存头。调大 TTL 可减少重复点击回源,但同样以统计精度为代价;private 限制仅浏览器缓存,public 允许中间 CDN 缓存(流量大且不依赖统计时可开)。

八、统计与隐私参数详解

8.1 TRACK_ORPHAN_VISITS(实测关闭)

孤儿访问指不对应任何短链的流量:失效短码访问、根路径访问等。默认 true 记录。C 组实测 TRACK_ORPHAN_VISITS=false 后,访问不存在的短码再查孤儿列表,表为空(仅表头):

$ docker exec shlink-cfg-c shlink visit:orphan --no-ansi
+------+---------------+------------+---------+---------+--------+------+-------------+--------------+------+
| Date | Potential bot | User agent | Referer | Country | Region | City | Visited URL | Redirect URL | Type |
+------+---------------+------------+---------+- Page 1 of 1 ----+------+-------------+--------------+------+

配合 7.2 的兜底跳转使用是合理组合——失效流量已被导流,孤儿统计的意义只剩排障。爬虫扫描带来的海量无效访问撑大 visit 表时,关掉它可显著抑制表膨胀。

8.2 DISABLE_TRACK_PARAM(实测 ?myp=1 不计数)

设置一个魔法 query 参数名后,任何带该参数的访问不计入统计。C 组实测 DISABLE_TRACK_PARAM=myp:

$ curl -s -o /dev/null http://localhost:8138/RO7Vl?myp=1   # 不产生记录
$ curl -s -o /dev/null http://localhost:8138/RO7Vl          # 正常记录
$ docker exec shlink-cfg-c shlink short-url:visits RO7Vl --no-ansi
+---------------------------+---------------+-------------+---------+---------+---------+---------+-----------------------------+------------------------+-----------------+
| Date                      | Potential bot | User agent  | Referer | Country | Region  | City    | Visited URL                 | Redirect URL           | Type            |
+---------------------------+---------------+-------------+---------+---------+---------+---------+-----------------------------+------------------------+-----------------+
| 2026-10-30T06:52:59+00:00 | Potential bot | curl/8.18.0 |         | Unknown | Unknown | Unknown | http://localhost:8138/RO7Vl | https://www.quzuo.net/ | valid_short_url |
+---------------------------+---------------+-------------+---------+---------+---------+---------+-----------------------------+------------------------+-----------------+

带 ?myp=1 的那次访问没有出现在明细里,正常访问记录在案。用途:自己点击验证短链是否存活而不污染统计数据(替代系列 FAQ 篇 Q6 的「事后清理」法,前置规避优于事后删除)。

8.3 全局开关与细粒度开关

  • DISABLE_TRACKING=true:全局关闭统计(跳转照常,visit 表零写入),DISABLE_IP_TRACKING 等一切统计开关均被它压制;
  • DISABLE_IP_TRACKING=true:不记 IP 且不解析地理(地理位置库下载都可省);
  • DISABLE_REFERRER_TRACKING / DISABLE_UA_TRACKING:分别不记来源页/User-Agent;
  • ANONYMIZE_REMOTE_ADDR=true(默认):IP 落库前做匿名化(IPv4 末段置零、IPv6 截断),满足 GDPR 类合规要求,开启后地理定位精度降到城市级以内基本无影响;
  • DISABLE_TRACKING_FROM:按 IP/网段关闭统计(逗号分隔,如 192.168.1.0/24,10.0.0.5),办公网自测流量默认不计入,与 8.2 互补。

8.4 隐私配置的合规组合模板

面向欧盟用户的统计合规组合:ANONYMIZE_REMOTE_ADDR=true(保持默认)+ DISABLE_TRACKING_FROM=192.168.1.0/24(换成自家办公网段)+ 可选 DISABLE_UA_TRACKING=true。需要完全合规(不落任何个人数据)则直接 DISABLE_TRACKING=true,Shlink 退化为纯跳转服务。

九、缓存与实时更新参数详解

9.1 REDIS_SERVERS(实测 13 个缓存键)

未配置 Redis 时 Shlink 用进程内数组缓存(多实例不共享,重启即失)。配置后缓存与锁全部落到 Redis。D 组实测单机 Redis:

$ docker run -d --name shlink-cfg-redis --network shlink-cfg-net redis:7
$ docker run -d --name shlink-cfg-d --network shlink-cfg-net \
    -p 8139:8080 \
    -e DEFAULT_DOMAIN=surl-cfgd.localhost:8139 \
    -e IS_HTTPS_ENABLED=false \
    -e REDIS_SERVERS=tcp://shlink-cfg-redis:6379 \
    shlinkio/shlink:5.1.8

创建短链并访问一次后,Redis 侧实测出现 13 个 Shlink: 前缀键:

$ docker exec shlink-cfg-redis redis-cli --scan --pattern 'Shlink*'
Shlink:Shlinkio__Shlink__Core__Tag__Entity__Tag__CLASSMETADATA__
Shlink:36c7821085bdac13c0673c86b8352f44
Shlink:Shlinkio__Shlink__Core__Visit__Entity__VisitLocation__CLASSMETADATA__
Shlink:Shlinkio__Shlink__Core__Visit__Entity__ShortUrlVisitsCount__CLASSMETADATA__
Shlink:Shlinkio__Shlink__Core__ShortUrl__Entity__ShortUrl__CLASSMETADATA__
Shlink:Shlinkio__Shlink__Core__RedirectRule__Entity__ShortUrlRedirectRule__CLASSMETADATA__
Shlink:fa82f3c2096b04dcdd680367626113da
Shlink:Shlinkio__Shlink__Core__Visit__Entity__Visit__CLASSMETADATA__
Shlink:Shlinkio__Shlink__Core__Domain__Entity__Domain__CLASSMETADATA__
Shlink:d45626bdc5c721eed382d31da5a4fc8d
Shlink:3d7d8aff9404de494dccab7bd9d0b070
Shlink:Shlinkio__Shlink__Rest__Entity__ApiKey__CLASSMETADATA__
Shlink:07754e78a13658f1aedd368cfd4d9176

两类键:CLASSMETADATA 结尾的是 Doctrine ORM 元数据缓存;哈希名的是短码→长 URL 的跳转缓存(受 7.3 的 TTL 控制)。地址格式 tcp://host:port,多实例间逗号分隔(如 tcp://r1:6379,tcp://r2:6379,客户端侧分片)。REDIS_SENTINEL_SERVICE 配 Sentinel 服务名接管地址发现;REDIS_SERVERS_USER/REDIS_SERVERS_PASSWORD 配 ACL 认证。

9.2 REDIS_PUB_SUB_ENABLED 与多实例实时更新

多实例部署时,A 实例建的短链 B 实例的跳转缓存要失效——默认靠缓存 TTL 自然过期(最长 30 秒不一致),设 REDIS_PUB_SUB_ENABLED=true 后改为 Redis 发布订阅即时广播失效事件。单实例无此需求,保持默认。

9.3 Mercure 与 RabbitMQ(可选实时面)

Shlink 的实时推送(Web Client 的访问实时刷新)有两条通道:MERCURE_*(Mercure Hub,SSE 协议)与 RABBITMQ_*(AMQP)。MERCURE_ENABLED 默认随 MERCURE_PUBLIC_HUB_URL 是否设置联动;两者同时启用时事件双发。REAL_TIME_UPDATES_TOPICS 过滤推送主题(如只要短链更新、不要访问事件)。自托管最小化部署建议两者都不开,实时面用 CLI/API 轮询替代。

十、GeoIP 与删除保护参数详解

10.1 GEOLITE_LICENSE_KEY(实测无 Key 报错)

地理定位依赖 MaxMind GeoLite2 离线库,Shlink 默认不带。容器启动时 entrypoint 检查 GEOLITE_LICENSE_KEY:有值则初始化阶段自动下载库文件,无值(或 SKIP_INITIAL_GEOLITE_DOWNLOAD=true)则跳过。未配置 Key 时手动下载实测报错:

$ docker exec shlink-cfg-d shlink visit:download-db
 Downloading GeoLite2 db file...

 [WARNING] It was not possible to download GeoLite2 db, because a license was   
           not provided.                                                        

exit=2

Key 在 MaxMind 免费注册获取。未配置时的直接后果:访问明细的 Country/Region/City 全为 Unknown(系列 API 篇实测留痕),补配 Key 后执行 visit:download-db 下载、visit:locate 回溯存量记录。GeoLite2 每周更新,库文件放 cron 定期刷新。

10.2 DELETE_SHORT_URL_THRESHOLD(实测删除保护)

防误删保护:访问次数达到阈值的短链,删除命令会被拦截。源码默认 15。B 组实测设 DELETE_SHORT_URL_THRESHOLD=2,访问 2 次后删除:

$ curl -s -o /dev/null http://localhost:8137/jmAHb   # ×2 次访问
$ docker exec shlink-cfg-b shlink short-url:delete jmAHb
Impossible to delete short URL with short code "jmAHb", since it has more than "2" visits.

 Do you want to delete it anyway? (yes/no) [no]:
 >

 [WARNING] Short URL was not deleted.
exit=2

三个实测细节:拦截时 CLI 给交互确认(默认 no,脚本场景无交互输入即退出码 2 不删);确认 yes 可强删;-i/--ignore-threshold 参数直接跳过检查(short-url:delete -i jmAHb)。对照实测 0 访问的短链删除畅通:

$ docker exec shlink-cfg-b shlink short-url:delete lGwu3

 [OK] Short URL with short code "lGwu3" successfully deleted.

阈值语义是「访问数超过该值的短链删除需确认」:营销类高价值短链多的环境调大(如 100),测试环境调小(如 1)让保护尽早介入。

10.3 INITIAL_API_KEY

首次启动预置 API Key(UUID 形态),省掉容器起来后手动 shlink api-key:generate 一步,也便于基础设施即代码(编排文件里固定 Key,服务一就绪集成方即可调用)。已初始化的实例设置它无效果,Key 管理命令全集见 《Shlink 5.1.8 REST API 与 CLI 命令详解》。

十一、运维杂项参数详解

11.1 资源与运行时

  • MEMORY_LIMIT(默认 512M):PHP memory_limit,启动时经 ini_set 注入(源码 container.php),统计量大、批量导入短链时按需调到 1G;RoadRunner 常驻 worker 的重启阈值(处理 250 个请求后重建进程防内存泄漏)由镜像内置,不受此变量控制;
  • LOGS_FORMAT:日志输出格式,默认 console(人类可读),容器日志采集进 ELK/Loki 时改 json;
  • APP_ENV:prod(默认)/dev/test,dev 模式会输出详细错误栈,生产严禁;
  • TRUSTED_PROXIES:Shlink 在反代之后必须配置信任网段(如 10.89.0.0/16),否则统计里的客户端 IP 全是反代地址、地理定位随之失效;与 X-Forwarded-For 头处理直接相关。

11.2 REST API 跨域(CORS_*)

Web 前端直连 Shlink REST API 时才需要关注:CORS_ALLOW_ORIGIN 默认 *(开发方便但生产建议收敛到自家域名,如 https://admin.example.com)、CORS_ALLOW_CREDENTIALS 默认 false、CORS_MAX_AGE 默认 3600(预检请求缓存一小时)。纯服务端调用(curl/SDK)不受 CORS 影响。

11.3 Robots 与 Matomo 集成

  • ROBOTS_ALLOW_ALL_SHORT_URLS=true:默认 Shlink 对短链返回 noindex(防止搜索引擎收录短链稀释目标页权重),确认要收录才打开;
  • ROBOTS_USER_AGENTS:自定义 robots 规则命中的 UA 列表;
  • MATOMO_* 四件套:把每次访问同步推给 Matomo 分析平台(MATOMO_ENABLED=true + MATOMO_BASE_URL + MATOMO_SITE_ID + MATOMO_API_TOKEN),适合「短链入口 + Matomo 深度分析」的组合,选型参照 Matomo 官方部署文档。

十二、生产配置模板

PostgreSQL + Redis 生产形态的完整环境变量组(内存与磁盘标注:Shlink 容器内存上限 512M 起步即可,PostgreSQL 单独 512M1G,磁盘按访问量预留 visit 表空间——每 10 万次访问约占 5080MB):

name: shlink-5.1.8-stack

services:
  shlink-app:
    image: shlinkio/shlink:5.1.8
    ports:
      - "8132:8080"
    environment:
      # 域名与访问
      DEFAULT_DOMAIN: "s.example.com"
      IS_HTTPS_ENABLED: "true"
      TIMEZONE: "Asia/Shanghai"
      SHORT_URL_TRAILING_SLASH: "true"
      # 数据库(密码走 secret 文件)
      DB_DRIVER: "postgres"
      DB_HOST: "shlink-db"
      DB_NAME: "shlink"
      DB_USER: "shlink"
      DB_PASSWORD_FILE: "/run/secrets/shlink_db_pass"
      # 跳转行为
      REDIRECT_STATUS_CODE: "302"
      DEFAULT_INVALID_SHORT_URL_REDIRECT: "https://www.example.com/"
      DEFAULT_BASE_URL_REDIRECT: "https://www.example.com/"
      # 统计与隐私
      DISABLE_TRACKING_FROM: "192.168.1.0/24"
      DISABLE_TRACK_PARAM: "nohit"
      # 缓存
      REDIS_SERVERS: "tcp://shlink-redis:6379"
      REDIS_PUB_SUB_ENABLED: "false"
      # 运维
      TRUSTED_PROXIES: "10.89.0.0/16"
      MEMORY_LIMIT: "512M"
      GEOLITE_LICENSE_KEY: "${MAXMIND_KEY}"   # 第三方 Key 不落盘:写进 compose 同目录 .env 文件(chmod 600),变量替换注入
    secrets:
      - shlink_db_pass
    depends_on:
      shlink-db:
        condition: service_healthy
    networks: [shlink-net]

  shlink-db:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: "shlink"
      POSTGRES_USER: "shlink"
      POSTGRES_PASSWORD: "q1w2E3r4"
    volumes:
      - shlink-db-data:/var/lib/postgresql/data
    networks: [shlink-net]

  shlink-redis:
    image: redis:7
    networks: [shlink-net]

volumes:
  shlink-db-data:

networks:
  shlink-net:
    name: shlink-5.1.8-net
    driver: bridge

secrets:
  shlink_db_pass:
    file: ./shlink_db_pass.txt

编排结构与 healthcheck 的完整说明(本模板的删减版)见 《Shlink 5.1.8 Docker Compose 部署指南》。反代 TLS 接入与 TRUSTED_PROXIES 的配合参照 《Nginx HTTPS 与证书配置方案(certbot/自签名)》。

十三、常见配置问题(实测沉淀)

13.1 设置了 SHORT_URL_TRAILING_SLASH=true,生成的短链怎么没有尾斜杠

生成 URL 固定无尾斜杠(5.x 生成侧源码无此分支)。该项的实测语义是访问侧容错:带尾斜杠的访问从 404(默认)变为正常跳转。想改生成结果是没有开关的——若下游系统强依赖尾斜杠形态,只能自定义 slug 以 / 结尾并开启多段 slug。

13.2 DEFAULT_INVALID_SHORT_URL_REDIRECT 设了但跳转状态码不是预期的 302

兜底跳转沿用全局 REDIRECT_STATUS_CODE(实测设 301 后无效短码访问返回 HTTP 301)。两者是乘法关系,规划兜底导流时要连状态码一起核对。

13.3 DISABLE_TRACK_PARAM 配了却还在统计

实测确认参数是精确匹配:访问 ?myp=1 不计数,但其他参数组合(如 ?myp=1&x=2)同样生效(键存在即命中);真正常见的失效原因是参数名大小写不一致,或该参数被写进了短链目标长 URL 而非短链访问 URL——拦截发生在跳转请求上,跳转之后的后续动作不再受控。

13.4 Redis 配了但短链查询还是慢 / 键里没有短码

用 redis-cli --scan --pattern 'Shlink*' 实测核对:只有 13 个左右键(元数据 + 少量哈希)是正常的——跳转缓存按短码粒度懒加载,没人点过的短链不在缓存里。若连元数据键都没有,先查 REDIS_SERVERS 格式(必须带 tcp:// 前缀)与网络连通性。缓存调优进阶见 《Shlink 5.1.8 常见问题与进阶实战》。

13.5 删短链报 "Impossible to delete ... since it has more than N visits"

这是 DELETE_SHORT_URL_THRESHOLD 保护在生效(实测默认 15),不是故障。脚本场景无交互输入会以退出码 2 终止且不删除;确认要删用 short-url:delete -i(ignore-threshold)。

十四、配置速查与系列导航

按场景速查:换域名 → 4.1;短链带斜杠 404 → 4.2;短码长度/大小写 → 第五章;连不上数据库 → 第六章;跳转 301/404 兜底 → 第七章;统计数据不要记 → 第八章;多实例部署 → 9.1/9.2;地理 Unknown → 10.1;删不掉短链 → 10.2/13.5;反代后 IP 不对 → 11.1。

系列文章:

  1. 《Shlink 5.1.8 介绍与选型指南》 — 特性全景、版本演进与选型对比
  2. 《Shlink 5.1.8 Docker Compose 部署指南》 — PostgreSQL/SQLite 双形态编排实测
  3. 本文 — 67 项配置参数全量详解与逐项实测
  4. 《Shlink 5.1.8 REST API 与 CLI 命令详解》 — API 全流程与 30+ CLI 命令清单
  5. 《Shlink 5.1.8 常见问题与进阶实战》 — 部署/统计类 FAQ 与进阶场景