Inboxen 2026.2.22.0.27.49 配置参数详解
Inboxen 2026.2.22.0.27.49 配置体系详解:inboxen.config 加载机制与全部参数组、settings.py 硬编码安全项与 debug 联动、Salmon 收信设置覆盖、Postfix 收信链路对接参数,逐项配置片段与实测生效验证。
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) |
| Python | 3.12.12 |
| 应用目录 | /opt/inboxen/app(inboxen.config 所在的工作目录) |
| 数据库 | PostgreSQL 15.19(127.0.0.1:5432/inboxen) |
| Celery broker | Redis 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.config | pip 包形态下 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 部署必须写 |
name | inboxen | 库名 |
user / password | "" | 连接凭据 |
port | "" | 空 = 5432 默认端口 |
三个实测要点:
- 数据库引擎不可配置:settings.py 中硬编码
django.db.backends.postgresql_psycopg2,PostgreSQL 是唯一支持的生产数据库,inboxen.config里写database.engine并不生效(本实测配置里保留了这一行,属于无效键,框架忽略)。 - psycopg2 为源码构建:pip 安装时无预编译 wheel,需系统预装
libpq-dev(提供pg_config),否则安装失败。 - 生效验证:
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_url | amqp://guest:guest@localhost:5672// | Celery broker;官方默认 RabbitMQ,小实例换 Redis 需补装 redis 包 |
always_eager | false | true 时任务同步执行(测试用),生产必须 false |
liberation.path | liberation_store | 用户全量导出数据的存放目录(相对工作目录) |
liberation.sendfile_backend | django_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
| 键 | 默认值 | 说明 |
|---|---|---|
backend | FileBasedCache | 可换 Memcached(需装 pylibmc) |
location | inboxen_cache(相对路径) | 建议写绝对路径 |
timeout | 300 | 缓存秒数 |
默认相对路径会触发 Django 启动告警,实测回显:
WARNINGS:
?: (caches.W003) Your 'default' cache LOCATION path is relative. Use an absolute path instead.
把 cache.location 改为绝对路径后告警消失。缓存承担登录限速计数、搜索限速等(见第七节),清空缓存会重置全部限速冷却窗口。
五、站点信息与路径配置
| 键 | 默认值 | 说明 | 实测生效值 |
|---|---|---|---|
site_name | LazyAdmin.com's Inboxen(上游默认残留) | 页面标题与发信前缀 [site_name] | 建议必改 |
site_url | "" | 管理员通知邮件里引用的站点地址 | |
server_email | django@localhost | 系统发信地址 | |
admins | [] | 管理员通知列表,[["名字","邮箱"],…] | |
source_link | Codeberg 仓库地址 | 页面「源码」入口;AGPLv3 改码实例应指向自己的公开仓库 | |
issue_link | Codeberg issues | 页面「反馈」入口 | |
language_code | en-gb | 界面回退语言 | |
time_zone | UTC | 展示时区 | |
static_root | static_content | collectstatic 输出目录 | |
media_root | media_content | 媒体目录 | |
templates | extra_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_registration | false | 是否开放公网注册;内部分发账号的场景建议保持关闭 |
enable_inbox_creation | true | 全局建箱开关(2026.2.22 新增),置 false 后所有用户都无法新建收件箱 |
inbox_length | 6 | 自动生成收件箱地址的本地部份长度(小写字母) |
per_user_email_quota | 0 | 单用户邮件持有上限,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: 分钟}:
| 组 | 默认值 | 约束对象 |
|---|---|---|
login | 5 次 / 60 分钟 | 失败登录尝试 |
register | 5 次 / 30 分钟 | 按 IP 注册 |
inbox | 100 次 / 1440 分钟 | 建收件箱 |
single_email | 100 次 / 60 分钟 | 单封邮件下载 |
search | 5 次 / 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_REDIRECT | True | 全站 HTTP 301 跳 HTTPS |
SECURE_HSTS_SECONDS | 31536000 | HSTS 一年,含子域 + preload |
SESSION_COOKIE_SECURE / CSRF_COOKIE_SECURE | True | Cookie 仅 HTTPS 传输 |
SESSION_COOKIE_AGE | 604800 | 会话 7 天 |
X_FRAME_OPTIONS | DENY | 禁止被嵌入 iframe |
CONTENT_SECURITY_POLICY | 全部 self | CSP 收紧到同源 |
SALMON_CHECK_WINDOW | 3 小时 | 收信进程健康检查窗口 |
debug 开关对安全参数的整体联动是本层最关键的行为,实测对照(同一实例翻转 debug 前后用探针脚本取值):
| 参数 | debug: true(实测) | debug: false(生产) |
|---|---|---|
SECURE_SSL_REDIRECT | False | True |
SESSION_COOKIE_SECURE | False | True |
CSRF_COOKIE_SECURE | False | True |
| 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"}
| 键 | 取值 | 说明 |
|---|---|---|
host | localhost | 默认只听本机回环,且实测解析为 IPv6 回环 [::1] |
port | 8823 | 收信管道端口 |
type | smtp / lmtp | lmtp 时改走 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]:8823(带方括号):Salmon 默认只听 IPv6 回环[::1],写127.0.0.1连不上;方括号让 Postfix 跳过 MX 查询按地址直连。 - 验证:
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.W003 | cache.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 |
十二、参考链接
- 官方配置文档 The Setting File:
https://inboxen.readthedocs.io/en/latest/settings.html(2026-10-26 查询) - 官方代码仓(config_defaults.yaml / settings.py 取证):
https://codeberg.org/Inboxen/Inboxen(2026-10-26 查询) - 站内关联:《Inboxen 2026.2.22.0.27.49 介绍与选型指南》、《Debian 12 安装 Inboxen 2026.2.22.0.27.49 指南》