Inboxen 2026.2.22.0.27.49 配置参数详解

Inboxen 2026.2.22.0.27.49 配置体系详解:inboxen.config 加载机制与全部参数组、settings.py 硬编码安全项与 debug 联动、Salmon 收信设置覆盖、Postfix 收信链路对接参数,逐项配置片段与实测生效验证。

InboxenInboxen邮件服务2026/10/26

Inboxen 2026.2.22.0.27.49 配置参数详解

目标:把 Inboxen 2026.2.22.0.27.49 的配置体系一次讲透——inboxen.config 主配置的加载机制与全部参数组、settings.py 中硬编码的安全与调度参数、以及收信链路上 Postfix 侧的对接参数,每项给出配置片段与生效验证方法。本文基于《Debian 12 安装 Inboxen 2026.2.22.0.27.49 指南》的实测环境展开,全部验证输出均为实测记录。

一、环境信息

项目值
操作系统Debian GNU/Linux 12.15 (bookworm)
Inboxen 版本2026.2.22.0.27.49(pip 包安装,venv 位于 /opt/inboxen/env)
Python3.12.12
应用目录/opt/inboxen/app(inboxen.config 所在的工作目录)
数据库PostgreSQL 15.19(127.0.0.1:5432/inboxen)
Celery brokerRedis 7.0.15(127.0.0.1:6379/0)
收信链路Postfix 3.7.11 → Salmon([::1]:8823)
管理员账号admin / q1w2e3r4
源码参照https://codeberg.org/Inboxen/Inboxen main 分支(main@000eee1,2026-10-26 实查)
实测日期2026-10-26

Inboxen 的参数分布在两层,职责不同:

层载体可配置性典型内容
业务配置层inboxen.config(YAML)运维者按需编写数据库、broker、注册开关、限速、站点信息等
框架行为层inboxen/settings.py(pip 包内置)一般不动,可写 settings 覆盖模块改写安全头、会话策略、Celery 队列拓扑、定时任务表

二、inboxen.config 加载机制

2.1 四级查找顺序

配置文件从 inboxen/config.py 启动时按以下顺序查找(源码实查,2026-10-26):

优先级位置说明
1环境变量 INBOX_CONFIG 指定的绝对路径代码实读的是 INBOX_CONFIG
2当前工作目录下的 inboxen.configpip 包形态下 inboxen 命令的默认行为
3~/.config/inboxen/inboxen.config用户级配置
4包内仓库根目录(manage.py 同级)的 inboxen.config源码形态默认位置

四处都没有时启动直接报错:ImproperlyConfigured: You must provide a inboxen.config file。

⚠️ 实测发现:注释与代码不一致。config.py 源码顶部注释写「The environment variable "INBOXEN_CONFIG"」,但代码实际读取的是 INBOX_CONFIG。在实测环境用同一个探针配置文件分别验证:

INBOX_CONFIG=/root/probe-order.config inboxen …     # SITE_NAME = 'ORDER-PROBE-SITE'(探针配置生效)
INBOXEN_CONFIG=/root/probe-order.config inboxen …   # SITE_NAME = "LazyAdmin.com's Inboxen"(探针配置被忽略)

结论以代码为准:用 INBOX_CONFIG,写 INBOXEN_CONFIG 不生效。

2.2 默认值合并规则

加载后框架把用户配置与内置默认值(inboxen/config_defaults.yaml)做深度合并(setdefault_deep):只写想覆盖的键,其余自动落到官方默认值。因此一份最小可用的 inboxen.config 只需写 secret_key,其余全部继承默认。

实测默认值全文(config_defaults.yaml,2026.2.22.0.27.49):

admins: []
allowed_hosts: []
cache:
  backend: "django.core.cache.backends.filebased.FileBasedCache"
  location: "inboxen_cache"
  timeout: 300
database:
    host: ""
    name: "inboxen"
    password: ""
    port: ""
    user: ""
debug: false
enable_inbox_creation: true
enable_registration: false
inbox_length: 6
issue_link: "https://codeberg.org/Inboxen/Inboxen/issues"
language_code: "en-gb"
media_root: "media_content"
templates: "extra_templates"
per_user_email_quota: 0
ratelimits:
    inbox:
        count: 100
        window: 1440
    login:
        count: 5
        window: 60
    register:
        count: 5
        window: 30
    single_email:
        count: 100
        window: 60
    search:
        count: 5
        window: 30
server_email: "django@localhost"
site_name: "LazyAdmin.com's Inboxen"
site_url: ""
source_link: "https://codeberg.org/Inboxen/Inboxen"
static_root: "static_content"
tasks:
    always_eager: false
    broker_url: "amqp://guest:guest@localhost:5672//"
    liberation:
        path: "liberation_store"
        sendfile_backend: "django_sendfile.backends.simple"
time_zone: "UTC"

💡 技术拓展:secret_key 是唯一没有默认值的必填项——它用于 Django 会话与 CSRF 签名,泄露等于接管全部用户会话。生产环境用 openssl rand -hex 32 生成;更换 key 会使所有已登录会话失效(签名验不过),属于正常安全行为而非故障。

2.3 实测环境的主配置

以下为实测环境 /opt/inboxen/app/inboxen.config 全文(后续各节逐项解释):

debug: true
secret_key: "b1-experiment-only-026-1nboxen-test-key"
database:
    engine: "django.db.backends.postgresql"
    host: "127.0.0.1"
    name: "inboxen"
    user: "inboxen"
    password: "q1w2e3r4"
    port: "5432"
tasks:
    broker_url: "redis://127.0.0.1:6379/0"
enable_registration: true
allowed_hosts:
    - "*"

三、数据库配置(database 组)

database:
    host: "127.0.0.1"
    name: "inboxen"
    user: "inboxen"
    password: "q1w2e3r4"
    port: "5432"
键默认值说明
host""空 = 走 Unix socket;TCP 部署必须写
nameinboxen库名
user / password""连接凭据
port""空 = 5432 默认端口

三个实测要点:

  1. 数据库引擎不可配置:settings.py 中硬编码 django.db.backends.postgresql_psycopg2,PostgreSQL 是唯一支持的生产数据库,inboxen.config 里写 database.engine 并不生效(本实测配置里保留了这一行,属于无效键,框架忽略)。
  2. psycopg2 为源码构建:pip 安装时无预编译 wheel,需系统预装 libpq-dev(提供 pg_config),否则安装失败。
  3. 生效验证:
cd /opt/inboxen/app
/opt/inboxen/env/bin/python -c "
import django, os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'inboxen.settings')
django.setup()
from django.conf import settings
db = settings.DATABASES['default']
print(db['ENGINE'], db['USER'], db['HOST'], db['PORT'], db['NAME'])
"

实测回显:

django.db.backends.postgresql_psycopg2 inboxen 127.0.0.1 5432 inboxen

💡 技术拓展:Django 数据库引擎命名里 postgresql_psycopg2 与 postgresql 在新版 Django 中等价(2.0 起官方移除旧 psycopg1 支持后统一指向 psycopg2);Inboxen 沿用旧写法只是历史习惯,排查连接问题时两者可互换理解。

四、任务队列与缓存配置

4.1 tasks 组(Celery)

tasks:
    broker_url: "redis://127.0.0.1:6379/0"
    always_eager: false
    liberation:
        path: "liberation_store"
        sendfile_backend: "django_sendfile.backends.simple"
键默认值说明
broker_urlamqp://guest:guest@localhost:5672//Celery broker;官方默认 RabbitMQ,小实例换 Redis 需补装 redis 包
always_eagerfalsetrue 时任务同步执行(测试用),生产必须 false
liberation.pathliberation_store用户全量导出数据的存放目录(相对工作目录)
liberation.sendfile_backenddjango_sendfile.backends.simple导出下载加速后端,可换 nginx sendfile 等

Celery 队列拓扑与定时任务表在 settings.py 中硬编码(不可经 inboxen.config 修改),排障时需要知道:

定时任务crontab作用
statistics每日 00:11统计任务
cleanup每日 01:03清理孤儿模型
sessions每日 02:12清理过期会话
auto-delete每日 03:07自动删除到期邮件
quota每小时第 32 分计算用户配额
suspended每日 04:14挂起账户处理
monitor每 3 小时第 56 分任务健康自检

生效验证(实测回显节选):

CELERY_BROKER_URL = 'redis://127.0.0.1:6379/0'
CELERY_RESULT_BACKEND = 'django-db'

💡 技术拓展:Celery 结果默认存回 PostgreSQL(django-db 后端),因此Redis 只承担 broker 职责——即使 Redis 数据丢失,已完成的任务结果仍在库里,只有排队中的任务会丢。这决定了备份策略:保 PostgreSQL 即可保业务数据,Redis 可随实例重建。

4.2 cache 组

cache:
    backend: "django.core.cache.backends.filebased.FileBasedCache"
    location: "/opt/inboxen/app/inboxen_cache"
    timeout: 300
键默认值说明
backendFileBasedCache可换 Memcached(需装 pylibmc)
locationinboxen_cache(相对路径)建议写绝对路径
timeout300缓存秒数

默认相对路径会触发 Django 启动告警,实测回显:

WARNINGS:
?: (caches.W003) Your 'default' cache LOCATION path is relative. Use an absolute path instead.

把 cache.location 改为绝对路径后告警消失。缓存承担登录限速计数、搜索限速等(见第七节),清空缓存会重置全部限速冷却窗口。

五、站点信息与路径配置

键默认值说明实测生效值
site_nameLazyAdmin.com's Inboxen(上游默认残留)页面标题与发信前缀 [site_name] 建议必改
site_url""管理员通知邮件里引用的站点地址
server_emaildjango@localhost系统发信地址
admins[]管理员通知列表,[["名字","邮箱"],…]
source_linkCodeberg 仓库地址页面「源码」入口;AGPLv3 改码实例应指向自己的公开仓库
issue_linkCodeberg issues页面「反馈」入口
language_codeen-gb界面回退语言
time_zoneUTC展示时区
static_rootstatic_contentcollectstatic 输出目录
media_rootmedia_content媒体目录
templatesextra_templates自定义模板目录

全部路径相对工作目录解析(os.path.join(os.getcwd(), …)),因此 pip 包形态下必须固定工作目录运行(cd /opt/inboxen/app 后再启动各进程),否则静态资源/媒体/导出目录会漂移。实测生效值(/opt/inboxen/app):

STATIC_ROOT = '/opt/inboxen/app/static_content'
MEDIA_ROOT = '/opt/inboxen/app/media_content'
INBOXEN_EXTRA_TEMPLATE_DIR = '/opt/inboxen/app/extra_templates'
SENDFILE_ROOT = '/opt/inboxen/app/liberation_store'

六、注册与收件箱策略配置

enable_registration: true
enable_inbox_creation: true
inbox_length: 6
per_user_email_quota: 0
键默认值说明
enable_registrationfalse是否开放公网注册;内部分发账号的场景建议保持关闭
enable_inbox_creationtrue全局建箱开关(2026.2.22 新增),置 false 后所有用户都无法新建收件箱
inbox_length6自动生成收件箱地址的本地部份长度(小写字母)
per_user_email_quota0单用户邮件持有上限,0 不限;配合每日 auto-delete 任务回收空间

配套的账户挂起策略在 settings.py 硬编码(USER_SUSPEND_TASKS):注册 30 天未登录、登录后 90/180/360 天不活跃分别触发「删邮件 / 删账户」的分级清理,这一机制与 per_user_email_quota 共同构成磁盘空间的自动回收闭环。

生效验证(实测回显):

ENABLE_REGISTRATION = True
ENABLE_INBOX_CREATION = True
INBOX_LENGTH = 6
PER_USER_EMAIL_QUOTA = 0

七、限速参数(ratelimits 组)

五组独立限速,键为 {count: 次数, window: 分钟}:

组默认值约束对象
login5 次 / 60 分钟失败登录尝试
register5 次 / 30 分钟按 IP 注册
inbox100 次 / 1440 分钟建收件箱
single_email100 次 / 60 分钟单封邮件下载
search5 次 / 30 分钟搜索

计数存在缓存后端(键前缀 inboxen-login- 等),生效验证实测回显:

LOGIN_LIMIT_WINDOW = 60
LOGIN_LIMIT_COUNT = 5
REGISTER_LIMIT_WINDOW = 30
REGISTER_LIMIT_COUNT = 5
SINGLE_EMAIL_LIMIT_WINDOW = 60
SINGLE_EMAIL_LIMIT_COUNT = 100
INBOX_LIMIT_WINDOW = 1440
INBOX_LIMIT_COUNT = 100
SEARCH_LIMIT_WINDOW = 30
SEARCH_LIMIT_COUNT = 5

⚠️ 自托管一次性邮箱天然会被用于绕过他人注册风控,公网实例建议至少收紧 register 与 inbox 两组;配合 enable_registration: false(关闭注册)是最彻底的防滥用组合。

八、安全设置(settings.py 硬编码层)

以下安全参数不在 inboxen.config 中,硬编码于 inboxen/settings.py(2026.2.22.0.27.49 实查):

参数值行为
SECURE_SSL_REDIRECTTrue全站 HTTP 301 跳 HTTPS
SECURE_HSTS_SECONDS31536000HSTS 一年,含子域 + preload
SESSION_COOKIE_SECURE / CSRF_COOKIE_SECURETrueCookie 仅 HTTPS 传输
SESSION_COOKIE_AGE604800会话 7 天
X_FRAME_OPTIONSDENY禁止被嵌入 iframe
CONTENT_SECURITY_POLICY全部 selfCSP 收紧到同源
SALMON_CHECK_WINDOW3 小时收信进程健康检查窗口

debug 开关对安全参数的整体联动是本层最关键的行为,实测对照(同一实例翻转 debug 前后用探针脚本取值):

参数debug: true(实测)debug: false(生产)
SECURE_SSL_REDIRECTFalseTrue
SESSION_COOKIE_SECUREFalseTrue
CSRF_COOKIE_SECUREFalseTrue
debug_toolbar注入启用不加载
日志级别Web INFO / Salmon DEBUG均 WARNING

⚠️ 纯 HTTP 部署必须 debug: true 的根因就在这里:生产模式三开关全开,HTTP 访问会被 301 到 HTTPS 且 Cookie 拒绝明文传输,站点表现为「打不开、登不上」。生产正确姿势是置 debug: false 并在 Nginx 做 TLS 终结,让 Django 收到 X-Forwarded-Proto: https。

九、收信进程设置(SALMON_SERVER)

收信监听由 Django settings 的 SALMON_SERVER 控制(同样不在 inboxen.config):

SALMON_SERVER = {"host": "localhost", "port": 8823, "type": "smtp"}
键取值说明
hostlocalhost默认只听本机回环,且实测解析为 IPv6 回环 [::1]
port8823收信管道端口
typesmtp / lmtplmtp 时改走 Unix socket(inboxen/router/config/boot.py 实现了 LMTPReceiver)

覆盖方法(官方 settings.py 头部注释认可的定制方式):新建一个 Python 模块导入默认 settings 后覆盖,再让进程以该模块启动:

# /opt/inboxen/app/settings_local.py
from inboxen.settings import *  # noqa

SALMON_SERVER = {"host": "0.0.0.0", "port": 8823, "type": "smtp"}
export DJANGO_SETTINGS_MODULE=settings_local
export SALMON_SETTINGS_MODULE=inboxen.router.config.settings
/opt/inboxen/env/bin/salmon start --pid run/router.pid --boot inboxen.router.config.boot

适用场景:收信转发来自同一台机器时用默认值即可;当 Postfix 与 Inboxen 分机部署(或需要从其它内网机器直接投递到 8823)时才需要把 host 改为 0.0.0.0 或内网网卡地址。覆盖是否生效用探针验证:

SALMON_SERVER = {'host': '0.0.0.0', 'port': 8823, 'type': 'smtp'}   # 覆盖生效
SALMON_SERVER = {'host': 'localhost', 'port': 8823, 'type': 'smtp'} # 默认值

十、与 Postfix 收信链路对接的参数

Inboxen 不直接面对公网 25 端口,Postfix 侧三个参数决定收信链路能否打通(全部实测):

10.1 relay_domains:登记收信域

postconf -e "relay_domains = inboxen.lan"

声明本机愿意为 inboxen.lan 收信。缺省时外部来信直接 554 Relay access denied。注意不要把收信域加进 mydestination——那会让 Postfix 尝试本地投递而不是走 transport 转交。

10.2 transport_maps:转交 Salmon

echo "inboxen.lan smtp:[::1]:8823" >> /etc/postfix/transport
postconf -e "transport_maps = hash:/etc/postfix/transport"
postmap /etc/postfix/transport

两个实测细节:

  1. 目标必须写 [::1]:8823(带方括号):Salmon 默认只听 IPv6 回环 [::1],写 127.0.0.1 连不上;方括号让 Postfix 跳过 MX 查询按地址直连。
  2. 验证:
postmap -q inboxen.lan hash:/etc/postfix/transport
smtp:[::1]:8823

10.3 maillog_file:日志直写

postconf -e "maillog_file = /var/log/mail.log"
systemctl reload postfix

Debian 12 默认不装 rsyslog,不配此项 Postfix 日志无处可寻,收信排障(status=sent / status=deferred)全靠它。

10.4 链路验证基准

打通后的投递日志基准(实测):

Oct 26 05:27:25 mail postfix/smtp[22504]: 8AC83124B50B: to=<shiunb@inboxen.lan>, relay=::1[::1]:8823, delay=4.1, delays=4/0/0.04/0.01, dsn=2.0.0, status=sent (250 OK)

生产环境还需 DNS 配合:把收信域的 MX 记录指向本机、放行公网 25 端口入站。

十一、配置生效总验证

一份把两层配置一次性核对完的探针脚本(保存为 probe-settings.py 后执行 python probe-settings.py,工作目录 /opt/inboxen/app):

import django, os

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "inboxen.settings")
django.setup()
from django.conf import settings

for k in ["DEBUG", "SITE_NAME", "ENABLE_REGISTRATION", "ENABLE_INBOX_CREATION",
          "INBOX_LENGTH", "PER_USER_EMAIL_QUOTA", "SALMON_SERVER",
          "CELERY_BROKER_URL", "SECURE_SSL_REDIRECT", "SESSION_COOKIE_SECURE"]:
    print(k, "=", repr(getattr(settings, k, "<unset>")))

实测回显(debug: true 环境):

DEBUG = True
SITE_NAME = "LazyAdmin.com's Inboxen"
ENABLE_REGISTRATION = True
ENABLE_INBOX_CREATION = True
INBOX_LENGTH = 6
PER_USER_EMAIL_QUOTA = 0
SALMON_SERVER = {'host': 'localhost', 'port': 8823, 'type': 'smtp'}
CELERY_BROKER_URL = 'redis://127.0.0.1:6379/0'
SECURE_SSL_REDIRECT = False
SESSION_COOKIE_SECURE = False

常见配置错误与排查对照:

现象根因处置
启动报 You must provide a inboxen.config file四级查找位置都没有配置文件在工作目录放 inboxen.config,或用 INBOX_CONFIG 指绝对路径
设置了 INBOXEN_CONFIG 不生效源码注释笔误,代码读的是 INBOX_CONFIG改用 INBOX_CONFIG
启动报 You must set 'secret_key'必填项缺失配置里补 secret_key
纯 HTTP 打不开站点/登不上debug: false 时三安全开关全开实验环境 debug: true;生产上 TLS
启动告警 caches.W003cache.location 相对路径改绝对路径
celery 报 'NoneType' object has no attribute 'Redis'broker 用 Redis 但未装传输包pip install redis
改了 site_name 页面没变改错了层(写进 settings.py 无效键)或进程未重启site_name 属 inboxen.config,改后需重启全部进程
静态资源 404工作目录漂移导致 static_root 落错位置固定 cd /opt/inboxen/app 再启动,重跑 collectstatic

十二、参考链接