Mealie 3.30.0 配置参数详解

Mealie v3.30.0 全部后端环境变量按必配/默认即用/条件启用三级分类详解:General/安全/数据库/SMTP/Webworker/TLS/LDAP/反代认证/OIDC/AI抓取/主题品牌/Docker Secrets 十二组,官方默认值与首启 APP SETTINGS dump 逐项对照,LOG_LEVEL、HTTP_ALLOW_LIST、TOKEN_TIME、DAILY_SCHEDULE_TIME 等关键行为改参闭环实测。

MealieMealie自托管DockerPythonFastAPIPostgreSQL2026/11/02

Mealie 3.30.0 配置参数详解

目标:把 Mealie v3.30.0 的全部后端配置变量按"必配 / 默认即用 / 条件启用"分类讲透——每个分组给出官方默认值、生效条件与本地实测证据。口径来源有二:官方 Backend Configuration 文档全量抓取(1007 行),以及本地实例首次启动打印的 APP SETTINGS 全量 dump(90+ 键)逐项对照;关键行为(LOG_LEVEL、HTTP_ALLOW_LIST、TOKEN_TIME、DAILY_SCHEDULE_TIME、API_HOST、.secret 持久性)均做了改参闭环实测。部署流程见本专栏《Mealie 3.30.0 Docker Compose 部署指南》。

一、环境信息

  • 版本:ghcr.io/mealie-recipes/mealie:v3.30.0(GIT_COMMIT_HASH=9552df62118224a377d9c9b0a62706a62220ab86,APP SETTINGS dump 实测)
  • 官方文档:docs.mealie.io Backend Configuration 页(查询日期 2026-11-02,全文已存档对照)
  • 实测实例:PG 形态 :8152、SQLite 形态 :8157(改参闭环在 SQLite 实例做,避免影响 PG 取证现场)
  • 配置加载方式:全部通过环境变量(compose environment: / docker run -e / Docker Secrets _FILE),无配置文件;改环境变量后需重建容器生效

二、配置如何生效与如何核对(实测)

  1. 改参闭环实测:给 SQLite 实例 compose 加 LOG_LEVEL: debug → docker compose up -d(Recreated)→ 日志立即出现 DEBUG 行(Migration not needed.、Registering daily callback: purge_expired_tokens 等);删掉该行再 up -d → grep -c '^DEBUG' 归 0,回到 INFO。结论:环境变量改动必须经容器重建生效,运行中改 compose 不热加载。
  2. 核对生效值:首次启动日志的 ------APP SETTINGS------ 段会打印全量最终配置(JSON,90+ 键),是"变量到底读没读到"的权威口径。实测踩坑:旧启动日志里 HTTP_ALLOW_LIST 为空串,而 compose 已配置——原因是容器启动早于 compose 编辑;用 docker inspect 查当前容器 Env 确认 HTTP_ALLOW_LIST=10.89.56.0/24 已注入,重建后日志与 inspect 一致。
  3. 密钥持久性:.secret/.session_secret 落在 /app/data 卷内,实测容器 recreate 后旧 access_token 仍有效(JWT 签名密钥未变)。删数据卷 = 全部 token 失效 + 需重新初始化。
  4. 主题/品牌类变量只在启动时读一次(官方明确),改后同样要重启容器;前端浏览器可能缓存旧主题,需清 cookie。

三、变量总览:必配 / 默认即用 / 条件启用

分类变量说明
必配(3 个)BASE_URL、TZ、PUID/PGID(视宿主机目录属主)BASE_URL 影响通知与 OIDC 回调;TZ 默认 UTC 必改;PUID/PGID 默认 911,与数据目录属主对齐
默认即用DB_ENGINE=sqlite、API_PORT=9000、TOKEN_TIME=48、ALLOW_SIGNUP=false、LOG_LEVEL=info、DAILY_SCHEDULE_TIME=23:45、DEFAULT_GROUP=Home、DEFAULT_HOUSEHOLD=Family、API_DOCS=True、ALLOW_PASSWORD_LOGIN=true单机自用可一行不改直接跑
条件启用POSTGRES_*(选 PG 时)、SMTP_*(要发邮件时)、LDAP_* / OIDC_* / REVERSE_PROXY_AUTH_*(接 SSO 时)、SCRAPER_PROXY_URL / SCRAPER_FLARESOLVERR_URL(抓取被反爬时)、HTTP_ALLOW_LIST(要抓内网 URL 时)、THEME_* / BRANDING_*(换肤时)、TLS_*(不走反代直接 https 时)各节展开

四、General 与监听

变量默认说明(含实测)
PUID / PGID911容器运行身份。root 启动时 run.sh 用 gosu 降权并 chown /app;非 root 启动则要求目录属主已匹配
DEFAULT_GROUP / DEFAULT_HOUSEHOLDHome / Family初始化默认组与家务单元名(APP SETTINGS 实测一致)
BASE_URLhttp://localhost:8080对外可达地址,用于通知链接与 OIDC 回调。单机写 http://127.0.0.1:<映射端口>
TOKEN_TIME48登录会话小时数,上限 9600(400 天)。实测签发的 JWT exp = iat+48h,吻合
API_PORT9000后端监听端口。官方明确 Docker 形态不要改(healthcheck.sh 也读它)
API_HOST空监听地址。空=自动开一个 IPv6 dual-stack socket(实测日志 Uvicorn running on socket ('::', 9000),IPv4 同时可达);可显式 0.0.0.0/127.0.0.1/::/::1。端口被占或无权限绑定会直接启动失败
API_DOCSTrue是否暴露 /docs、/redoc。公网部署建议关
TZUTC必设本地时区。实测 DAILY_SCHEDULE_TIME: 23:45 + TZ=Asia/Shanghai → 日志 Daily tasks scheduled for 2026-11-02 15:45:00+00:00(=23:45 CST),排期按本地时间换算
ALLOW_SIGNUPfalse自 v1.4.0 因安全评审改为默认 false。注意:不拦截内置默认管理员,首登改密仍是必须动作
ALLOW_PASSWORD_LOGINtrue是否显示用户名密码登录框。仅 OIDC 场景才考虑关
LOG_LEVELinfocritical/error/warning/info/debug。改参闭环实测见第二节
LOG_CONFIG_OVERRIDEnull自定义日志配置文件路径
DAILY_SCHEDULE_TIME23:45每日任务时间,HH:MM,按服务器本地时间而非 UTC

五、安全

变量默认说明(含实测)
HOST_IP*Uvicorn 信任哪些来源地址送来的 X-Forwarded-For/X-Forwarded-Proto。默认 * 信任所有来源的转发头(可伪造真实 IP),官方要求仅在访问受限时使用;反代场景应设为代理 IP/CIDR(如 127.0.0.1,10.42.1.0/24),设空串=不信任任何转发头。APP SETTINGS 实测默认值 *
SECURITY_MAX_LOGIN_ATTEMPTS5连错次数上限,超过锁号
SECURITY_USER_LOCKOUT_TIME24锁定时长(小时)
ALLOWED_IFRAME_HOSTS空食谱内容里允许内嵌 <iframe> 的额外主机(内置白名单已含 YouTube/Vimeo,子域自动包含,仅 https)。加域名=向包括匿名访客在内的所有人渲染该来源嵌入,谨慎
HTTP_ALLOW_LIST空服务端发起请求(URL 抓取、webhook、recipe actions、OIDC 头像拉取)允许触达的私网/内网 CIDR 或主机。实测:不放行时贴内网 URL 导入被 SSRF 防护拦截;设 10.89.56.0/24 重建后 POST /api/recipes/create-url 成功(返回 slug mapo-tofu)
HTTP_DISALLOW_LIST空永不可达的主机/CIDR,优先级高于 ALLOW_LIST,即使公网地址也拦

六、数据库

变量默认说明(含实测)
DB_ENGINEsqlitesqlite 或 postgres。不设即 SQLite(docker run 实测日志 "DB_ENGINE": "sqlite")
SQLITE_MIGRATE_JOURNAL_WALFalsetrue 则把 SQLite journal 模式切 WAL(多并发/远端存储如 Ceph 场景)。实测默认库 journal_mode=delete(容器内 python sqlite3 查询确认),与默认值吻合;库内共 70 张表
POSTGRES_USERmealie †PG 用户名
POSTGRES_PASSWORDmealie †PG 密码。生产必改或用 secret
POSTGRES_SERVERpostgres †PG 地址(compose 服务名即可)
POSTGRES_PORT5432 †PG 端口
POSTGRES_DBmealie †库名
POSTGRES_URL_OVERRIDENone †整条 DSN 直接覆盖上面五项

† 表示支持 _FILE Docker Secrets 形态(见第十一节)。PG 形态首启实测:alembic 一次跑完 62 个 upgrade 步骤到 head 071e03b4f851,其中 postgres fuzzy search 步骤与库内 pg_trgm 扩展即模糊搜索的实现(SQLite 形态无此能力)。

七、邮件(SMTP)

变量默认说明
SMTP_HOSTNone †必填项
SMTP_PORT587 †必填项
SMTP_FROM_NAMEMealie必填项
SMTP_FROM_EMAILNone必填项
SMTP_AUTH_STRATEGYTLS必填项,可选 TLS/SSL/NONE
SMTP_USER / SMTP_PASSWORDNone †可选,但必须成对设置

用途:邀请注册、找回密码、膳食计划通知。缺必填项不会启动失败,而是功能降级——APP FEATURES 实测打印:--------==SMTP==-------- Enabled: False Reason: Missing required values for ['SMTP_HOST', 'SMTP_FROM_EMAIL']。排查"邮件不发"先看这行。

八、Webworker 与 TLS

变量默认说明
UVICORN_WORKERS1web 进程数。官方警告:调高可能引发内存泄漏类问题,多人卡顿前建议保持默认;APP SETTINGS 另见 WORKER_PER_CORE=1
TLS_CERTIFICATE_PATH / TLS_PRIVATE_KEY_PATHNone仅不挂反代直接对外 https 时用。两者同时设置后 healthcheck.sh 自动改用 https://127.0.0.1:9000/api/app/about 探针(脚本实测,-k 跳过自签证书校验)

九、认证外挂(LDAP / 反代头 / OIDC)

三套都默认关闭,按需启用;首启 APP FEATURES 段会逐个打印判定结果(实测 LDAP ... Reason: LDAP_AUTH_ENABLED is false、OIDC ... Reason: OIDC_AUTH_ENABLED is false)。

LDAP(LDAP_AUTH_ENABLED=False 起):LDAP_SERVER_URL†、LDAP_BASE_DN、LDAP_QUERY_BIND/LDAP_QUERY_PASSWORD†(不设则匿名 bind)、LDAP_USER_FILTER/LDAP_ADMIN_FILTER、LDAP_ID_ATTRIBUTE=uid/LDAP_NAME_ATTRIBUTE=name/LDAP_MAIL_ATTRIBUTE=mail、LDAP_TLS_INSECURE=False、LDAP_TLS_CACERTFILE、LDAP_ENABLE_STARTTLS=False。在内置账号之外叠加 LDAP 验证。

Reverse Proxy Auth(REVERSE_PROXY_AUTH_ENABLED=False 起):信任已认证反代(Authelia/Authentik/oauth2-proxy/Tailscale Serve)转发的用户名头 REVERSE_PROXY_AUTH_HEADER=X-Forwarded-User,访问登录页即自动登入;REVERSE_PROXY_AUTH_SIGNUP_ENABLED=False 控制首见用户自动建号。官方强警告:必须让反代始终覆盖/剥离该头且应用不可被绕过直连,并设置 REVERSE_PROXY_AUTH_SECRET(经 REVERSE_PROXY_AUTH_SECRET_HEADER=X-Mealie-Reverse-Proxy-Secret 传递),否则任何人可伪造头部冒充管理员。

OIDC(OIDC_AUTH_ENABLED=False 起,v1.4.0 引入):核心四件套 OIDC_CONFIGURATION_URL† / OIDC_CLIENT_ID† / OIDC_CLIENT_SECRET†(v2.0.0 起支持 secret)+ 回调地址依赖 BASE_URL。行为开关:OIDC_SIGNUP_ENABLED=True(首登建号)、OIDC_REQUIRES_EMAIL_VERIFICATION=True(v3.21.0 起要求 email_verified claim,仅 IdP 不发该 claim 时关)、OIDC_AUTO_REDIRECT=False(True 则跳过登录页直达 IdP,加 ?direct=1 可绕回)、OIDC_PROVIDER_NAME=OAuth(登录按钮文案)、OIDC_REMEMBER_ME=False。字段映射:OIDC_USER_CLAIM=email、OIDC_NAME_CLAIM=name、OIDC_GROUPS_CLAIM=groups、OIDC_USER_GROUP/OIDC_ADMIN_GROUP(按组放行/提权)。杂项:OIDC_SCOPES_OVERRIDE(至少 openid profile email)、OIDC_TLS_CACERTFILE、OIDC_VERIFY_X509_STRICT=True(Python 3.13 收紧 X509 校验导致部分 CA 证书失败时设 False)、OIDC_CLIENT_TIMEOUT=default(5.0s;None 关闭超时)、OIDC_NATIVE_CLIENT_ID†/OIDC_NATIVE_CONFIDENTIAL=True(Google/Microsoft 等要求独立原生客户端时配)。

十、AI 与抓取器(Scraper)

变量默认说明
YTDLP_COOKIEFILENone视频转写导入(yt-dlp 下载)需登录内容时提供 cookie 文件
SCRAPER_PROXY_URLNone抓取与图片下载的统一出口代理(http://user:pass@host:port),换 IP 信誉绕 IP 封禁
SCRAPER_PROXY_MODEalwaysalways 全走代理;fallback 先直连、被拦才走代理(按流量计费代理用);无法识别的值按 always
SCRAPER_FLARESOLVERR_URLNone自建 FlareSolverr 地址(如 http://flaresolverr:8191),最后手段解 JS/Cloudflare 挑战;只用于食谱页,图片下载永远不走它
SCRAPER_FLARESOLVERR_TIMEOUT60单次挑战最长秒数

官方抓取升级策略(逐步 escalate,首个成功即停):① 直连+轮换浏览器 TLS 指纹(内置,无需配置,多数站点够用)→ ② 代理(设了 SCRAPER_PROXY_URL 才参与)→ ③ FlareSolverr(设了 URL 且仍被拦才用)。真实 404 视为错误,不会重试后两级。AI 供应商(OpenAI 兼容,生成食谱/图像解析)不走环境变量,在管理界面配置(ai providers 表,v3.30.0 迁移含 backfill missing ai provider settings)。

十一、主题与品牌

  • THEME_LIGHT_PRIMARY=#E58325、THEME_LIGHT_ACCENT=#007A99、THEME_LIGHT_SECONDARY=#973542、THEME_LIGHT_SUCCESS=#43A047、THEME_LIGHT_INFO=#1976D2、THEME_LIGHT_WARNING=#FF6D00、THEME_LIGHT_ERROR=#EF5350;深色对应 THEME_DARK_* 同值。共 14 个变量,APP SETTINGS dump 的 theme 对象与默认值逐项吻合(实测)。
  • YAML 引号坑(官方明示):KEY: '#E58325' 必须带引号,否则 # 被 YAML 当注释吃掉;序列写法 KEY=#E58325 则不要引号。改了不生效先查这里,再清浏览器 cookie。
  • BRANDING_NAME=Mealie、BRANDING_LOGO_PATH(容器内路径非 URL,需 bind-mount 图片文件进去;路径无效/类型不认识则静默回退内置 logo)。只改顶栏名/页签标题/PWA 名与 logo/favicon,翻译文案与邮件不受影响。同样仅启动时读取一次。

十二、Docker Secrets(_FILE 模式)

自 v2.4.2 起,官方带 † 标记的变量支持追加 _FILE 后缀从文件读值。实测容器内 /app/run.sh 的 secret_supported_vars 白名单共 16 个,与文档 † 完全一致:

POSTGRES_USER / POSTGRES_PASSWORD / POSTGRES_SERVER / POSTGRES_PORT / POSTGRES_DB / POSTGRES_URL_OVERRIDE
SMTP_HOST / SMTP_PORT / SMTP_USER / SMTP_PASSWORD
LDAP_SERVER_URL / LDAP_QUERY_PASSWORD
OIDC_CONFIGURATION_URL / OIDC_CLIENT_ID / OIDC_NATIVE_CLIENT_ID / OIDC_CLIENT_SECRET

规则(文档 + run.sh 源码互证):

  1. 基础变量与 _FILE 同时设置时,secret 永远优先;
  2. _FILE 必须指向可读的常规文件,缺失/非普通文件/不可读 → 启动直接报错退出(run.sh load_secrets || exit 1,即使基础变量也设了);
  3. 文件内容尾部换行会被去掉;结果为空则打 WARN 并以空值覆盖基础变量;
  4. 文件必须在容器降权后的运行用户(默认 911 或你的 PUID)下可读;K8s Secret 的符号链接形态支持(target 为可读常规文件即可);
  5. 未使用的可选项不要设空 _FILE,直接省略;
  6. 官方建议共享环境至少把 POSTGRES_PASSWORD、SMTP_PASSWORD、LDAP_QUERY_PASSWORD 三个转成 secret。

compose 用法示例(官方口径):secrets: 块声明文件 → 服务挂 secrets: → 环境写 POSTGRES_PASSWORD_FILE: /run/secrets/postgres-password(Docker 挂载到 /run/secrets/)。

十三、参考链接

Mealie 3.30.0 配置参数详解 - Quzuo