Debian 12 安装 Inboxen 2026.2.22.0.27.49 指南
在 Debian 12 从零安装 Inboxen 2026.2.22.0.27.49 全流程实测:编译 Python 3.12、pip 双源安装、PostgreSQL/Celery/Salmon/Gunicorn+Nginx 部署、Postfix 收信链路对接与 telnet SMTP 端到端验证。
Debian 12 安装 Inboxen 2026.2.22.0.27.49 指南
目标:在一台 Debian 12 服务器上从零安装 Inboxen 2026.2.22.0.27.49,打通「Postfix 收信 → Salmon 收信管道 → Celery 异步处理 → PostgreSQL 落库 → Nginx+Gunicorn Web 展示」的完整闭环,并用 telnet SMTP 会话投递一封真实信件完成端到端验证。本文全部命令与输出均为实测记录。
一、环境信息
| 项目 | 值 |
|---|---|
| 操作系统 | Debian GNU/Linux 12.15 (bookworm) |
| 内核 | 6.1.0-37-amd64 |
| Inboxen 版本 | 2026.2.22.0.27.49(Codeberg 官方 PyPI 索引最新包) |
| Python | 3.12.12(源码编译,/usr/local/python3.12) |
| PostgreSQL | 15.19 (Debian 15.19-0+deb12u1) |
| Redis | 7.0.15 |
| Nginx | 1.22.1 |
| Postfix | 3.7.11 |
| 服务器名/IP | mail.inboxen.lan / 10.89.57.2(局域网测试域) |
| 收信域名 | inboxen.lan |
| 管理员账号 | admin / q1w2e3r4 |
| 实测日期 | 2026-10-26 |
⚠️ 版本前提:Inboxen 2026.2.22.0.27.49 要求 Python ≥ 3.12,而 Debian 12 自带 Python 3.11,因此本文第 4 节先编译 Python 3.12。若使用 Debian 13 (trixie,自带 3.13) 可跳过编译直接
apt install python3-venv python3-dev。
二、前置准备
2.1 配置 APT 源
Debian 12 默认源可用。若在境内网络环境,建议先切 HTTP 形态的镜像源(不要用 HTTPS 源:系统此时还没有 ca-certificates,HTTPS 握手会报 No system certificates available,这是实测踩过的第一个坑):
# 实测:切换镜像源(/etc/apt/sources.list.d/debian.sources)
sed -i 's|http://deb.debian.org/debian|http://mirrors.aliyun.com/debian|g; s|http://deb.debian.org/debian-security|http://mirrors.aliyun.com/debian-security|g' /etc/apt/sources.list.d/debian.sources
apt-get update
2.2 安装编译依赖与服务组件
# 实测(输出末行 EXIT=0)
export DEBIAN_FRONTEND=noninteractive
apt-get install -y -qq build-essential wget ca-certificates curl libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev libffi-dev liblzma-dev libncursesw5-dev \
tk-dev uuid-dev xz-utils pkg-config \
postgresql redis-server nginx postfix libpq-dev
echo EXIT=$?
实测回显(节选):
EXIT=0
实测安装版本核查:
psql --version
nginx -v
postconf mail_version
psql (PostgreSQL) 15.19 (Debian 15.19-0+deb12u1)
nginx version: nginx/1.22.1
mail_version = 3.7.11
💡 libpq-dev 必须装:Inboxen 依赖 psycopg2(源码构建版),没有
pg_config时 pip 安装会在最后一步报ERROR: Failed building wheel for psycopg2,前功尽弃(实测踩坑 2)。
2.3 服务组件就位
systemctl start postgresql redis-server nginx postfix
systemctl is-active postgresql redis-server nginx postfix
实测回显:
active
active
active
active
监听端口核查(PostgreSQL/Redis 默认只听本机回环,Postfix 听 25,Nginx 听 80):
0.0.0.0:25
0.0.0.0:80
127.0.0.1:5432
127.0.0.1:6379
三、创建 PostgreSQL 数据库与用户
# 实测
cat > /tmp/init.sql <<'EOF'
CREATE USER inboxen WITH PASSWORD 'q1w2e3r4';
CREATE DATABASE inboxen OWNER inboxen;
EOF
su postgres -c "psql -f /tmp/init.sql"
实测回显:
CREATE ROLE
CREATE DATABASE
四、编译安装 Python 3.12.12
# 实测:下载约 27 MB
cd /usr/local/src
wget https://www.python.org/ftp/python/3.12.12/Python-3.12.12.tgz
tar xf Python-3.12.12.tgz && cd Python-3.12.12
./configure --prefix=/usr/local/python3.12
make -j$(nproc)
make install
/usr/local/python3.12/bin/python3.12 -V
实测回显:
Python 3.12.12
五、安装 Inboxen 2026.2.22.0.27.49
5.1 建立虚拟环境
# 实测
/usr/local/python3.12/bin/python3.12 -m venv /opt/inboxen/env
5.2 pip 安装(双源)
Inboxen 官方包发布在项目自建的 Codeberg PyPI 索引,依赖包来自公共 PyPI,因此 pip 需要同时配置两个源:
# 实测
/opt/inboxen/env/bin/pip install "inboxen==2026.2.22.0.27.49" \
--index-url https://pypi.org/simple \
--extra-index-url https://codeberg.org/api/packages/inboxen/pypi/simple/
实测回显(关键行):
Successfully installed Django-5.2.18 Faker-40.43.0 Markdown-3.11.2 amqp-5.4.1 asgiref-3.13.0
billiard-4.3.1 cachetools-7.2.5 celery-5.6.3 ... inboxen-2026.2.22.0.27.49 kombu-5.6.2 ...
psycopg2-2.9.13 ... salmon-mail-3.3.0 ...
5.3 补齐三个运行时缺口(实测必踩)
-
setuptools(Python 3.12 移除了 distutils,Inboxen 依赖链里的
django-bootstrap-form仍from distutils.version import StrictVersion,不补则在首次manage.py调用时崩出ModuleNotFoundError: No module named 'distutils'):/opt/inboxen/env/bin/pip install setuptools redis gunicorn django-debug-toolbar其中
redis是 Celery Redis broker 必需的传输包(缺它则 celery 启动即报'NoneType' object has no attribute 'Redis'并退出),gunicorn是 9 节的 WSGI 服务器,django-debug-toolbar是 debug 模式(本教程用 HTTP 部署时)必需项。 -
安装完成后 venv 里自带两个入口命令:
inboxen(等价manage.py)与salmon(收信进程)。pip 包已内置编译好的静态资源,无需 Node.js/npm。
六、编写配置文件 inboxen.config
pip 安装形态下,inboxen 命令以当前工作目录的 inboxen.config 为配置源,先建应用目录:
# 实测
mkdir -p /opt/inboxen/app && cd /opt/inboxen/app
cat > inboxen.config <<'EOF'
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:
- "*"
EOF
字段说明:
| 字段 | 作用 | 备注 |
|---|---|---|
secret_key | Django 会话/CSRF 签名密钥 | 生产环境用 openssl rand -hex 32 生成并妥善保管 |
database.* | PostgreSQL 连接五要素 | 对应第三节创建的库与用户 |
tasks.broker_url | Celery broker | 默认 amqp://(RabbitMQ),本教程用单机 Redis |
enable_registration | 是否开放公网注册 | 默认 false;内网部署可开,公网建议关 |
allowed_hosts | Django ALLOWED_HOSTS | "*" 仅限测试;生产写实际域名 |
debug | Django DEBUG | true 时关闭 HTTPS 强制跳转,适合纯 HTTP 实验;生产置 false 并上 TLS |
⚠️ HTTPS 重定向坑:生产模式(debug 关闭)下 Inboxen 内置
SECURE_SSL_REDIRECT = True,纯 HTTP 访问会 301 跳 https 并打不开站点(实测踩坑 3)。实验环境请保持debug: true;生产环境应配置 Nginx TLS 终结,让 Django 收到X-Forwarded-Proto: https。
七、初始化数据库与基础数据
依次执行迁移、静态资源收集、管理员创建、收信域名登记:
cd /opt/inboxen/app
/opt/inboxen/env/bin/inboxen migrate
实测回显(尾部):
Applying otp_totp.0003_add_timestamps... OK
Applying search.0001_initial_squashed... OK
Applying sessions.0001_initial... OK
Applying tickets.0001_initial_squashed... OK
Applying two_factor.0001_squashed_0008_delete_phonedevice... OK
/opt/inboxen/env/bin/inboxen collectstatic --noinput
实测回显:
26 static files copied to '/opt/inboxen/app/static_content'.
System check identified some issues:
WARNINGS:
?: (caches.W003) Your 'default' cache LOCATION path is relative. Use an absolute path instead.
💡
caches.W003是 FileBasedCache 相对路径的提示性告警,不影响功能;在inboxen.config的cache.location写绝对路径即可消除。
DJANGO_SUPERUSER_PASSWORD=q1w2e3r4 /opt/inboxen/env/bin/inboxen createsuperuser --noinput --username admin --email admin@inboxen.lan
/opt/inboxen/env/bin/inboxen createdomain inboxen.lan
实测回显:
Superuser created successfully.
inboxen.lan created!
八、启动 Celery 与 Salmon 收信进程
准备运行目录,然后分别拉起 Celery worker、beat 与 Salmon SMTP 收信进程:
# 实测
cd /opt/inboxen/app
mkdir -p run logs
export DJANGO_SETTINGS_MODULE=inboxen.settings
nohup /opt/inboxen/env/bin/celery -A inboxen worker -l warning --events -Ofair \
-f logs/celery-worker.log >/dev/null 2>&1 &
nohup /opt/inboxen/env/bin/celery -A inboxen beat -l warning \
-f logs/celery-beat.log >/dev/null 2>&1 &
export SALMON_SETTINGS_MODULE=inboxen.router.config.settings
/opt/inboxen/env/bin/salmon start --pid run/router.pid --boot inboxen.router.config.boot
sleep 5
/opt/inboxen/env/bin/salmon status --pid run/router.pid
实测回显:
Salmon running with PID 21618
监听端口确认:
ss -ltn | grep 8823
LISTEN 0 5 [::1]:8823 [::]:*
⚠️ Salmon 默认只监听 IPv6 回环
[::1]:8823(官方设置项SALMON_SERVER),Postfix 侧转发目标必须写[::1]:8823,写127.0.0.1会连不上。
💡 生产环境建议把以上三个进程写成 systemd 单元(
inboxen-celery-worker.service、inboxen-celery-beat.service、inboxen-salmon.service),WorkingDirectory=/opt/inboxen/app、Environment=DJANGO_SETTINGS_MODULE=inboxen.settings,实现开机自启与崩溃拉起。本文为保持与实测一致,正文采用 nohup 方式。
九、部署 Gunicorn 并配置 Nginx 反代
# 实测:venv 内自带 gunicorn(5.3 节安装),版本 26.2.0
cd /opt/inboxen/app
nohup /opt/inboxen/env/bin/gunicorn inboxen.wsgi -b 127.0.0.1:8000 --workers 2 \
--access-logfile logs/gunicorn-access.log --error-logfile logs/gunicorn-error.log >/dev/null 2>&1 &
Nginx 站点配置(替换 /etc/nginx/sites-available/default):
# 实测配置
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
location /static/ {
alias /opt/inboxen/app/static_content/;
}
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
nginx -t && systemctl reload nginx
curl -s -o /dev/null -w "%{http_code}\n" -L http://127.0.0.1/
实测回显:
nginx: configuration file /etc/nginx/nginx.conf test is successful
200
浏览器访问 http://<服务器IP>/,应看到 Inboxen 欢迎页,右上角可进入 /user/account/login/ 用 admin 登录。
十、配置 Postfix 收信链路
Inboxen 自己不做 MX,公网信件由 Postfix 接收后转发给 Salmon。三个关键参数:
# 实测
# 1) 声明本机为 inboxen.lan 的收信域(允许外部来源投递,否则外网信件 554 Relay access denied)
postconf -e "relay_domains = inboxen.lan"
# 2) transport 表:该域全部转交 Salmon(注意 [::1])
echo "inboxen.lan smtp:[::1]:8823" >> /etc/postfix/transport
postconf -e "transport_maps = hash:/etc/postfix/transport"
postmap /etc/postfix/transport
# 3) 开启 Postfix 自写日志(Debian 12 默认无 rsyslog 时排障必备,Postfix ≥3.4 支持)
touch /var/log/mail.log && chmod 644 /var/log/mail.log
postconf -e "maillog_file = /var/log/mail.log"
systemctl reload postfix
postconf relay_domains
实测回显:
relay_domains = inboxen.lan
配置生效核查:
postmap -q inboxen.lan hash:/etc/postfix/transport
smtp:[::1]:8823
💡 DNS 前提:生产环境需把 inboxen.lan 的 MX 记录指向本服务器,并放行公网 25 端口入站;局域网/测试环境可由上游 MTA 直接把该域路由到本机 25 端口。
十一、创建收件箱并完成端到端验证
11.1 创建第一个收件箱
Inboxen 的收件箱本地部份由系统按 inbox_length(默认 6 位小写字母)随机生成,走标准的 QuerySet 创建入口:
# 实测
cd /opt/inboxen/app
/opt/inboxen/env/bin/python - <<'EOF'
import django, os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "inboxen.settings")
django.setup()
from django.contrib.auth.models import User
from inboxen.models import Inbox, Domain
u = User.objects.get(username="admin")
d = Domain.objects.get(domain="inboxen.lan")
i = Inbox.objects.create(domain=d, user=u)
print("INBOX-ADDR:", i.inbox + "@" + d.domain)
EOF
实测回显:
INBOX-ADDR: shiunb@inboxen.lan
(也可登录 Web 后在 /inbox/add/ 页面点击创建,效果一致。)
11.2 从外部 telnet SMTP 会话投递一封信
在另一台机器上(或本机回环亦可)执行 telnet 会话,完整交互实录如下(每步等待前一响应后再发下一条):
telnet <服务器IP> 25
实测回显(逐行):
220 mail.inboxen.lan ESMTP Postfix (Debian/GNU)
250 mail.inboxen.lan
250 2.1.0 Ok
250 2.1.5 Ok
354 End data with <CR><LF>.<CR><LF>
250 2.0.0 Ok: queued as 8AC83124B50B
221 2.0.0 Bye
对应的输入序列:
HELO client.example.net
MAIL FROM:<sender@example.net>
RCPT TO:<shiunb@inboxen.lan>
DATA
From: Sender <sender@example.net>
To: shiunb@inboxen.lan
Subject: Hello From Telnet
This message was delivered with a plain telnet session.
.
QUIT
⚠️ 时序坑:
DATA正文必须以单独一行.结束,且必须等到250 ... Ok: queued as ...响应出现后再发QUIT。实测中若 telnet 会话在 DATA 结束前断开,Postfix 会直接丢弃信件(队列空、无投递日志、Inboxen 无感知),极易误判为链路故障。
11.3 三重验证
① Postfix 投递日志(信件确实转交 Salmon):
grep "8AC83124B50B" /var/log/mail.log
实测回显:
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)
Oct 26 05:27:25 mail postfix/qmgr[22490]: 8AC83124B50B: removed
② Web 端可见:浏览器登录 admin 后打开 http://<服务器IP>/inbox/shiunb@inboxen.lan/,信件列表出现主题 Hello From Telnet。用命令行验证(先走 /user/account/login/ 表单登录拿会话 Cookie,登录表单是 two_factor 向导,字段为 csrfmiddlewaretoken + login_view-current_step=auth + auth-username + auth-password):
curl -s -b cookies.txt -L http://127.0.0.1/inbox/shiunb@inboxen.lan/ | grep -o "Hello From Telnet"
实测回显:
Hello From Telnet
③ 数据库落库(可选):
cd /opt/inboxen/app
/opt/inboxen/env/bin/python -c "import django,os;os.environ.setdefault('DJANGO_SETTINGS_MODULE','inboxen.settings');django.setup();from inboxen.models import Email;print('EMAIL-TOTAL:', Email.objects.count())"
实测回显:
EMAIL-TOTAL: 3
至此「SMTP 投递 → Inboxen 收信 → Web 可见」闭环全部打通。
十二、常见排障
| 现象 | 根因 | 处置 |
|---|---|---|
pip 报 ERROR: Failed building wheel for psycopg2 | 缺 pg_config | apt install libpq-dev 后重跑 pip |
首次执行 inboxen 命令报 No module named 'distutils' | Python 3.12 无 distutils,依赖链需 setuptools 兼容层 | pip install setuptools |
celery 秒退、日志 0 字节,status 报 'NoneType' object has no attribute 'Redis' | 用 Redis broker 但未装 redis 传输包 | pip install redis |
| 纯 HTTP 访问 301 跳 https | 生产模式内置 SECURE_SSL_REDIRECT=True | 实验环境 config 里 debug: true;生产上 TLS |
| telnet 投信后队列空、无日志、Web 无信 | DATA 未以单独 . 行结束即断开,Postfix 丢弃会话 | 按响应节奏发送,等 250 ... queued as ... 再 QUIT |
| Postfix 日志无处可寻 | Debian 12 默认无 rsyslog | postconf -e "maillog_file=/var/log/mail.log" 后 reload |
外部投递报 Relay access denied | 域未登记为本机收信域 | postconf -e "relay_domains=inboxen.lan" |
| Postfix 转 Salmon 连接失败 | Salmon 只听 [::1] | transport 目标写 smtp:[::1]:8823 |
缓存告警 caches.W003 | FileBasedCache 相对路径 | cache.location 改绝对路径 |
十三、卸载
# 停进程
pkill -f 'celery -A inboxen'
/opt/inboxen/env/bin/salmon stop --pid /opt/inboxen/app/run/router.pid
pkill -f gunicorn
# 撤 Nginx 站点并恢复默认
rm -f /etc/nginx/sites-enabled/default && systemctl reload nginx
# 撤 Postfix 对接
postconf -X transport_maps -X relay_domains; systemctl reload postfix
# 删库删用户
su postgres -c "dropdb inboxen && dropuser inboxen"
# 删应用目录与 Python
rm -rf /opt/inboxen /usr/local/python3.12 /usr/local/src/Python-3.12.12*
十四、参考链接
- 官方 Getting Started(
make salmon-start等原始流程):https://inboxen.readthedocs.io/en/latest/getting_started.html(2026-10-26 查询) - 官方配置文档:
https://inboxen.readthedocs.io/en/latest/settings.html(2026-10-26 查询) - 官方代码仓:
https://codeberg.org/Inboxen/Inboxen(2026-10-26 查询) - 站内关联:《Inboxen 2026.2.22.0.27.49 介绍与选型指南》