HyperKitty 1.3.12 配置参数详解

HyperKitty 1.3.12 三层配置逐项详解:settings.py 安全/数据库/core 集成/搜索/邮件参数表解,归档插件 mailman-hyperkitty.cfg 的 base_url 与 api_key 语义,uwsgi 双协议 socket 与 nginx 反代逐指令说明,附配置生效矩阵、标准验证序列与 8 条真实 FAQ。

HyperKitty邮件列表Django自托管2026/10/26

HyperKitty 1.3.12 配置参数详解

目标:逐项讲透 HyperKitty 1.3.12 的三层配置——Django 主体 settings.py、core 侧归档插件 mailman-hyperkitty.cfg、uwsgi + nginx 服务承载,每个参数给出默认值、实测语义与生产建议,配置示例全部来自真实安装环境(Debian 12 + HyperKitty 1.3.12,实测日期 2026-10-26)。安装过程见 《Debian 12 安装 HyperKitty 1.3.12 指南》。

一、环境信息

  • 软件版本:HyperKitty 1.3.12、mailman-web 0.0.9(Django 工程模板包)、postorius 1.3.13、django-mailman3 1.3.15、Mailman core 3.3.10、uwsgi 2.0.21、nginx 1.22.1、PostgreSQL 15.19
  • 本篇涉及的配置文件清单(实测环境中的真实路径):
文件归属职责
/etc/mailman3/settings.pyHyperKitty(Django 主体)安全、数据库、与 core 集成、搜索、邮件、本地化
/etc/mailman3/mailman-hyperkitty.cfg归档插件(core 侧)推送目标与认证令牌
/etc/mailman3/mailman.cfg([archiver.hyperkitty] 段)Mailman core归档器启停开关与插件指定
/etc/uwsgi/mailman-web.iniuwsgiWSGI 应用承载参数
/etc/nginx/sites-available/mailman-webnginx反代与静态资源
  • 配置装载机制(实测验证):mailman-web 0.0.9 的 wsgi 与管理命令入口先执行 mailman_web.manage.setup(),读取环境变量 MAILMAN_WEB_CONFIG(缺省 /etc/mailman3/settings.py),将 DJANGO_SETTINGS_MODULE 指向该文件——因此 uwsgi 与 systemd 单元里的 env = MAILMAN_WEB_CONFIG=/etc/mailman3/settings.py 是配置生效的总开关。
  • 生效方式:settings.py 与 uwsgi.ini 改后 systemctl restart mailman-web;mailman-hyperkitty.cfg 改后 systemctl restart mailman3 mailman-web;nginx 站点改后 nginx -t && systemctl reload nginx。所有回显均实测采集。

二、配置体系总览

HyperKitty 的配置分散在三个层次,理解「谁加载谁、改哪层、怎么生效」是配置管理的核心:

浏览器/nginx
   │
   ▼
uwsgi(/etc/uwsgi/mailman-web.ini)
   │  env: MAILMAN_WEB_CONFIG=/etc/mailman3/settings.py
   ▼
HyperKitty Django 应用(/etc/mailman3/settings.py 覆盖 mailman_web.settings.base 默认值)
   │                                    ▲
   │ MAILMAN_REST_API_* 读 core         │ MAILMAN_ARCHIVER_KEY 校验推送
   ▼                                    │
Mailman core(REST 8001)── 归档插件 mailman_hyperkitty
   ([archiver.hyperkitty] 开关 ──▶ /etc/mailman3/mailman-hyperkitty.cfg:推送地址+令牌)
层次文件加载方改后生效动作
Django 主体/etc/mailman3/settings.pyuwsgi 与所有 mailman-web 命令restart mailman-web
归档插件/etc/mailman3/mailman-hyperkitty.cfgcore 的归档插件进程restart mailman3(重读)与 mailman-web(令牌侧)
归档器开关/etc/mailman3/mailman.cfg [archiver.hyperkitty]core 启动时restart mailman3
应用承载/etc/uwsgi/mailman-web.iniuwsgirestart mailman-web
入口反代nginx 站点nginxreload nginx

优先级关系:settings.py 逐行 from mailman_web.settings.base import * 之后写覆盖项,后写的值生效;mailman.cfg 的 [archiver.hyperkitty] 只管「插件装不装、配置在哪」,推送行为细节全在 mailman-hyperkitty.cfg。

三、settings.py 核心参数详解

3.1 实测配置全文

(来自实测环境 /etc/mailman3/settings.py,生产可直接套用后按 3.2 的表逐项核对)

from mailman_web.settings.base import *
from mailman_web.settings.mailman import *

SECRET_KEY = "hk3-prod-secret-key-change-me-0123456789abcdef"
DEBUG = False
ALLOWED_HOSTS = ["hk1.example.com", "localhost", "127.0.0.1"]

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.postgresql",
        "NAME": "mailmanweb",
        "USER": "mailman",
        "PASSWORD": "q1w2e3r4",
        "HOST": "localhost",
        "PORT": "5432",
    }
}

TIME_ZONE = "Asia/Shanghai"
USE_TZ = True

STATIC_ROOT = "/opt/mailman/mm/static"
MEDIA_ROOT = "/opt/mailman/mm/media"
STATIC_URL = "/static/"
MEDIA_URL = "/media/"

MAILMAN_REST_API_URL = "http://localhost:8001"
MAILMAN_REST_API_USER = "restadmin"
MAILMAN_REST_API_PASS = "restpass"
MAILMAN_ARCHIVER_KEY = "SecretArchiverAPIKey"
MAILMAN_ARCHIVER_FROM = ("127.0.0.1", "::1")

POSTORIUS_TEMPLATE_BASE_URL = "http://localhost:8000"
DEFAULT_FROM_EMAIL = "hyperkitty@example.com"
SERVER_EMAIL = "hyperkitty@example.com"
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
ACCOUNT_DEFAULT_HTTP_PROTOCOL = "http"

HAYSTACK_CONNECTIONS = {
    "default": {
        "ENGINE": "haystack.backends.whoosh_backend.WhooshEngine",
        "PATH": "/opt/mailman/mm/fulltext_index",
    }
}

3.2 参数逐项详解

安全类

参数默认值实测值说明与生产建议
SECRET_KEYbase 内置固定串演示串Django 会话/CSRF/密码重置令牌的签名密钥。生产必须换 ≥50 位随机串(python3 -c "import secrets; print(secrets.token_urlsafe(50))");泄露等于可伪造任意用户会话;更换后全部会话失效(FAQ 8.1)
DEBUGFalse(base)False调试页会暴露配置与栈信息,生产恒 False;临时开启排障后立即改回
ALLOWED_HOSTSbase 预置 localhost 等hk1.example.com, localhost, 127.0.0.1Host 头白名单;只放真实对外域名,遗漏会得到 400(FAQ 8.3);多域名逗号分隔
ACCOUNT_DEFAULT_HTTP_PROTOCOLhttphttpdjango-allauth 生成的账号链接协议;上 HTTPS 后必须同步改 https,否则找回密码等链接走错协议

数据库类

参数说明与生产建议
DATABASES.defaultHyperKitty 独立库。实测 mailmanweb,与 core 的 mailman 库分离,备份策略可分别制定;ENGINE 按需换 mysql/sqlite(官方支持,生产推荐 postgresql)
HOST/PORT实测 localhost:5432 走 TCP+密码;改动后仅需 restart mailman-web,Django 会自动执行连接迁移检查

与 Mailman core 集成类(本组是 HyperKitty 配置的灵魂)

参数默认值实测值说明与生产建议
MAILMAN_REST_API_URLhttp://localhost:8001同默认core REST 地址;HyperKitty/Postorius 经它读列表、订阅者数据;core 只绑 127.0.0.1 时本机直连即可,跨机部署改 core 主机地址并同步 core 侧 [webservice]
MAILMAN_REST_API_USER / PASSrestadmin/restpass(base 默认)restadmin/restpassREST 凭据,与 mailman.cfg [webservice] 成对修改;生产务必改掉默认口令
MAILMAN_ARCHIVER_KEY无默认(必配)SecretArchiverAPIKey归档推送的 Token 令牌,与 core 侧 mailman-hyperkitty.cfg 的 api_key 完全一致;不一致时推送被 403 拒绝、邮件进 spool(FAQ 8.2)
MAILMAN_ARCHIVER_FROM("127.0.0.1", "::1")同默认允许向归档 API 推信的来源地址白名单;core 在本机即保持默认,core 跨机部署时加入其出口 IP;白名单外来源一律 403
POSTORIUS_TEMPLATE_BASE_URL无http://localhost:8000Postorius 渲染列表页模板时回源 HyperKitty 的基址;填 nginx 对外地址时注意与 ALLOWED_HOSTS 一致

路径与静态资源类

参数默认值实测值说明与生产建议
STATIC_ROOTbase 内置/opt/mailman/mm/staticcollectstatic 汇集目录,nginx alias 指向它;权限需 uwsgi 运行用户可写
MEDIA_ROOTbase 内置/opt/mailman/mm/media用户上传附件落盘目录,随归档量增长,纳入备份
STATIC_URL / MEDIA_URL/static/、/media/同默认URL 前缀,与 nginx location 一一对应,勿单独改动其一
HAYSTACK_CONNECTIONS.default.PATHbase 内置/opt/mailman/mm/fulltext_indexWhoosh 全文索引目录;全量重建由 mailman-web update_index 完成(见常用 CLI 篇);纳入备份

邮件类

参数默认值实测值说明与生产建议
EMAIL_BACKENDconsole(base)console演示用控制台后端;生产换 django.core.mail.backends.smtp.EmailBackend 并补 EMAIL_HOST/PORT/HOST_USER 等参数,否则用户收不到确认邮件
DEFAULT_FROM_EMAIL / SERVER_EMAILbase 内置hyperkitty@example.com系统发出邮件的发件人地址,应使用真实可回信地址
TIME_ZONE / USE_TZbase 默认Asia/Shanghai / True归档时间戳显示与存储;USE_TZ=True 保持不改,TIME_ZONE 按用户群时区调整

四、归档插件配置 mailman-hyperkitty.cfg 详解

core 侧插件负责把每封过信邮件 HTTP POST 给 HyperKitty,它的配置极简但责任重大:

# /etc/mailman3/mailman-hyperkitty.cfg
[general]
base_url: http://localhost:8000/hyperkitty/
api_key: SecretArchiverAPIKey
参数说明
base_url推送目标基址。指向承载 HyperKitty 的 HTTP 端口(uwsgi 的 http-socket 8000),不是 nginx 的 80、更不是 uwsgi 协议端口——插件是纯 HTTP 客户端。实际推送地址为 {base_url}api/mailman/archive 一族 API;core 到此地址不可达或被拒时,邮件自动落到 core 侧 spool 目录 /opt/mailman/mm/var/archives/hyperkitty/spool/ 等待重试(修复后 core 自动补推,实测积压 2 封在修复后 1 秒内全部补档成功)
api_key与 settings.py 的 MAILMAN_ARCHIVER_KEY 成对的令牌,随请求 Authorization: Token <api_key> 头上送;两端不一致时 HyperKitty 返回 403,推送失败进 spool。生产必须换长随机串

它的启用开关在 core 主配置 /etc/mailman3/mailman.cfg(属 Mailman core 配置体系,此处仅列出与 HyperKitty 相关的三行):

[archiver.hyperkitty]
class: mailman_hyperkitty.Archiver
enable: yes
configuration: /etc/mailman3/mailman-hyperkitty.cfg
  • class:插件 Archiver 类的 Python 路径,来自 mailman-hyperkitty 1.2.1 包;
  • enable: yes:总开关,改 no 后 core 不再推信(只影响新邮件,历史归档不受影响);
  • configuration:指向本章的插件配置文件。

验证推送链路是否就绪(实测回显——用插件同款调用方式直查归档 API,200 即令牌与白名单双通过):

curl -s -o /dev/null -w '%{http_code}\n' \
  'http://127.0.0.1:8000/hyperkitty/api/mailman/urls?mlist=testlist@example.com' \
  -H 'Authorization: Token SecretArchiverAPIKey'
200

五、uwsgi 承载配置详解

/etc/uwsgi/mailman-web.ini(实测全文):

[uwsgi]
plugins = python3
socket = /opt/mailman/mm/uwsgi.sock
chmod-socket = 666
http-socket = 127.0.0.1:8000
chdir = /opt/mailman/web
virtualenv = /opt/mailman/venv
module = mailman_web.wsgi:application
env = MAILMAN_WEB_CONFIG=/etc/mailman3/settings.py
master = true
processes = 4
threads = 2
harakiri = 60
max-requests = 500
vacuum = true
uid = mailman
gid = mailman
logto = /opt/mailman/mm/var/log/uwsgi.log

逐项详解:

参数实测值说明与生产建议
pluginspython3加载 Debian 打包的 Python3 插件,缺失会报 -- unavailable modifier requested
socket/opt/mailman/mm/uwsgi.sockuwsgi 二进制协议 unix socket,供 nginx uwsgi_pass 使用;nginx→uwsgi 全站 502 的第一排查点(FAQ 8.4)
chmod-socket666让 nginx 运行用户(www-data)可读写该 sock;权限不对同样是 502
http-socket127.0.0.1:8000原生 HTTP 监听,供 core 归档插件推送(插件是 HTTP 客户端,说不了 uwsgi 协议);与 socket 行并存、各服务其主——只留一行必踩 502 或 RemoteDisconnected 二选一(FAQ 8.2/8.4)
chdir / module/opt/mailman/web / mailman_web.wsgi:application直接使用 mailman-web 包内置工程,无需自建 Django 项目
virtualenv/opt/mailman/venv应用运行环境隔离,与 4.4 步骤的安装环境一致
envMAILMAN_WEB_CONFIG=/etc/mailman3/settings.pysettings 装载总开关(见第一章),漏写则应用落到内置默认配置、数据库连不上
processes / threads4 / 2worker×线程池;归档渲染有 MIME 解析开销,2C4G 建议从 4×2 起步观察
harakiri60单请求 60 秒强杀,防超大附件渲染占死 worker;大 mbox 导入场景可临时调大
max-requests500每 500 请求回收 worker,抑制内存泄漏
vacuum / uid / gidtrue / mailman / mailman退出自清理 sock 与 pid;以专用系统用户运行
logto…/var/log/uwsgi.log应用日志落盘,排障第一现场

六、nginx 反代配置详解

/etc/nginx/sites-available/mailman-web(实测全文):

server {
    listen 80;
    server_name hk1.example.com;

    access_log /var/log/nginx/mailman-web.access.log;
    error_log  /var/log/nginx/mailman-web.error.log;

    client_max_body_size 20m;

    location /static/ {
        alias /opt/mailman/mm/static/;
        expires 30d;
    }

    location /media/ {
        alias /opt/mailman/mm/media/;
        expires 7d;
    }

    location / {
        include uwsgi_params;
        uwsgi_pass unix:/opt/mailman/mm/uwsgi.sock;
        uwsgi_read_timeout 300;
    }
}

逐项详解:

指令说明与生产建议
server_name与 settings.py 的 ALLOWED_HOSTS 一致;两者不一致时 Django 直接 400
client_max_body_size 20mnginx 默认 1m 会拦掉大附件上传与归档导入,按业务放宽
location /static/alias 指向 STATIC_ROOT,动静分离;expires 30d 带版本指纹的静态资源可长缓存
location /media/用户附件目录,注意目录权限与敏感文件泄露(不允许目录索引)
uwsgi_pass unix:…uwsgi 二进制协议走 unix socket(对应 uwsgi.ini 的 socket 行);这是与一般 HTTP 反代最大的差异点
uwsgi_read_timeout 300慢请求(搜索、导入)容忍上限,与 harakiri 配合观察

改后生效与验证:

nginx -t && systemctl reload nginx
curl -sI http://127.0.0.1/ | head -3
HTTP/1.1 301 Moved Permanently
Server: nginx/1.22.1
Date: Mon, 26 Oct 2026 04:09:40 GMT

(根路径 301 到 HyperKitty/Postorius 默认列表页;curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/hyperkitty/ 返回 200 即入口正常。)

七、配置变更生效矩阵与验证

改动需要的动作连带影响
settings.py 任意参数systemctl restart mailman-webuwsgi 短暂重启,约 1–2 秒闪断
SECRET_KEYrestart mailman-web全体用户重新登录
MAILMAN_ARCHIVER_KEYrestart mailman3 与 mailman-web(两端成对改)改动间隙推送失败,邮件进 spool,恢复后自动补推
mailman-hyperkitty.cfg base_urlrestart mailman3同上,注意 spool 清零确认
[archiver.hyperkitty] enablerestart mailman3关闭后新邮件停止归档
uwsgi.inirestart mailman-web同 settings.py
nginx 站点nginx -t && reload nginx无感热加载

变更后的标准验证序列(全部实测通过):① systemctl is-active mailman3 mailman-web nginx postgresql postfix 五服务全 active;② mailman info 打印 db url 与 REST 地址;③ 归档 API Token 查询 200(4.4 节命令);④ curl -o /dev/null -w '%{http_code}' http://127.0.0.1/hyperkitty/ 得 200;⑤ core 归档日志出现 HyperKitty archived message <msgid> to … 且 spool 目录为空。

八、常见问题(FAQ)

Q1:换了 SECRET_KEY 之后发生什么? 所有已签发会话立即失效,用户需重新登录;密码重置链接作废。归档数据与账号本体不受影响。生产建议在首次上线前就定好强随机值并纳入配置备份。

Q2:归档推送报 403 或邮件堆在 spool? 三处逐一核对:mailman-hyperkitty.cfg 的 api_key 与 settings.py 的 MAILMAN_ARCHIVER_KEY 是否逐字符一致;base_url 指向的端口是否有 HTTP 服务应答(uwsgi 必须有 http-socket 行);来源 IP 是否在 MAILMAN_ARCHIVER_FROM 白名单内。修复后无需手工清 spool——core 自动重试补推(实测两封积压邮件修复后 1 秒内归档成功)。

Q3:页面报 400(Bad Request)? 请求 Host 头不在 ALLOWED_HOSTS 白名单。补上真实访问域名(nginx server_name 同步核对)后 restart mailman-web。

Q4:nginx 全站 502,sock 文件也在? uwsgi.ini 缺 socket = 行(只写了 http-socket)。nginx 的 uwsgi_pass 需要uwsgi 二进制协议,socket 与 http-socket 必须并存(第五章)。同时核对 chmod-socket 666 是否被改过——权限收窄后 www-data 打不开 sock 同样 502。

Q5:页面样式全丢,静态资源 404? collectstatic 没跑或 STATIC_ROOT 变更后 nginx 未同步。执行 mailman-web collectstatic --noinput(实测回显 0 static files copied … 387 unmodified. 属复检正常态,首启为 387 copied),确认 nginx alias 指向新路径后 reload。

Q6:搜索一直无结果? Whoosh 索引目录为空或权限不可写。mailman-web update_index 全量重建(实测归档两封邮件后重建立即可搜);确认 settings.py 的 HAYSTACK PATH 目录属主与 uwsgi 运行用户一致。

Q7:归档邮件时间显示不对? 核对 settings.py 的 TIME_ZONE 与 USE_TZ;USE_TZ 必须为 True(存 UTC、显示按时区),只改 TIME_ZONE 不改 USE_TZ 会出现历史时间整体偏移。

Q8:想把 HyperKitty 挂到 / 前缀以外的子路径? 需要同时改:nginx location 加路径前缀、settings.py 的 STATIC_URL/MEDIA_URL 前缀、uwsgi 无需动;HyperKitty 官方不建议子路径部署,优先用独立子域名。

九、参考链接

(实测环境:Debian 12 + HyperKitty 1.3.12,配置文件与全部回显采集日期 2026-10-26)