Spug v4.1.1 配置参数详解

Spug v4.1.1 配置体系全解析:部署环境变量、首启生成的 overrides.py、settings.py 常量(Redis 键/目录/鉴权豁免)与 nginx/Redis/进程管理组件配置,逐项实测值与调优建议。

SpugSpug自动化运维自托管2026/10/25

Spug v4.1.1 配置参数详解

目标:把 Spug v4.1.1 的配置体系讲透——部署期环境变量、首启自动生成的运行时覆盖配置、镜像内置常量、以及 nginx/Redis/进程管理三类组件配置,逐项给出实测值、生效机制与调优建议。本文所有配置原文均于 2026-10-25 从一台按 《Spug v4.1.1 Docker Compose 部署指南》 部署并正常运行 v4.1.1 的服务器上实查(直接读取配置文件原文),文中行号与取值逐字照抄。

一、环境信息

项目实测值
部署形态官方 Compose 编排:Spug 应用 + MariaDB 10.11(宿主端口 8128→80)
Spug 版本v4.1.1(镜像内源码目录 /data/spug,程序目录 /data/spug/spug_api)
后端Python 3.11.17 / Django 4.2 / gunicorn(9001) / daphne(9002) / Redis 7.0.15 / nginx 1.22.1
实测方式读取容器内配置文件原文(settings.py、overrides.py、/etc/nginx/nginx.conf、/etc/redis.conf、/etc/supervisord.conf、/entrypoint.sh)并实测生效行为
实测日期2026-10-25

二、参数概览:四层配置载体与优先级

Spug 的配置分散在四层载体上,理解「谁覆盖谁」是改配置的第一步:

层载体生成/修改方式生效时机是否跨升级保留
① 部署环境变量编排文件 environment(MYSQL_、TZ、SPUG_ADMIN_ 等)部署前改编排每次启动重新读取随编排保留
② 运行时覆盖配置/data/spug/spug_api/spug/overrides.py首次启动由启动脚本自动生成;文件头注释明确「可在此追加自己的配置」每次进程启动导入保留(落盘在数据卷)
③ 镜像内置常量/data/spug/spug_api/spug/settings.py随镜像发布,一般不改首次安装 rsync 到数据卷后生效升级版本时随源码更新
④ 组件与应用内配置nginx(/etc/nginx/nginx.conf)、Redis(/etc/redis.conf)、进程管理(/etc/supervisord.conf)、数据库内「系统设置」直接改文件或 Web 后台supervisorctl restart 对应进程①②保留;组件文件升级时以镜像内模板为准

优先级关系:settings.py 末尾以 from spug.overrides import * 方式导入覆盖层(源码原文 # override default config),因此 ② overrides.py 的同名项覆盖 ③ settings.py,环境变量又是 overrides.py 的取值来源——最终决定权排序为:环境变量 → overrides.py → settings.py 内置值。

三、部署环境变量详解(编排级)

以下变量由启动脚本 /entrypoint.sh 实测读取(逐字摘录关键判断逻辑,行号 96~129):

if [ -n "${MYSQL_HOST:-}" ]; then
    log "waiting for the database at $MYSQL_HOST:${MYSQL_PORT:-3306}"
    ……
    deadline = time.time() + int(os.environ.get('SPUG_DB_WAIT', '180'))
    ……
            host=os.environ['MYSQL_HOST'], port=int(os.environ.get('MYSQL_PORT') or 3306),
            user=os.environ.get('MYSQL_USER', 'spug'), passwd=os.environ.get('MYSQL_PASSWORD', ''),
            db=os.environ.get('MYSQL_DATABASE', 'spug'), connect_timeout=5,
    ……
    log "MYSQL_HOST is not set, using SQLite at $API/db.sqlite3 (fine for a trial, use MySQL/MariaDB for real use)"
    ……
    admin_user=${SPUG_ADMIN_USER:-admin}
    admin_password=${SPUG_ADMIN_PASSWORD:-}
变量默认值作用与实测行为
MYSQL_HOST未设置总开关:设置后启用 MySQL/MariaDB 引擎并在启动前等待数据库可达;未设置则退化为 SQLite(实测日志原文:MYSQL_HOST is not set, using SQLite at $API/db.sqlite3 (fine for a trial, use MySQL/MariaDB for real use)),官方定位仅供试用
MYSQL_PORT3306数据库端口
MYSQL_DATABASEspug库名,须与 db 服务的 MARIADB_DATABASE 一致(首启自动建库)
MYSQL_USERspug业务账号,须与 MARIADB_USER 一致
MYSQL_PASSWORD空业务密码,须与 MARIADB_PASSWORD 一致
SPUG_DB_WAIT180(秒)等待数据库就绪的超时上限,超时后启动脚本退出并提示检查 MYSQL_* 配置
TZUTC时区;必须是合法 zoneinfo 名(脚本校验 /usr/share/zoneinfo/ 下存在才生效),决定任务计划执行时刻、监控时间戳与数据库会话时区
SPUG_ADMIN_USERadmin首启创建的管理员用户名
SPUG_ADMIN_PASSWORD未设置首启管理员密码;设置则用该值创建(日志:created the admin account '$admin_user' with SPUG_ADMIN_PASSWORD),未设置则随机生成并打印在日志
SPUG_DB_PASSWORD(compose 模板变量)spug.cc官方编排用它同时注入 MYSQL_PASSWORD 与 MARIADB_PASSWORD,两侧必须同值

⚠️ 三个易错点(实测确认):① MYSQL_* 与 MARIADB_* 是两套变量,改一侧必翻车;② TZ 写错时区名不会报错,而是静默回落 UTC;③ SPUG_ADMIN_PASSWORD 只在「首次创建管理员」时有效,数据卷已初始化后改它不会更新已有账号密码(改密码见 CLI 篇 user reset)。

四、运行时配置详解(settings.py 与 overrides.py)

4.1 overrides.py:首启自动生成的覆盖层(实测全文)

首次启动后生成于 /data/spug/spug_api/spug/overrides.py,实测全文如下(逐字照抄,SECRET_KEY 为本机实测值,每台不同):

# Generated by the Docker image on first start and kept across upgrades; add your own
# settings here. Database and time zone come from the container environment.
import os

DEBUG = False
ALLOWED_HOSTS = ['127.0.0.1']
SECRET_KEY = '_iOcJxJgTzposLg_bscr6fRZbHlCFTj1SMAVbURve7EZ9ATqe9l7vPIFSQDscE5yZ6k'

_tz = os.environ.get('TZ', '')
if _tz and not _tz.startswith('/') and os.path.isfile('/usr/share/zoneinfo/' + _tz):
    TIME_ZONE = _tz

if os.environ.get('MYSQL_HOST'):
    DATABASES = {
        'default': {
            'ATOMIC_REQUESTS': True,
            'ENGINE': 'django.db.backends.mysql',
            'NAME': os.environ.get('MYSQL_DATABASE', 'spug'),
            'USER': os.environ.get('MYSQL_USER', 'spug'),
            'PASSWORD': os.environ.get('MYSQL_PASSWORD', ''),
            'HOST': os.environ['MYSQL_HOST'],
            'PORT': os.environ.get('MYSQL_PORT', '3306'),
            'OPTIONS': {
                'charset': 'utf8mb4',
                'sql_mode': 'STRICT_TRANS_TABLES',
            }
        }
    }

逐项注解:

配置项实测值说明
DEBUGFalse生产安全缺省;排障时可临时改 True 后重启 spug-api 进程
ALLOWED_HOSTS['127.0.0.1']仅允许 127.0.0.1 作为 Host。外部域名为何能正常访问:编排内 nginx 以 proxy_pass http://127.0.0.1:9001 转发且未设置 Host 头,Django 收到的 Host 恒为 127.0.0.1,校验天然通过;若自建外层反代直连 9001,需把对外域名追加进该列表
SECRET_KEY随机 64 位字符串(首启生成)会话与凭据加密根基;换库/迁移部署时不要重新生成,否则已保存的凭据将无法解密
TIME_ZONE取 TZ,实测 Asia/Shanghai仅当 TZ 是合法 zoneinfo 名才写入
DATABASESMySQL 引擎,ATOMIC_REQUESTS: True(每个请求包在一个事务里)、charset: utf8mb4、sql_mode: STRICT_TRANS_TABLES与 db 服务编排参数一一对应;ATOMIC_REQUESTS 意味着批量接口出错即整体回滚

4.2 settings.py 内置常量详解(实测摘录,行号 74~142)

缓存与消息通道(Redis 是批量执行/发布/流水线控制台输出与 WebSocket 消息的载体,源码注释原文:the deploy/build/pipeline consoles use get_redis_connection() to stream their output through redis lists):

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}

CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/1",
        "KEY_PREFIX": "spug",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    }
}

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": [("127.0.0.1", 6379)],
            "prefix": "spug:channel",
            "capacity": 1000,
            "expiry": 120,
        },
    },
}

内置 DATABASES 是 SQLite(db.sqlite3),仅作为未设 MYSQL_HOST 时的兜底;编排形态下被 overrides.py 的 MySQL 配置覆盖。

配置项实测值说明
CACHES.default.LOCATIONredis://127.0.0.1:6379/11 号库做缓存;Redis 为服务内进程,仅监听本机回环
CACHES.default.KEY_PREFIXspug所有缓存键前缀
CHANNEL_LAYERS.prefixspug:channelWebSocket 通道层键前缀
CHANNEL_LAYERS.capacity1000单通道消息容量,超容量丢最旧消息;大量并发在线终端时可调大
CHANNEL_LAYERS.expiry120(秒)消息过期时间
TOKEN_TTL8 * 3600(8 小时)登录 access_token 有效期,过期需重新登录

任务/队列键名(worker、scheduler、monitor 之间通过这些 Redis 键协作,排查卡任务时可 redis-cli 直接观察):

键实测值
SCHEDULE_KEY / SCHEDULE_WORKER_KEYspug:schedule / spug:schedule:worker
MONITOR_KEY / MONITOR_WORKER_KEYspug:monitor / spug:monitor:worker
EXEC_WORKER_KEY / EXEC_RESULT_KEYspug:exec:worker / spug:exec:result
REQUEST_KEYspug:request
BUILD_KEYspug:build
PIPELINE_KEYspug:pipeline

目录常量(决定发布产物与传输文件落盘位置,均在数据卷内):

配置项实测值说明
TRANSFER_DIR<BASE_DIR>/storage/transfer批量执行的文件分发暂存
DEPLOY_DIR<BASE_DIR>/storage/deploy应用发布产物
REPOS_DIR<BASE_DIR 上两级>/repos源码树之外(实测即 /data/repos),源码注释:kept outside of the source tree, the docker image mounts it as /data/repos
BUILD_DIR<REPOS_DIR>/build构建工作目录

国际化与鉴权豁免:

配置项实测值说明
LANGUAGE_CODEen-usv4 起界面语言由前端切换(中/英双语),后端基准 en
TIME_ZONEAsia/Shanghai(settings 默认值)实际被 overrides 按 TZ 覆盖
USE_TZFalse时间以本地时区落库
AUTHENTICATION_EXCLUDES/account/login/、/setting/basic/、正则 /apis/.*登录页、系统基本设置、开放 API 三类路径免登录鉴权(开放 API 用独立凭据)
SPUG_VERSIONv4.1.1版本标识,升级时启动脚本对比新旧值决定是否重装源码
中间件链TranslateMiddleware → AuthenticationMiddleware → HandleExceptionMiddleware → XFrameOptionsMiddleware认证在异常处理之前,未带 token 的请求直接 401

4.3 组件配置详解

nginx(/etc/nginx/nginx.conf 内置 server 块,实测摘录):前端为构建产物(root /data/spug/spug_web/build),单页应用回退 try_files $uri /index.html:

server {
    listen       80 default_server;
    listen       [::]:80 default_server;
    server_name  _;
    root         /data/spug/spug_web/build;
    client_max_body_size   0;
    add_header   X-Frame-Options SAMEORIGIN always;

    gzip  on;
    gzip_min_length  1k;
    gzip_buffers     4 16k;
    gzip_http_version 1.1;
    gzip_comp_level  7;
    gzip_types       text/plain text/css text/javascript application/javascript application/json;
    gzip_disable "MSIE [1-6]\.";
    gzip_vary on;

    location ^~ /api/ {
            rewrite ^/api(.*) $1 break;
            proxy_pass http://127.0.0.1:9001;
            proxy_read_timeout 180s;
            proxy_redirect off;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    location ^~ /api/ws/ {
            rewrite ^/api(.*) $1 break;
            proxy_pass http://127.0.0.1:9002;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "Upgrade";
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    location / {
            try_files $uri /index.html;
    }
}

要点:client_max_body_size 0 即不限制上传体积(大文件分发不受 nginx 限制);/api/ 转发会剥掉 /api 前缀再交给后端;proxy_read_timeout 180s 限定普通 API 的等待上限;/api/ws/ 是 WebSocket 专用升级转发(在线终端与控制台实时输出走这条链路)。

Redis(/etc/redis.conf 实测关键项):

配置项实测值说明
bind / port127.0.0.1 / 6379仅本机可连,不对外暴露
maxmemory / maxmemory-policy2GB / allkeys-lru内存上限 2GB,满后 LRU 淘汰;小规格主机建议下调
save900 1、300 10、60 10000RDB 快照策略(缓存与队列用途,无需 AOF)
appendonlyno未开启 AOF

进程管理(/etc/supervisord.conf 实测 7 个受管程序):

程序名启动命令(tools/start-*.sh 实测)端口
nginxnginx -g "daemon off;"80
redisredis-server /etc/redis.conf6379
spug-apigunicorn -b 127.0.0.1:9001 -w 2 --threads 8 --access-logfile - spug.wsgi9001
spug-wsdaphne -p 9002 spug.asgi:application9002
spug-workerpython3 manage.py runworker-
spug-monitorpython3 manage.py runmonitor-
spug-schedulerpython3 manage.py runscheduler-

五、调优建议(基于实测参数)

  1. API 并发:start-api.sh 中 gunicorn 固定 -w 2 --threads 8(16 并发),中小团队够用;调大后记得 supervisorctl restart spug-api。该脚本在数据卷内(/data/spug),改动会跨重启保留,但跨版本升级会随源码更新被覆盖,升级后需复核。
  2. 在线终端/控制台并发:CHANNEL_LAYERS.capacity(1000)与 Redis maxmemory(2GB)是两个相关上限;终端较多的团队优先保证 Redis 内存,控制台输出全部经 Redis 列表流转。
  3. Token 时效:登录态 8 小时(TOKEN_TTL),高频自动化对接建议改走开放 API 凭据而非长期会话 token。
  4. 大文件:nginx 已不限上传体积;若在 Spug 之外自建了一层反代,记得同步放开其 client_max_body_size,否则文件分发/上传会在外层被 413 拦截。
  5. 时区:任务计划按时区触发(TZ),改编排环境变量后需整体重启编排生效;用错误时区名会静默回落 UTC,务必用 Asia/Shanghai 这类标准名。
  6. 数据库事务:ATOMIC_REQUESTS: True 已把每个请求包进事务,无需也不能再在业务代码层重复包事务;STRICT_TRANS_TABLES 使非法数据直接报错而非静默截断。

六、常见问题

Q1:改了 settings.py / overrides.py 不生效? A:Python 进程只读一次配置。supervisorctl restart spug-api spug-ws spug-worker spug-monitor spug-scheduler,或整体 docker compose restart spug。

Q2:overrides.py 会不会被升级覆盖? A:不会。该文件由首启生成并落在数据卷,文件头注释原文明确 kept across upgrades;升级只更新镜像内源码模板。自定义配置写在这里是官方预期姿势。

Q3:外层自建反代直连 9001 报 DisallowedHost? A:overrides.py 的 ALLOWED_HOSTS = ['127.0.0.1'],编排内 nginx 转发时 Host 恒为 127.0.0.1 所以不受影响;自建反代直连时把域名追加进该列表并重启 spug-api。

Q4:能从 SQLite 切到 MySQL 吗? A:引擎由 MYSQL_HOST 环境变量决定(有则 MySQL,无则 SQLite),但官方没有内建的 SQLite→MySQL 数据迁移命令;正式使用请在首次部署就配好数据库,避免事后再迁。

Q5:任务计划的时间不对? A:三查:TZ 是否合法 zoneinfo 名、是否写进了编排 environment(不是只改系统时区)、改动后是否重启了编排。任务计划与时区的关系是 v4.1.0 起的明确行为。

七、总结与参考链接

Spug v4.1.1 的配置体系是「环境变量驱动 + 单文件覆盖」的简洁设计:部署期只调 MYSQL_*/TZ/SPUG_ADMIN_* 几个变量,运行期定制集中在 overrides.py,Redis 键名与目录常量透明可查。掌握 4.1/4.2 两张参数表即可覆盖绝大多数调优与排障场景。账号、升级与服务进程的命令行操作见 《Spug v4.1.1 常用 CLI 命令详解》。

参考链接: