Skip to content

环境变量参考 ​

本文引用的文件

目录 ​

  1. 简介
  2. 项目结构与变量入口
  3. 核心环境变量总览
  4. 架构概览:环境变量如何影响系统
  5. 详细变量说明
  6. 依赖关系分析
  7. 性能与限流特性
  8. 安全与敏感信息保护
  9. 故障排查指南
  10. 结论

简介 ​

本文是 SkinNexus 所有 SKIN_* 环境变量的权威参考。它按功能域分组,列出每个变量的名称、类型、默认值、是否必需、示例值和用途,并重点解释数据库连接串、SMTP、站点 URL、OIDC、Union 联邦、Yggdrasil 回源、限流、日志、安全头、插件信任、主题市场和访问日志等关键行为。

该文档只描述代码实际读取的变量;未出现在代码中的变量即使被某些部署脚本设置,也不会被进程使用。

项目结构与变量入口 ​

SKIN_* 环境变量的“唯一真实来源”是配置包的已知列表。程序启动时会检查是否有未知变量,避免“拼写错误导致配置静默失效”。

图表来源

章节来源

核心环境变量总览 ​

下表按功能域组织所有 SKIN_* 变量。

功能域变量类型默认值必需示例值用途
网络与站点SKIN_LISTEN字符串:8080否:8080、0.0.0.0:8080HTTP 监听地址
网络与站点SKIN_BASE_URL字符串http://localhost:8080否https://skin.example.com站点根地址;影响 OIDC issuer、Webhook 回调、皮肤分发 URL、纹理 URL
网络与站点SKIN_ENV字符串production否production、staging部署标签
网络与站点SKIN_DATA_DIR字符串./data否/var/lib/skin-nexus数据根目录;签名密钥、主题、插件通常位于其下
网络与站点SKIN_TEXTURES_DIR字符串<DataDir>/textures否/var/lib/skin-nexus/textures纹理文件目录
网络与站点SKIN_THEMES_DIR字符串<DataDir>/themes否<DataDir>/themes主题包目录
网络与站点SKIN_PLUGINS_DIR字符串<DataDir>/plugins否<DataDir>/plugins插件包目录
网络与站点SKIN_MIGRATIONS_DIR字符串./migrations否./migrationsSQL 迁移目录
网络与站点SKIN_AUTO_MIGRATE布尔false否true启动时自动应用迁移
网络与站点SKIN_LEGACY_ENV字符串路径无否/etc/skin-nexus/.env导入旧版 .env 验证方法
身份与安全SKIN_SETUP_TOKEN字符串启动时生成并输出到日志否a1b2c3d4e5f6安装向导令牌
身份与安全SKIN_SITE_NAME字符串SkinNexus否我的皮肤站站点展示名
身份与安全SKIN_TRUSTED_PROXIES逗号分隔字符串历史默认(环回或 RFC1918)否10.0.0.0/8,172.16.0.0/12,192.168.0.0/16允许转发真实 IP 的反向代理网段
身份与安全SKIN_SERVER_NAME字符串SkinNexus否SkinNexusYggdrasil 元数据中的服务器名
身份与安全SKIN_SKIN_DOMAINS逗号分隔字符串空否skin.example.com允许的皮肤域名
身份与安全SKIN_SIGN_KEY文件路径<DataDir>/sign-key.pem否<DataDir>/sign-key.pem站点 RSA 私钥 PEM 路径
身份与安全SKIN_ADMIN_TOKEN字符串无否admin-secret-token管理接口令牌
身份与安全SKIN_CSP_SCRIPT_EXTRA_SOURCES字符串空否'https://cdn.example.com'追加到 CSP script-src 的来源
身份与安全SKIN_CSP_CONNECT_EXTRA_SOURCES字符串空否'https://api.example.com'追加到 CSP connect-src 的来源
注册与认证SKIN_OIDC_ENABLED布尔false否true启用内部 OIDC 提供者和无密码登录流程
注册与认证SKIN_OIDC_ISSUER字符串继承 SKIN_BASE_URL否https://skin.example.comOIDC issuer;应等于站点公开根
注册与认证SKIN_OIDC_SIGN_KEY文件路径<DataDir>/oidc-key.pem否<DataDir>/oidc-key.pemOIDC JWT 签名私钥 PEM 路径
注册与认证SKIN_OIDC_SHARED_CLIENT_ID字符串2否2公共客户端发现 ID
注册与认证SKIN_REQUIRE_VERIFICATION布尔false否true要求邮箱验证后才能加入服务器
注册与认证SKIN_INVITE_REQUIRED布尔false否true注册需要邀请码
注册与认证SKIN_LOGIN_FAIL_LIMIT整数5否5同一标识连续失败后锁定次数
注册与认证SKIN_RATE_LIMIT_AUTH整数120否120每 IP 每 10 分钟滑动窗口最大请求数
邮件SKIN_SMTP_HOST字符串空条件必需smtp.example.comSMTP 主机;为空表示关闭邮件功能
邮件SKIN_SMTP_PORT整数465否465、587SMTP 端口;非法值回退 465
邮件SKIN_SMTP_USER字符串空条件必需[email protected]SMTP 用户名;当 From 为空时可充当 From
邮件SKIN_SMTP_PASS字符串空否secretSMTP 密码
邮件SKIN_SMTP_FROM字符串空条件必需[email protected]发件人地址;为空且用户名为空时邮件功能不可用
插件市场SKIN_PLUGIN_SECRET_KEY字符串无否plugin-signing-secret插件签名相关密钥
插件市场SKIN_PLUGIN_STATE_DIR字符串<PluginsDir>/.state否<PluginsDir>/.state插件状态目录
插件市场SKIN_PLUGIN_MARKET_URL字符串官方插件注册表可显式设为空以禁用https://yimingzhanshen.github.io/skin-nexus-plugins/v1/registry.json插件市场地址
插件市场SKIN_PLUGIN_TRUST_KEYS字符串官方插件信任键可显式设为空以关闭受信任安装market-2026-10:ID2EWgcfs1E4UbGCCX9WjD0aCgTof3oeuHV03IpdGNY=插件市场信任键
插件市场SKIN_PLUGIN_UPLOAD_MAX整数字节64 MiB否134217728插件上传大小上限
主题市场SKIN_THEME_MARKET_URL字符串官方主题注册表可显式设为空以禁用https://yimingzhanshen.github.io/skin-nexus-plugins/themes/v1/registry.json主题市场地址
主题市场SKIN_THEME_TRUST_KEYS字符串官方主题信任键可显式设为空以关闭受信任安装theme-market-2026-11:EXxNehbsxNG9gdYUztMl/EU/lZ09+fPftPvmjeqPr/I=主题市场信任键
Union 联邦SKIN_UNION_ENABLED布尔false否true启用 Union 成员模块
Union 联邦SKIN_UNION_API_ROOT绝对 URLhttps://skin.mualliance.ltd/api/union启用时为必需https://hub.example.com/api/unionHub 端点根地址
Union 联邦SKIN_UNION_MEMBER_KEY字符串无启用时为必需member-shared-secret成员共享密钥,用于出站调用和 OAuth2 grant 签名
Union 联邦SKIN_UNION_HOST_PUBKEY文件路径<DataDir>/union-host-pubkey.pem启用时为必需<DataDir>/union-host-pubkey.pemHub 消息签名公钥 PEM
Union 联邦SKIN_UNION_ALLOW_UPDATEBACKENDKEY布尔false否false是否允许远端更新后端成员密钥
Union 联邦SKIN_UNION_QUERYEMAIL_MODE枚举full否full、off邮箱查询模式:full 返回邮箱,off 拒绝
Union 联邦SKIN_UNION_OAUTH2_SIG_KEY文件路径<DataDir>/union-oauth2-sig.pem启用时为必需<DataDir>/union-oauth2-sig.pemUnion OAuth2 用户信息签名私钥 PEM
Union 联邦SKIN_UNION_HUB_ORIGIN字符串https://skin.mualliance.ltd否https://hub.example.comHub CORS 白名单来源
Union 联邦SKIN_UNION_RESOLVE_NAMES布尔true否true是否解析各节点自身发现文档显示站点名
Yggdrasil 回源SKIN_MOJANG_FALLBACK字符串由配置加载逻辑处理在已知清单中声明https://sessionserver.mojang.comMojang 回源地址(存在于已知变量清单)

章节来源

架构概览:环境变量如何影响系统 ​

SKIN_BASE_URL 是整个站点对外地址的核心锚点。它不仅决定 Web 界面链接,还影响 OIDC issuer、Webhook 回调和皮肤分发 URL。

图表来源

详细变量说明 ​

数据库连接:SKIN_DATABASE_DSN ​

该变量直接传给底层存储打开函数,不经过通用配置解析器。因此它的格式取决于数据库驱动:

数据库连接串格式说明
MySQLuser:pass@tcp(host:port)/database?parseTime=true&charset=utf8mb4现有生产部署默认走 MySQL;裸 MySQL DSN 保持 MySQL
PostgreSQLpostgres://user:pass@host:port/database带 postgres:// 前缀会被识别为 PostgreSQL
SQLitesqlite:/path/to/file.db带 sqlite: 前缀会被识别为 SQLite

注意:

  • 该变量没有统一默认值;如果未设置,存储初始化会接收空 DSN。
  • 文件名和连接参数应由运维人员根据部署环境填写。
  • SQLite 适合单实例开发或小规模部署;MySQL 和 PostgreSQL 适合多实例和生产环境。

图表来源

章节来源

SMTP 邮件:SKIN_SMTP_* ​

邮件配置由独立的配置解析逻辑处理,规则如下:

变量类型默认值必需性说明
SKIN_SMTP_HOST字符串空条件必需为空表示邮件功能关闭
SKIN_SMTP_PORT整数465否必须为正数且小于 65536;非法值回退 465
SKIN_SMTP_USER字符串空条件必需若 SKIN_SMTP_FROM 也为空,则用它作为 From
SKIN_SMTP_PASS字符串空否SMTP 密码
SKIN_SMTP_FROM字符串空条件必需发件人地址;为空且用户名为空时邮件不可用

关键行为:

  • 只要 SKIN_SMTP_HOST 为空,整个邮件配置就视为未配置。
  • 如果没有有效的 From 地址,邮件功能不可用;此时管理面板不会伪装成功,而是返回 503。
  • 从协议兼容性看,SKIN_SMTP_PORT=465 对应隐式 TLS,SKIN_SMTP_PORT=587 通常配合 STARTTLS。代码实现中仅解析端口,并未暴露独立 starttls 或 tls 布尔开关。

图表来源

章节来源

站点 URL:SKIN_BASE_URL ​

SKIN_BASE_URL 是站点对外根地址,最终通过 siteurl.Set() 安装到全局原子指针中。它会影响:

  1. OIDC issuer:如果未显式设置 SKIN_OIDC_ISSUER,则回退到 SKIN_BASE_URL。
  2. 纹理 URL:纹理资源使用站点根地址拼接 /textures/{hash}。
  3. 头像 URL:头像和资源预览都基于站点根地址。
  4. 页面 URL:所有页面跳转都基于站点根地址。
  5. 皮肤分发 URL 和 Webhook 回调:这些对外回调地址依赖已解析的站点基础地址。

图表来源

章节来源

OIDC:SKIN_OIDC_* ​

当 SKIN_OIDC_ENABLED=true 时,系统启用内部 OIDC 提供者,支持设备授权、刷新 token、撤销、用户信息等标准端点。

变量类型默认值必需说明
SKIN_OIDC_ENABLED布尔false否启用 OIDC
SKIN_OIDC_ISSUER字符串继承 SKIN_BASE_URL否OIDC issuer;应与外部可见站点根一致
SKIN_OIDC_SIGN_KEY文件路径<DataDir>/oidc-key.pem启用时为必需OIDC JWT 签名私钥 PEM
SKIN_OIDC_SHARED_CLIENT_ID字符串2否公共客户端 discovery ID

OIDC 端点包括:

  • /.well-known/openid-configuration
  • /authorize
  • /oauth/token
  • /oauth/introspect
  • /authorize/callback
  • /revoke
  • /end_session
  • /keys
  • /device_authorization
  • /userinfo
  • /yggc/userinfo
  • /device.html
  • /api/v1/oidc/...

图表来源

章节来源

Union 成员站:SKIN_UNION_* ​

Union 是 MUA 联盟的成员站协议。启用后,站点可与 hub 和其他成员站通信,包括签名消息、OAuth2 grant、邮箱查询、成员名解析等。

变量类型默认值必需说明
SKIN_UNION_ENABLED布尔false否启用 Union 模块
SKIN_UNION_API_ROOT绝对 URLhttps://skin.mualliance.ltd/api/union启用时为必需Hub API 根地址
SKIN_UNION_MEMBER_KEY字符串无启用时为必需成员共享密钥
SKIN_UNION_HOST_PUBKEY文件路径<DataDir>/union-host-pubkey.pem启用时为必需Hub 消息签名公钥
SKIN_UNION_ALLOW_UPDATEBACKENDKEY布尔false否是否允许远端更新后端密钥
SKIN_UNION_QUERYEMAIL_MODE枚举full否full 或 off
SKIN_UNION_OAUTH2_SIG_KEY文件路径<DataDir>/union-oauth2-sig.pem启用时为必需Union OAuth2 签名私钥
SKIN_UNION_HUB_ORIGIN字符串https://skin.mualliance.ltd否Hub CORS 来源
SKIN_UNION_RESOLVE_NAMES布尔true否是否解析节点发现文档显示站点名

安全要点:

  • SKIN_UNION_MEMBER_KEY 是出站调用的 HMAC 密钥,也是 OAuth2 grant token 的签名密钥。
  • SKIN_UNION_HOST_PUBKEY 是固定 pin 的 Hub 公钥,不应依赖每次远程拉取。
  • SKIN_UNION_ALLOW_UPDATEBACKENDKEY=false 是默认安全策略,防止远端改写共享密钥。
  • SKIN_UNION_QUERYEMAIL_MODE 为非法值时采用 fail-closed 策略。

图表来源

章节来源

Yggdrasil 回源与回退:SKIN_MOJANG_FALLBACK ​

SKIN_MOJANG_FALLBACK 出现在已知环境变量清单中,代表 Yggdrasil 协议的 Mojang 回源配置。具体回源行为由 Yggdrasil 服务层处理,并与限流、会话 TTL、玩家匹配等逻辑协同。

章节来源

限流:SKIN_RATE_LIMIT_AUTH 与 SKIN_LOGIN_FAIL_LIMIT ​

认证限流由内存中的滑动窗口 + 连续失败锁机制组成:

变量类型默认值说明
SKIN_RATE_LIMIT_AUTH整数120每 IP 每 10 分钟滑动窗口最大请求数;0 关闭窗口层
SKIN_LOGIN_FAIL_LIMIT整数5同一标识连续失败达到阈值后锁定 15 分钟;0 关闭锁层

重要限制:

  • 失败计数针对“标识”,不是 IP;防止 NAT 出口被误伤。
  • 请求窗口针对 IP;防止资源滥用。
  • 两个维度相互独立:失败不会锁定 IP,窗口命中不会锁定标识。
  • 时间戳使用毫秒精度,清理循环定期释放过期条目。

图表来源

章节来源

日志级别与访问日志 ​

代码中没有名为 SKIN_LOG_LEVEL 的环境变量。系统的可观测性主要通过访问日志模块实现,而不是通过一个通用的日志级别开关。

访问日志记录以下类别:

  • Web 登录、注册、邮箱验证门控
  • Yggdrasil 认证、刷新、校验、加入、hasJoined、profile
  • Union 入站和出站
  • 插件事件

结果分类包括:

  • ok:成功
  • fail:业务拒绝
  • denied:限流、锁死或模块禁用
  • miss:未知资料或会话
  • error:内部错误

访问日志写入失败不会影响正常请求路径,只会记录操作者日志。

图表来源

章节来源

安全头:SKIN_CSP_SCRIPT_EXTRA_SOURCES、SKIN_CSP_CONNECT_EXTRA_SOURCES ​

这两个变量向内容安全策略追加第三方来源:

变量用途
SKIN_CSP_SCRIPT_EXTRA_SOURCES追加到 script-src
SKIN_CSP_CONNECT_EXTRA_SOURCES追加到 connect-src

它们保留原始值,由头部层负责校验来源合法性;无效值会在启动阶段拒绝。

章节来源

插件信任:SKIN_PLUGIN_TRUST_KEYS ​

插件信任键格式为 id:base64pub,...。默认值是官方插件信任键;可以显式设置为空以关闭受信任安装,也可以替换为自定义键。

变量默认值说明
SKIN_PLUGIN_MARKET_URL官方插件注册表插件市场地址;空值表示关闭
SKIN_PLUGIN_TRUST_KEYS官方插件信任键插件签名信任键;空值关闭受信任安装
SKIN_PLUGIN_UPLOAD_MAX64 MiB插件上传大小上限

章节来源

主题市场:SKIN_THEME_MARKET_URL、SKIN_THEME_TRUST_KEYS ​

主题市场与插件市场共用发行仓库,但使用独立的信任键。这样任何一个密钥泄露都不会同时破坏两个表面。

变量默认值说明
SKIN_THEME_MARKET_URL官方主题注册表主题市场地址;空值表示关闭
SKIN_THEME_TRUST_KEYS官方主题信任键主题签名信任键;空值关闭受信任安装

章节来源

依赖关系分析 ​

图表来源

性能与限流特性 ​

  • 认证限流使用内存映射,无外部依赖,适合单实例部署。
  • 滑动窗口和失败锁都有清理协程,按活跃键释放过期数据。
  • 默认 SKIN_RATE_LIMIT_AUTH=120 是为了解决共享 NAT 出口导致的批量触发问题。
  • 默认 SKIN_LOGIN_FAIL_LIMIT=5 防止暴力破解,并在超时后自动解除锁定。
  • 访问日志写入失败不会重试,也不会影响主请求路径。

章节来源

安全与敏感信息保护 ​

以下变量属于敏感信息,不应直接写入镜像、源码仓库或普通配置文件:

敏感变量风险建议
SKIN_SIGN_KEY站点签名私钥泄露会导致伪造内容使用 secret manager、docker secrets 或运行时注入
SKIN_OIDC_SIGN_KEYOIDC JWT 签名密钥泄露可伪造身份单独保管,不与站点签名密钥混用
SKIN_ADMIN_TOKEN管理接口越权使用强随机值并通过运行环境注入
SKIN_SMTP_PASS邮件凭据泄露不要硬编码进镜像
SKIN_UNION_MEMBER_KEYUnion 出站认证和 OAuth2 grant 签名只在目标部署中注入
SKIN_UNION_HOST_PUBKEY消息验签公钥应 pin 到可信版本
SKIN_UNION_OAUTH2_SIG_KEYUnion OAuth2 用户信息签名私钥严格隔离
SKIN_PLUGIN_SECRET_KEY插件签名相关密钥按需最小权限注入

最佳实践:

  1. 不要把密钥写入 Docker 镜像层。
  2. 使用 secret manager、Kubernetes Secret、Docker Secrets 或编排平台提供的机密注入能力。
  3. 不同服务使用不同密钥:站点签名密钥、OIDC 密钥、Union 密钥、SMTP 密码应分开。
  4. 对 Union 和 OIDC 密钥做轮换计划,并确保旧密钥过渡期兼容。
  5. 审计日志可能包含 IP、UA、部分诊断字段;确认访问日志存储位置不在公开仓库中。

章节来源

故障排查指南 ​

现象可能原因排查步骤
设置了一个 SKIN_* 变量但不起作用变量名拼写错误或未被代码读取检查启动警告;对照已知变量清单
邮件功能看似开启但无法发送SKIN_SMTP_FROM 和 SKIN_SMTP_USER 都为空至少提供一个有效 From 地址
邮箱功能直接返回 503邮件配置被视为未配置检查 SKIN_SMTP_HOST、From、User
OIDC issuer 与实际域名不一致未设置 SKIN_OIDC_ISSUER 且 SKIN_BASE_URL 指向内网显式设置 SKIN_OIDC_ISSUER
纹理或头像链接错误SKIN_BASE_URL 不包含正确域名或端口检查站点根地址
Union 启用时报错缺少必填成员密钥、Hub 公钥或 API Root检查 SKIN_UNION_* 配置
认证频繁 429SKIN_RATE_LIMIT_AUTH 过低或存在共享 NAT调整限流阈值或扩容实例
登录失败后被锁定SKIN_LOGIN_FAIL_LIMIT 触发连续失败锁等待锁定时长或检查客户端重试逻辑
迁移未执行SKIN_AUTO_MIGRATE 未启用或迁移目录不正确检查 SKIN_AUTO_MIGRATE 和 SKIN_MIGRATIONS_DIR
访问日志没有详情诊断窗口未开启确认诊断模式开关

章节来源

结论 ​

SKIN_* 环境变量构成了 SkinNexus 的全部运行时配置入口。其中:

  • SKIN_DATABASE_DSN 决定数据库引擎和连接方式。
  • SKIN_BASE_URL 是 OIDC issuer、Webhook 回调、皮肤分发 URL 和纹理 URL 的共同基础。
  • SKIN_SMTP_* 控制密码恢复邮件;为空表示关闭。
  • SKIN_OIDC_* 启用内部 OIDC 提供者。
  • SKIN_UNION_* 控制联盟成员站行为,尤其是成员密钥、Hub 公钥和安全级别。
  • SKIN_RATE_LIMIT_AUTH 和 SKIN_LOGIN_FAIL_LIMIT 共同保护认证接口。
  • 插件和主题市场各自拥有独立的市场地址和信任键。
  • 访问日志提供审计能力,但没有 SKIN_LOG_LEVEL 这类通用日志级别变量。
  • 所有密钥都应通过 secret manager 或容器编排平台的机密机制注入,不要写入镜像。

AGPL-3.0 · SkinNexus