ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Immich 配置文件指南:IMMICH_CONFIG_FILE 全参数详解与部署级配置管理

Immich 配置文件指南:IMMICH_CONFIG_FILE 全参数详解与部署级配置管理 Immich 配置文件指南IMMICH_CONFIG_FILE 全参数详解与部署级配置管理【免费下载链接】immichHigh performance self-hosted photo and video management solution.项目地址: https://gitcode.com/GitHub_Trending/im/immich本文围绕 Immich 官方的 Config File 文档展开讲解如何用一份 JSON/YAML 配置文件替代 Web 界面来管理整套系统配置包括文件创建与挂载步骤、IMMICH_CONFIG_FILE环境变量的正确用法、官方默认配置的完整参数参考以及从源码层面确认的配置加载、合并、校验与 UI 锁定机制帮助你把 Immich 的配置管理纳入版本控制与自动化部署流程。配置文件定位UI 配置的替代方案Immich 的常规配置入口是 Web 管理界面Administration Settings。但官方同时提供了一条“配置文件”路线A config file can be provided as an alternative to the UI configuration. —— config-file.md使用配置文件有两个关键约束均来自官方文档无需写全量配置文件不必包含示例中的所有键未提供的键会使用默认值这一点在源码的合并逻辑中得到印证见下文“配置加载与合并机制”锁定 UI 编辑一旦设置了IMMICH_CONFIG_FILE就不能再从 Immich Web UI 编辑其他属性。这一行为在源码中是硬性的——SystemConfigService.updateAdminConfig 检测到环境变量存在时直接抛出异常const { configFile } this.configRepository.getEnv(); if (configFile) { throw new BadRequestException(Cannot update configuration while IMMICH_CONFIG_FILE is in use); }因此配置文件的典型使用场景是希望配置可版本化、可 diff、可随部署脚本一起下发的环境CI/CD、多实例、Ansible/Terraform 管理等。此时所有配置修改都应回到文件本身重启后生效。两步完成配置第一步创建配置文件以 JSON 格式创建配置文件例如immich-config.json并把它放在容器内可被 Immich 访问的挂载位置。YAML 格式同样受支持。关于“YAML 也支持”这一点源码给出了直接证据config.ts 中的 loadFromFile 使用js-yaml的load解析文件内容而 JSON 是 YAML 的子集因此两种格式都能正确解析const loadFromFile async ({ metadataRepo, logger }: RepoDeps, filepath: string) { try { const file await metadataRepo.readFile(filepath); return loadYaml(file) as unknown; } catch (error: Error | any) { logger.error(Unable to load configuration file: ${filepath}); logger.error(error); throw error; } };官方文档给出了完整的默认配置示例以下原样继承自 config-file.md{ backup: { database: { cronExpression: 0 02 * * *, enabled: true, keepLastAmount: 14 } }, ffmpeg: { accel: disabled, accelDecode: true, acceptedAudioCodecs: [aac, mp3, opus], acceptedContainers: [mov, ogg, webm], acceptedVideoCodecs: [h264], bframes: -1, cqMode: auto, crf: 23, gopSize: 0, maxBitrate: 0, preferredHwDevice: auto, preset: ultrafast, refs: 0, targetAudioCodec: aac, targetResolution: 720, targetVideoCodec: h264, temporalAQ: false, threads: 0, tonemap: hable, transcode: required, twoPass: false }, image: { colorspace: p3, extractEmbedded: false, fullsize: { enabled: false, format: jpeg, quality: 80 }, preview: { format: jpeg, quality: 80, size: 1440 }, thumbnail: { format: webp, quality: 80, size: 250 } }, job: { backgroundTask: { concurrency: 5 }, faceDetection: { concurrency: 2 }, library: { concurrency: 5 }, metadataExtraction: { concurrency: 5 }, migration: { concurrency: 5 }, notifications: { concurrency: 5 }, ocr: { concurrency: 1 }, search: { concurrency: 5 }, sidecar: { concurrency: 5 }, smartSearch: { concurrency: 2 }, thumbnailGeneration: { concurrency: 3 }, videoConversion: { concurrency: 1 } }, library: { scan: { cronExpression: 0 0 * * *, enabled: true }, watch: { enabled: false } }, logging: { enabled: true, level: log }, machineLearning: { availabilityChecks: { enabled: true, interval: 30000, timeout: 2000 }, clip: { enabled: true, modelName: ViT-B-32__openai }, duplicateDetection: { enabled: true, maxDistance: 0.01 }, enabled: true, facialRecognition: { enabled: true, maxDistance: 0.5, minFaces: 3, minScore: 0.7, modelName: buffalo_l }, ocr: { enabled: true, maxResolution: 736, minDetectionScore: 0.5, minRecognitionScore: 0.8, modelName: PP-OCRv5_mobile }, urls: [http://immich-machine-learning:3003] }, map: { darkStyle: https://tiles.immich.cloud/v1/style/dark.json, enabled: true, lightStyle: https://tiles.immich.cloud/v1/style/light.json }, metadata: { faces: { import: false } }, newVersionCheck: { enabled: true }, nightlyTasks: { clusterNewFaces: true, databaseCleanup: true, generateMemories: true, missingThumbnails: true, startTime: 00:00, syncQuotaUsage: true }, notifications: { smtp: { enabled: false, from: , replyTo: , transport: { host: , ignoreCert: false, password: , port: 587, secure: false, username: } } }, oauth: { autoLaunch: false, autoRegister: true, buttonText: Login with OAuth, clientId: , clientSecret: , defaultStorageQuota: null, enabled: false, issuerUrl: , endSessionEndpoint: , mobileOverrideEnabled: false, mobileRedirectUri: , profileSigningAlgorithm: none, roleClaim: immich_role, scope: openid email profile, signingAlgorithm: RS256, storageLabelClaim: preferred_username, storageQuotaClaim: immich_quota, timeout: 30000, tokenEndpointAuthMethod: client_secret_post }, passwordLogin: { enabled: true }, reverseGeocoding: { enabled: true }, server: { externalDomain: , loginPageMessage: , publicUsers: true }, storageTemplate: { enabled: false, hashVerificationEnabled: true, template: {{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}} }, templates: { email: { albumInviteTemplate: , albumUpdateTemplate: , welcomeTemplate: } }, theme: { customCss: }, trash: { days: 30, enabled: true }, user: { deleteDelay: 7 } }官方文档还给出了一条实用提示Administration Settings 页面里有一个按钮可以把当前生效的完整配置复制到剪贴板。从界面复制 → 粘贴成文件 → 挂载进容器是最省事的上手路径之后只改需要覆盖的键即可。第二步指定文件位置在.env文件中设置变量IMMICH_CONFIG_FILE为配置文件路径更多信息可参考 Environment Variables。官方文档特别强调了一个容易踩坑的细节在.env中UPLOAD_LOCATION和DB_DATA_LOCATION指的是宿主机上的位置而IMMICH_CONFIG_FILE指的是容器内部的位置它的作用是告知immich-server容器“存在一个配置文件”。文档推荐的docker-compose.yml写法是复用同一个变量保证宿主机路径与容器内路径一一对应volumes: - ./immich-config.json:${IMMICH_CONFIG_FILE}即宿主机上的./immich-config.json挂载到容器内${IMMICH_CONFIG_FILE}所指路径。官方 docker-compose.yml 默认并未包含这行 volume启用配置文件时需要自行在immich-server服务的volumes下追加默认已有${UPLOAD_LOCATION}:/data等挂载可作参照。另外文档还提醒如果你有microservicesworker它们同样需要把配置文件挂载进对应容器。在 environment-variables.md 的变量表中IMMICH_CONFIG_FILE的作用范围标注为server组件下的api, microservices两个 worker与这一提醒一致。核心参数分组速查上面的完整 JSON 即官方给出的默认配置全貌以下按分组说明各部分含义及关键取值范围。取值范围来自 config.dto.ts 中的 Zod 校验定义与defaults默认值可据此判断哪些值合法。backup数据库自动备份键默认值说明backup.database.cronExpression0 02 * * *备份 cron 表达式每天凌晨 2 点backup.database.enabledtrue是否启用自动备份backup.database.keepLastAmount14保留最近多少份备份ffmpeg视频转码这是参数最多的一组控制转码策略与编码器参数键默认值说明 / 取值范围acceldisabled硬件加速方式如disabled、nvenc等accelDecodetrue是否启用加速解码acceptedVideoCodecs[h264]无需转码即接受的视频编码acceptedAudioCodecs[aac, mp3, opus]无需转码即接受的音频编码acceptedContainers[mov, ogg, webm]无需转码即接受的容器格式targetVideoCodec/targetAudioCodech264/aac转码目标编码crf23CRF 值校验范围 0–51presetultrafastx264 预设bframes/refs/gopSize-1/0/0B 帧-1–16、参考帧0–6、GOP 大小≥0temporalAQ/twoPassfalse时域自适应量化 / 两遍编码cqModeautoCQ 模式targetResolution720目标分辨率maxBitrate0最大码率0表示不限threads0线程数0为自动tonemaphable色调映射算法transcoderequired转码策略preferredHwDeviceauto首选硬件设备源码中有一处值得注意的归一化逻辑config.ts 的 buildConfig如果你设置的targetVideoCodec/targetAudioCodec不在accepted*列表里系统会自动把它追加进 accepted 列表避免“目标编码反而触发转码”的自相矛盾。image图片生成thumbnail缩略图默认 webp、250px、质量 80preview预览图默认 jpeg、1440px、质量 80fullsize是否生成全尺寸派生图默认关闭格式 jpeg、质量 80colorspace默认p3Display P3extractEmbedded是否提取嵌入图。校验定义要求quality为 1–100 的整数、size为 ≥1 的整数见 AdminConfigGeneratedImageSchema。job后台任务并发度每个任务组只有一个concurrency键校验要求为 ≥1 的整数AdminConfigJobSettingsSchema。默认值任务concurrency任务concurrencythumbnailGeneration3faceDetection2metadataExtraction5smartSearch2videoConversion1backgroundTask5library5migration5search5sidecar5ocr1notifications5这是调优整机吞吐的核心旋钮机器负载高时优先下调ocr、smartSearch、videoConversion这类重任务并发。library / nightlyTasks / trashlibrary.scan每日 0 点0 0 * * *自动扫描外部库默认启用library.watch的实时监听默认关闭nightlyTasks.startTime默认00:00控制人脸聚类、数据库清理、生成回忆、补齐缩略图、配额同步等夜间维护任务的触发时间trash.days回收站保留 30 天。machineLearning机器学习urlsML 服务地址列表默认[http://immich-machine-learning:3003]clipCLIP 模型默认ViT-B-32__openai用于智能搜索duplicateDetection.maxDistance重复照片判定距离默认 0.01facialRecognition模型buffalo_lminScore 0.7、maxDistance 0.5、minFaces 3至少 3 张人脸才聚成一个簇ocr模型PP-OCRv5_mobile检测/识别最低分 0.5/0.8最大分辨率 736availabilityChecks可用性探测超时 2 秒、间隔 30 秒。oauth / notifications / templates / 其他oauth完整 OIDC 客户端配置issuer、client 凭据、scope、签名算法、claim 映射等默认全部关闭enabled: falsenotifications.smtpSMTP 通知默认关闭校验要求port为 0–65535见 AdminConfigSmtpSchematemplates.email欢迎邮件、相册邀请/更新邮件模板storageTemplate对象存储命名模板默认关闭server.externalDomain、server.loginPageMessage、server.publicUsers外部域名、登录页消息、是否公开用户列表theme.customCss全局自定义 CSSuser.deleteDelay用户删除前 7 天延迟软删除保护期passwordLogin.enabled、newVersionCheck.enabled、reverseGeocoding.enabled、map.enabled各功能开关。源码级机制配置是如何加载、合并与校验的读懂 buildConfig 的实现能解释配置文件路线的几个关键行为// load partial const partial configFile ? await loadFromFile(repos, configFile) : await metadataRepo.get(SystemMetadataKey.SystemConfig); // merge with defaults const rawConfig _.cloneDeep(defaults); for (const property of getKeysDeep(partial)) { _.set(rawConfig, property, _.get(partial, property)); }双数据源设置了IMMICH_CONFIG_FILE时从文件读取loadFromFile否则从数据库SystemMetadata表读取即 Web UI 保存的配置。这就是“替代 UI 配置”的实现方式。深合并 部分配置合法默认值先被深克隆再按“配置中出现的每个键”逐个覆盖。因此配置文件可以只写要改的键但注意合并是按你提供的键逐层覆盖嵌套对象整体替换该分支而不是逐字段合并分支内。未知键只告警不报错合并后代码会剔除默认结构中已知的键剩余部分即你写的非法/拼错的键只打印Unknown keys found: ...警告不会使服务崩溃——这意味着拼写错误是静默失效的修改后应留意日志。Zod 全量校验配置文件出错会拒绝启动合并结果用AdminConfigDto.schema.safeParse校验。差异在于来自配置文件时校验失败会直接 throw服务启动失败快速暴露错误来自数据库时仅记录错误日志并使用原始值。所以走文件路线反而更“严格”。环境变量覆盖IMMICH_CONFIG_FILE本身是可选环境变量定义于 EnvSchema经 ConfigRepository 解析为configFile字段后注入配置构建流程。另外两个来自 SystemConfigService 的联动规则日志级别冲突保护如果设置了IMMICH_LOG_LEVEL环境变量则不允许通过配置修改logging段否则在配置校验事件中被拒绝Logging cannot be changed while the environment variable IMMICH_LOG_LEVEL is set.。从源码看IMMICH_LOG_LEVEL的优先级高于配置文件中的logging.level生效时机配置在应用引导AppBootstrap时一次性加载并发出ConfigInit事件其中包含 ML 仓库的初始化因此修改配置文件后需要重启相关容器使其生效。实践建议与常见坑先复制再改用 Web UI 里“复制到剪贴板”的按钮导出当前全量配置作为文件基线再按需增删能避免遗漏必填结构microservices 别忘了挂载api与microservices两个 worker 都要能看到配置文件否则 ML 相关配置machineLearning.urls等在 microservices 侧不生效路径语义IMMICH_CONFIG_FILE是容器内绝对路径与UPLOAD_LOCATION的宿主机路径语义不同务必按文档推荐的./immich-config.json:${IMMICH_CONFIG_FILE}方式统一映射启用即锁定 UI确认团队接受“改配置 改文件 重启”的工作流后再启用回退时只需在.env中移除该变量并恢复数据库配置注意静默失效未知键只产生警告日志校验错误才会导致启动失败配置变更后建议检查启动日志中的Unknown keys found与Invalid system config输出版本对应关系本文参数范围基于当前仓库中 config.dto.ts 的校验定义与默认值升级 Immich 大版本后建议重新核对官方文档中的默认配置示例确认新增/变更的键。小结Immich 的配置文件机制把原本散落在 Web UI 的系统配置收敛为一个可版本化的 JSON/YAML 文件通过IMMICH_CONFIG_FILE指定容器内路径、在docker-compose.yml中挂载到immich-server及 microservices worker即可获得“部分配置合法、深合并默认值、Zod 严格校验、UI 自动锁定”的部署级配置管理。对多实例、自动化部署和配置审计而言这是官方文档给出的标准答案。【免费下载链接】immichHigh performance self-hosted photo and video management solution.项目地址: https://gitcode.com/GitHub_Trending/im/immich创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进