VoucherVault 1.30.3 配置参数详解
逐项详解 VoucherVault v1.30.3 全部 31 个环境变量:默认值、取值规则、Django 源码机制与实测行为,附个人/生产两套推荐配置基线与排障实录。
VoucherVault 1.30.3 配置参数详解
目标:逐项讲清 VoucherVault v1.30.3 的全部环境变量(官方 README 列出的 30 项 + 源码中隐含的 1 个 OIDC 密钥项),包括默认值、取值规则、背后的 Django 机制与实测行为。安装步骤见《Ubuntu 22.04 安装 VoucherVault 指南》与《VoucherVault Docker Compose 部署指南》。
一、配置加载机制
VoucherVault 是标准 Django 应用,配置只通过环境变量注入,加载路径有两条(myproject/settings.py 与 myproject/wsgi.py):
from dotenv import load_dotenv
load_dotenv() # settings.py:从当前工作目录找 .env
load_dotenv(os.path.join(project_folder, '.env')) # wsgi.py:从项目根目录找 .env
要点:
- 部署形态决定注入方式:Compose 形态用
environment:列表直接注入;裸机形态在项目根(manage.py同级目录)放.env文件; - 修改任何变量后必须重启应用进程(uWSGI/Celery),Django 不会热加载;
- 所有布尔型变量的判定逻辑是
os.environ.get('X','False').lower() in ['true'],即只有字面量True/true生效,写1、yes一律视为 False; manage.py命令(migrate、shell 等)同样会读.env,保证 CLI 与 Web 进程配置一致。
二、变量总览表
按功能分组,默认值与必选性取自官方 README(查询日期 2026-10-25)与 settings.py 源码核对:
| 分组 | 变量 | 默认值 | 必选 |
|---|---|---|---|
| 网络/安全 | DOMAIN | localhost | ✅ 必选 |
| 网络/安全 | PORT | 8000 | 可选 |
| 网络/安全 | SECURE_COOKIES | False | 可选 |
| 网络/安全 | SECRET_KEY | 每次启动自动生成 | 可选(生产强烈建议设置) |
| 网络/安全 | DEBUG | False | 可选 |
| 网络/安全 | CSP_FRAME_ANCESTORS | 'none' | 可选 |
| 会话 | SESSION_COOKIE_AGE | 30(分钟) | 可选 |
| 会话 | SESSION_EXPIRE_AT_BROWSER_CLOSE | True | 可选 |
| 通知 | EXPIRY_THRESHOLD_DAYS | 30 | 可选 |
| 通知 | EXPIRY_LAST_NOTIFICATION_DAYS | 7 | 可选 |
| 时区 | TZ | Europe/Berlin | 可选 |
| 数据库 | DB_ENGINE | sqlite3 | 可选 |
| 数据库 | POSTGRES_HOST | db | 可选 |
| 数据库 | POSTGRES_PORT | 5432 | 可选 |
| 数据库 | POSTGRES_USER | vouchervault | 可选 |
| 数据库 | POSTGRES_PASSWORD | vouchervault | 可选 |
| 数据库 | POSTGRES_DB | vouchervault | 可选 |
| 队列 | REDIS_URL | redis://redis:6379/0 | 可选 |
| 队列 | CELERY_WORKER_CONCURRENCY | 1 | 可选 |
| 队列 | CELERY_WORKER_PREFETCH_MULTIPLIER | 1 | 可选 |
| OIDC | OIDC_ENABLED | False | 可选 |
| OIDC | OIDC_AUTOLOGIN | False | 可选 |
| OIDC | OIDC_CREATE_USER | True | 可选 |
| OIDC | OIDC_RP_SIGN_ALGO | HS256 | 可选 |
| OIDC | OIDC_RP_CLIENT_ID | vouchervault(settings 中默认) | 可选 |
| OIDC | OIDC_RP_CLIENT_SECRET | 无 | 可选 |
| OIDC | OIDC_OP_JWKS_ENDPOINT | 无 | RS256 时必选 |
| OIDC | OIDC_OP_AUTHORIZATION_ENDPOINT | 无 | OIDC 时必选 |
| OIDC | OIDC_OP_TOKEN_ENDPOINT | 无 | OIDC 时必选 |
| OIDC | OIDC_OP_USER_ENDPOINT | 无 | OIDC 时必选 |
| OIDC | OIDC_RP_IDP_SIGN_KEY(仅源码) | 无 | HS256 时可用 |
三、网络与安全组
3.1 DOMAIN(必选)
决定 Django 的 ALLOWED_HOSTS 与 CSRF_TRUSTED_ORIGINS。源码逻辑(settings.py 第 42-56 行):
DOMAIN = str(os.environ.get("DOMAIN", "localhost"))
TRUSTED_PORT = str(os.environ.get("PORT", "8000"))
# 对每个域名生成 4 条信任源:
# http://<domain>:<PORT> http://<domain> https://<domain>:<PORT> https://<domain>
- 支持逗号分隔多个域名/IP,如
DOMAIN=vouchervault.example.com,192.168.1.10; - 实测佐证:域名不匹配时,登录表单 POST 会被 CSRF 中间件拒绝,返回 403「CSRF verification failed」(见 B1 篇排障实录第 1 条);
- 写域名时不要带
http://前缀与尾部斜杠,源码会先剥离这两个成分再拼装。
3.2 PORT
仅在访问端口不是 8000/80/443 时需要设置,用于拼 CSRF_TRUSTED_ORIGINS。例如 Compose 把宿主机 8130 映射到容器 8000,就应设 PORT=8130 并配合 DOMAIN=127.0.0.1,否则表单 POST 403。
3.3 SECURE_COOKIES
True 时同时开启三件事(settings.py 第 66-73 行):
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_HSTS_SECONDS = "31536000"
SECURE_HSTS_PRELOAD = True
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
- 仅在反向代理已上 HTTPS 后开启;纯 HTTP 环境开了会导致浏览器拒发 Cookie、直接无法登录;
- HSTS 一年期且含 preload、子域,一旦开启回退 HTTP 很麻烦,确认 TLS 稳定后再开。
3.4 SECRET_KEY
Django 签名密钥。不设置时每次进程启动都随机生成(secrets.token_urlsafe(32)),副作用是重启即踢掉所有已登录会话、既有签名链接全部失效。生产环境务必生成固定值写入配置:
python3 -c "import secrets; print(secrets.token_urlsafe(32))"
3.5 DEBUG
True 开启 Django 调试模式:错误页显示堆栈与配置细节(实测中曾用它定位 CSRF 失败原因,错误页会给出 Reason given for failure)。仅限排障时临时开启,用完立即改回 False 并重启。
3.6 CSP_FRAME_ANCESTORS
控制 CSP frame-ancestors 响应头(即本站允许被哪些页面 iframe 嵌入)。默认 'none' 完全禁止嵌入。如需嵌入内部门户,设为逗号分隔的来源列表,例如:
CSP_FRAME_ANCESTORS="'self',https://portal.example.com"
注意每项需自带单引号或完整 URL,源码只做逗号切分与去空格,不做格式校验。
四、会话组
| 变量 | 机制 |
|---|---|
SESSION_COOKIE_AGE | 会话最大分钟数,源码中 int(...) * 60 转成秒,默认 30 分钟 |
SESSION_EXPIRE_AT_BROWSER_CLOSE | 默认 True:关闭浏览器即失效;想在 SESSION_COOKIE_AGE 周期内保持登录,显式设 False |
会话 Cookie 名固定为 VVSESS,SameSite=Lax(均硬编码,无对应变量)。两个变量组合建议:个人使用 SESSION_COOKIE_AGE=1440 + SESSION_EXPIRE_AT_BROWSER_CLOSE=False(一天免登);共享终端保持默认。
五、通知组
到期提醒由 Celery Beat 每天触发 check_expiration 任务(源码 myapp/management/commands/check_expiration.py):
threshold_days = os.getenv('EXPIRY_THRESHOLD_DAYS', 30)
last_chance_threshold_days = os.getenv('EXPIRY_LAST_NOTIFICATION_DAYS', 7)
EXPIRY_THRESHOLD_DAYS:到期前 N 天发送首次提醒;EXPIRY_LAST_NOTIFICATION_DAYS:到期前 N 天发送最后一次提醒;- 两者必须是整数字符串,非整数会让任务直接报错退出(源码有显式校验与报错输出);
- 提醒投递渠道在 Web 界面的用户设置里按用户配置 Apprise URL,不在环境变量层;这两个变量只控制时机。
六、时区 TZ
设置 Django TIME_ZONE,影响页面时间显示与日期比较。建议国内部署设 TZ=Asia/Shanghai。
⚠️ 实测发现的一个坑:settings.py 中 CELERY_TIMEZONE = 'Europe/Berlin' 是硬编码,不跟随 TZ。默认周期任务按柏林时间每天 09:00 触发,即北京时间 15:00/16:00(视夏令时)。如需调整触发时间,到 Django 管理后台 /en/admin/django_celery_beat/periodictask/ 直接修改周期任务的 crontab。
七、数据库组
DB_ENGINE = os.environ.get("DB_ENGINE", "sqlite3")
- 缺省
sqlite3:数据文件<项目根>/database/db.sqlite3,零依赖,个人/家庭够用; - 设
postgres时启用以下五个变量:POSTGRES_HOST(默认db)、POSTGRES_PORT(默认5432)、POSTGRES_USER/POSTGRES_PASSWORD/POSTGRES_DB(默认均为vouchervault); POSTGRES_PASSWORD属敏感信息,Compose 形态建议改用.env文件配合${VAR}引用,不要写进版本库;- 切换引擎后需要重新跑
manage.py migrate建表,原 SQLite 数据不会自动迁移(需自行用dumpdata/loaddata搬迁)。
八、队列组
REDIS_URL = os.environ.get('REDIS_URL')
if REDIS_URL == None:
CELERY_BROKER_URL = 'redis://redis:6379/0'
else:
CELERY_BROKER_URL = REDIS_URL
REDIS_URL同时用作 Celery broker 与 result backend;Compose 形态默认值redis://redis:6379/0里的主机名就是 Redis 服务名,无需改动;裸机形态必须显式设为redis://127.0.0.1:6379/0;CELERY_WORKER_CONCURRENCY:worker 并发进程数,默认 1。本应用任务量极小(每天一次扫描),默认即可;CELERY_WORKER_PREFETCH_MULTIPLIER:预取倍数,默认 1,保持默认。
九、OIDC 组(企业单点登录)
开启 OIDC_ENABLED=True 后,登录走外部 IdP(Authentik/Keycloak/Authelia 等),基于 mozilla-django-oidc 实现:
| 变量 | 说明 |
|---|---|
OIDC_AUTOLOGIN | True 时访问登录页自动跳转 IdP,不再展示本地登录表单 |
OIDC_CREATE_USER | 默认 True:IdP 首次登录自动建本地账号 |
OIDC_RP_SIGN_ALGO | RS256(推荐,公钥验签)或 HS256(共享密钥) |
OIDC_OP_JWKS_ENDPOINT | RS256 必选,IdP 的 JWKS 地址 |
OIDC_RP_IDP_SIGN_KEY | HS256 时的 IdP 签名密钥(README 未列,仅见于 settings.py) |
OIDC_RP_CLIENT_ID / OIDC_RP_CLIENT_SECRET | IdP 侧注册的客户端凭据 |
OIDC_OP_AUTHORIZATION_ENDPOINT / OIDC_OP_TOKEN_ENDPOINT / OIDC_OP_USER_ENDPOINT | IdP 三个标准端点 URL |
开启 OIDC 后 URL 路由会追加 /oidc/ 前缀端点(settings.py 条件挂载 mozilla_django_oidc.urls),IdP 的回调地址填 https://<你的域名>/oidc/callback/。本地账号密码登录仍然保留(/en/accounts/login/),便于 IdP 故障时兜底。
十、推荐配置基线
个人/家庭(SQLite,直接 HTTP):
DOMAIN=192.168.1.10
PORT=8130
SECRET_KEY=<固定随机串>
TZ=Asia/Shanghai
SESSION_COOKIE_AGE=1440
SESSION_EXPIRE_AT_BROWSER_CLOSE=False
EXPIRY_THRESHOLD_DAYS=30
EXPIRY_LAST_NOTIFICATION_DAYS=7
REDIS_URL=redis://127.0.0.1:6379/0
生产(HTTPS 反代 + PostgreSQL):
DOMAIN=vouchervault.example.com
SECURE_COOKIES=True
SECRET_KEY=<固定随机串>
TZ=Asia/Shanghai
DB_ENGINE=postgres
POSTGRES_HOST=127.0.0.1
POSTGRES_PORT=5432
POSTGRES_USER=vouchervault
POSTGRES_PASSWORD=<强口令>
POSTGRES_DB=vouchervault
REDIS_URL=redis://127.0.0.1:6379/0
CSP_FRAME_ANCESTORS='none'
十一、排障实录
1. 布尔变量写了 1 不生效
判定逻辑只认 true(大小写不敏感)。SECURE_COOKIES=1 等价于 False,一律写 True/False。
2. 每次重启后所有用户被踢出登录
SECRET_KEY 未固定,每次启动随机重生成。设置固定 SECRET_KEY 后重启不再丢会话。
3. 到期提醒在北京时间下午才触发
CELERY_TIMEZONE 硬编码 Europe/Berlin,与 TZ 无关。到 Django 后台调整 Periodic tasks 的 crontab 时区/时刻。
4. 改完 .env 没效果
环境变量只在进程启动时读取。裸机形态重启 uWSGI 与两个 Celery 进程;Compose 形态 docker compose up -d --force-recreate app。
5. RS256 模式 OIDC 登录报验签失败
缺 OIDC_OP_JWKS_ENDPOINT 或 IdP 侧 JWKS 地址不可达。该变量在 RS256 模式下是必选,README 表格「Optional」列标注的 Optional 仅对 HS256 成立。
十二、参考链接
- 官方 README 环境变量表:https://github.com/l4rm4nd/VoucherVault#environment-variables (查询日期 2026-10-25)
- 官方 Wiki - 认证/OIDC:https://github.com/l4rm4nd/VoucherVault/wiki/02-%E2%80%90-Authentication (查询日期 2026-10-25)
- 官方 Wiki - 通知配置:https://github.com/l4rm4nd/VoucherVault/wiki/03-%E2%80%90-Notifications (查询日期 2026-10-25)
- 站内:《VoucherVault 介绍与选型指南》
- 站内:《Ubuntu 22.04 安装 VoucherVault 指南》
- 站内:《VoucherVault Docker Compose 部署指南》
- 站内:《VoucherVault API 使用详解》(本专栏)