OpenWISP 1.3.2 配置参数详解

OpenWISP 1.3.2 settings.py 关键参数详解:数据库与 PostGIS、缓存会话与 Channels、Celery、OPENWISP_* 应用开关、时区语言、邮件与 RADIUS、静态媒体目录与生产加固模板。

OpenWISPOpenWISP网络管理Django2026/10/28

OpenWISP 1.3.2 配置参数详解

目标:把 OpenWISP Controller(1.3.2)的 settings.py 讲清楚——哪些参数决定数据库、缓存、队列、时区、语言、邮件、静态目录与 OPENWISP_* 应用行为,每项给出真实生效值与修改后的验证方法。文中生效值在 /opt/openwisp/app/openwisp2/settings.py 实例上实测,安装步骤见 《OpenWISP 1.3.2 Ubuntu 22.04 安装指南》。

一、环境信息

  • 操作系统:Ubuntu 22.04.5 LTS
  • 应用版本:openwisp-controller 1.3.2、Django 5.2.18
  • 数据库:PostgreSQL 14.24 + PostGIS 3.2.0(django.contrib.gis.db.backends.postgis)
  • 缓存与队列:Redis 6.0.16(本机 6379)
  • 应用服务器:uWSGI 2.0.20 + Nginx 1.18.0
  • 项目路径:/opt/openwisp/app,配置文件 /opt/openwisp/app/openwisp2/settings.py
  • 运行用户:www-data
  • 站点域名:openwisp.example.com
  • 采集日期:2026-10-28

💡 说明:本文只讨论“改配置”,不重复安装过程。所有 manage.py 命令都在 /opt/openwisp/app 目录、以 www-data 身份执行,虚拟环境为 /opt/openwisp/venv。

二、前置条件

修改配置前需要确认三件事,否则改完无法验证:

  1. 服务可重启:三个 systemd 单元 uwsgi-openwisp、celery-openwisp、celery-beat-openwisp 处于 active。
  2. 数据库可连接:psql -h 127.0.0.1 -U openwisp -d openwisp -c 'select 1' 能返回结果。
  3. Redis 可用:redis-cli ping 返回 PONG。

检查命令与实测回显:

systemctl is-active uwsgi-openwisp celery-openwisp celery-beat-openwisp
redis-cli ping
PGPASSWORD=q1w2e3r4 psql -h 127.0.0.1 -U openwisp -d openwisp -tAc "select current_database()"

实测回显:

active
active
active
PONG
openwisp

⚠️ 注意:配置改动后必须同时重启 uWSGI 与两个 Celery 单元。只重启 uWSGI 会导致 Web 端读到新配置、后台任务仍用旧配置(例如缓存库、队列地址不一致)。

三、参数查看与修改方式

OpenWISP 的所有配置都是 Django settings,没有独立的配置文件格式。查看与修改有三条路径:

路径一:直接编辑 settings.py(最常用)

sudo -u www-data vi /opt/openwisp/app/openwisp2/settings.py

路径二:diffsettings 查看“非默认项”

该命令只列出与 Django 默认值不同的配置,适合快速确认自己改了什么:

cd /opt/openwisp/app
sudo -u www-data /opt/openwisp/venv/bin/python manage.py diffsettings | head -20

实测输出节选:

ACCOUNT_ADAPTER = 'openwisp_users.accounts.adapter.EmailAdapter'  ###
ACCOUNT_LOGOUT_REDIRECT_URL = 'admin:index'  ###
ALLOWED_HOSTS = ['openwisp.example.com', '127.0.0.1', 'localhost']
ASGI_APPLICATION = 'openwisp2.asgi.application'  ###
AUTH_USER_MODEL = 'openwisp_users.User'
BASE_DIR = '/opt/openwisp/app'  ###
CACHES = {'default': {'BACKEND': 'django.core.cache.backends.redis.RedisCache', 'LOCATION': 'redis://127.0.0.1:6379/6'}, ...}
CELERY_BROKER_URL = 'redis://127.0.0.1:6379/1'  ###
LANGUAGE_CODE = 'zh-hans'

带 ### 的行表示该值被项目显式覆盖(或由第三方包注入),不带标记的行是 Django 默认值。这个标记能帮你区分“我改的”和“框架自带的”。

路径三:运行时读取

sudo -u www-data /opt/openwisp/venv/bin/python manage.py shell -c "from django.conf import settings as s; print(s.TIME_ZONE, s.LANGUAGE_CODE, s.CACHES['default']['LOCATION'])"

实测回显:

Asia/Shanghai zh-hans redis://127.0.0.1:6379/6

修改后的生效检查顺序:改文件 → manage.py check → 重启三个服务 → 用 shell 或页面验证。check 只做静态检查,不会应用配置,因此不能替代重启。

四、参数总览

把关键参数按“作用域”分组,先给全景,再逐章展开:

分组参数本文实测值作用
基础DEBUGFalse关闭调试,生产必须
基础ALLOWED_HOSTS["openwisp.example.com","127.0.0.1","localhost"]限制可访问域名
基础SECRET_KEY50 字符随机串会话与签名密钥
数据库DATABASES.default.ENGINEdjango.contrib.gis.db.backends.postgis空间数据库后端
数据库DATABASES.default.CONN_MAX_AGE0(默认)连接复用秒数
缓存CACHES.default.LOCATIONredis://127.0.0.1:6379/6默认缓存库
缓存CACHES.sessions.LOCATIONredis://127.0.0.1:6379/8会话库
会话SESSION_ENGINEdjango.contrib.sessions.backends.cache会话存缓存
队列CELERY_BROKER_URLredis://127.0.0.1:6379/1任务队列
队列CELERY_RESULT_BACKENDredis://127.0.0.1:6379/2任务结果
队列CELERY_TASK_TIME_LIMIT600单任务硬超时(秒)
WebSocketCHANNEL_LAYERS.defaultchannels_redis,库 7通知推送
本地化TIME_ZONEAsia/Shanghai时区
本地化LANGUAGE_CODEzh-hans界面语言
本地化USE_TZ / USE_I18NTrue / True时区与国际化开关
静态STATIC_ROOT/opt/openwisp/app/staticcollectstatic 目标
媒体MEDIA_ROOT/opt/openwisp/app/media上传文件目录
邮件EMAIL_HOST / EMAIL_PORT127.0.0.1 / 25SMTP 服务
应用OPENWISP_ADMIN_DASHBOARD_ENABLEDTrue后台仪表盘
应用OPENWISP_CONTROLLER_GROUP_PIE_CHARTTrue设备分组饼图
应用OPENWISP_USERS_AUTH_APITrue用户认证 REST API
应用OPENWISP_NOTIFICATIONS_EMAIL_ENABLEDTrue邮件通知

读表要点:Redis 的 5 个库各有分工,不要随意合并。合并后会出现“清缓存把会话清掉”“任务结果覆盖缓存键”这类隐蔽故障。

五、数据库与 PostGIS 参数

数据库配置决定平台能否启动。OpenWISP 使用 GeoDjango 的空间字段(设备位置、地理围栏),因此 ENGINE 必须指向 PostGIS 后端。

DATABASES = {
    "default": {
        "ENGINE": "django.contrib.gis.db.backends.postgis",
        "NAME": "openwisp",
        "USER": "openwisp",
        "PASSWORD": "q1w2e3r4",
        "HOST": "127.0.0.1",
        "PORT": "5432",
    }
}

逐项说明:

  • ENGINE:写成 django.db.backends.postgresql 能在无空间字段时启动,但迁移 geo、openwisp_ipam 应用时会报 django.db.utils.ProgrammingError: type "geometry" does not exist。
  • NAME / USER / PASSWORD:数据库名与账号,实测为 openwisp / openwisp / q1w2e3r4。
  • HOST / PORT:数据库与应用同机时用 127.0.0.1,避免走 Unix Socket 时权限不一致。
  • CONN_MAX_AGE:默认 0(每次请求新建连接)。生产建议 60,减少连接开销;但需确认 PostgreSQL 的 max_connections 足够(uWSGI 4 worker × 2 线程 + Celery 2 进程)。

验证数据库与空间扩展:

cd /opt/openwisp/app
sudo -u www-data /opt/openwisp/venv/bin/python manage.py shell -c "
from django.db import connection
with connection.cursor() as c:
    c.execute('select postgis_version()'); print(c.fetchone()[0])
    c.execute(\"select count(*) from information_schema.tables where table_schema='public'\"); print(c.fetchone()[0])
"

实测回显:

3.2 USE_GEOS=1 USE_PROJ=1 USE_STATS=1
57

57 张表覆盖 17 个应用,表数量可作为“迁移是否完整”的快速判据;不同版本表数会有增减,以 showmigrations 全部 [X] 为准。

💡 技术拓展:Django 连接 PostgreSQL 有三种驱动组合——psycopg2(成熟、C 扩展)、psycopg 3(新驱动、支持异步)、psycopg[binary](免编译预编译包)。Django 5.2 同时支持前两者;本文选 psycopg[binary],原因是安装快、无需本机 pg_config,升级时只需替换 wheel。

六、缓存、会话与 Channels

OpenWISP 把 Redis 当成三套独立设施:Django 缓存、会话存储、Celery 队列,外加 Channels 的 WebSocket 通道层。四者用不同的库号隔离:

Redis 库用途配置项实测占用
1Celery 任务队列CELERY_BROKER_URL3 个键
2Celery 结果后端CELERY_RESULT_BACKEND2 个键(带过期)
6Django 默认缓存CACHES.default按业务写入
7Channels 通道层CHANNEL_LAYERS按通知推送写入
8会话CACHES.sessions + SESSION_ENGINE2 个键(登录后)

实测键分布:

redis-cli info keyspace

实测回显:

# Keyspace
db1:keys=3,expires=0,avg_ttl=0
db2:keys=2,expires=2,avg_ttl=85793874
db8:keys=2,expires=2,avg_ttl=1209113584

db8 的 2 个键来自实测登录(会话 + CSRF 相关),db1 的 3 个键来自 Celery worker/beat 心跳与任务投递,db2 的 2 个键带 TTL,符合“结果后端自动过期”的预期。

配置代码:

CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.redis.RedisCache",
        "LOCATION": f"{REDIS_URL}/6",
    },
    "sessions": {
        "BACKEND": "django.core.cache.backends.redis.RedisCache",
        "LOCATION": f"{REDIS_URL}/8",
    },
}

SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "sessions"

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {"hosts": [f"{REDIS_URL}/7"]},
    }
}

逐项说明:

  • SESSION_ENGINE 选 cache 后,会话不再落数据库,登录态完全依赖 Redis;Redis 重启会让所有用户掉线,这是可接受的取舍(可用 cached_db 折中)。
  • SESSION_CACHE_ALIAS 必须指向一个存在的缓存别名,写成 default 会让会话与业务缓存共享键空间。
  • CHANNEL_LAYERS 的 7 号库不能与缓存共用,否则 FLUSHDB 清缓存会同时清掉 WebSocket 通道。
  • openwisp-notifications 依赖 Channels 推送站内通知,缺 CHANNEL_LAYERS 时后台仍能用,但实时通知不工作。

验证缓存读写:

cd /opt/openwisp/app
sudo -u www-data /opt/openwisp/venv/bin/python manage.py shell -c "
from django.core.cache import caches
c = caches['default']; c.set('c1-probe','ok',30); print(c.get('c1-probe'))
"

实测回显:

ok

⚠️ 注意:如果 Redis 设了 maxmemory-policy allkeys-lru,会话键可能被业务缓存挤出。生产建议给会话单独实例,或在 redis.conf 里用 volatile-lru 并给会话键设置 TTL。

七、Celery 与异步任务

配置变更推送、通知分发、WHOIS 清理、VPN 密钥生成都在 Celery 里执行。相关配置分四类:

CELERY_BROKER_URL = f"{REDIS_URL}/1"
CELERY_RESULT_BACKEND = f"{REDIS_URL}/2"
CELERY_TASK_TIME_LIMIT = 600

CELERY_BEAT_SCHEDULE = {
    "cleanup_unreferenced_whois_records": {
        "task": "openwisp_controller.config.whois.tasks.cleanup_unreferenced_whois_records",
        "schedule": crontab(hour=2, minute=0),
    },
}
  • CELERY_BROKER_URL:任务投递地址。Redis 作 broker 时没有消息确认机制,任务可能因 worker 崩溃丢失;对配置推送这类可重试任务可接受,对计费类任务应换 RabbitMQ。
  • CELERY_RESULT_BACKEND:保存任务返回值。OpenWISP 主要用它查推送结果,2 号库独立可避免结果键挤占缓存。
  • CELERY_TASK_TIME_LIMIT = 600:单任务硬超时 10 分钟,超时后 worker 被杀。批量推送大配置时若经常触发,应调大该值或拆分批次。
  • CELERY_BEAT_SCHEDULE:定时任务表。实测 crontab(hour=2, minute=0) 在 diffsettings 中显示为 <crontab: 0 2 * * * (m/h/dM/MY/d)>。

验证 worker 在线与任务注册:

cd /opt/openwisp/app
sudo -u www-data /opt/openwisp/venv/bin/celery -A openwisp2 inspect ping --timeout 8
sudo -u www-data /opt/openwisp/venv/bin/celery -A openwisp2 inspect registered | head -6

实测回显:

->  celery@openwisp-lab: OK
        pong

1 node online.
->  celery@openwisp-lab: OK
    * openwisp_controller.config.tasks.auto_add_template_to_existing_configs
    * openwisp_controller.config.tasks.bulk_invalidate_config_get_cached_checksum
    * openwisp_controller.config.tasks.change_devices_templates
    * openwisp_controller.config.tasks.create_vpn_dh

💡 技术拓展:任务队列的可靠性有三档——Redis 队列(快、无确认、可能丢任务)、RabbitMQ 带 ack(可重投、可能重复)、数据库队列(最慢、最稳)。OpenWISP 官方文档默认 Redis,本文沿用;若设备规模超过千台且推送不可丢,建议把 broker 换成 RabbitMQ,仅需改 CELERY_BROKER_URL。

八、OPENWISP_* 应用开关

OPENWISP_* 是 OpenWISP 自有命名空间,控制后台界面、API、设备接入与连接器行为。实测 settings 对象中共有 18 个 OPENWISP_* 键,其余未显式设置的项在运行时由组件代码取内置默认值。

后台与 API 开关

参数实测值默认值说明
OPENWISP_ADMIN_DASHBOARD_ENABLEDTrueTrue后台首页仪表盘
OPENWISP_CONTROLLER_GROUP_PIE_CHARTTrueTrue设备分组饼图
OPENWISP_ORGANIZATION_USER_ADMINTrueFalse组织内用户管理入口
OPENWISP_USERS_AUTH_APITrueFalse用户认证 REST API
OPENWISP_CONTROLLER_API未显式设置TrueController REST API 总开关
OPENWISP_CONTROLLER_API_HOST未显式设置None前后端分离时的 API 地址

设备接入与连接器

参数默认值说明
OPENWISP_CONTROLLER_BACKENDS(netjsonconfig.OpenWrt, netjsonconfig.OpenWisp)可选的配置后端
OPENWISP_CONTROLLER_DEFAULT_BACKENDOPENWISP_CONTROLLER_BACKENDS[0][0]新建配置的默认后端
OPENWISP_CONTROLLER_VPN_BACKENDSOpenVPN / WireGuard / VXLAN over WireGuard / ZeroTierVPN 服务端类型
OPENWISP_CONNECTORSSSH / OpenWRT SNMP / Ubiquiti AirOS SNMP设备连接器
OPENWISP_UPDATE_STRATEGIESOpenWRT SSH / OpenWISP 1.x SSH配置更新策略
OPENWISP_CONTROLLER_REGISTRATION_ENABLEDTrue允许设备自动注册
OPENWISP_CONTROLLER_MANAGEMENT_IP_ONLYTrue仅用管理 IP 连接设备
OPENWISP_CONTROLLER_DEVICE_NAME_UNIQUETrue组织内设备名唯一(大小写不敏感)
OPENWISP_CONTROLLER_HARDWARE_ID_ENABLEDFalse启用硬件序列号字段

SSH 超时与安全

参数默认值单位说明
OPENWISP_SSH_CONNECTION_TIMEOUT5秒TCP 建连超时
OPENWISP_SSH_AUTH_TIMEOUT2秒认证响应超时
OPENWISP_SSH_BANNER_TIMEOUT60秒等待 SSH Banner
OPENWISP_SSH_COMMAND_TIMEOUT30秒命令阻塞读写超时

这些 SSH 超时在本文实例中均未显式写入 settings,运行时由组件内置默认值生效:

cd /opt/openwisp/app
sudo -u www-data /opt/openwisp/venv/bin/python manage.py shell -c "
from django.conf import settings as s
print(getattr(s, 'OPENWISP_SSH_COMMAND_TIMEOUT', '未设置(默认 30)'))
print(getattr(s, 'OPENWISP_CONNECTORS', '未设置(内置 SSH/OpenWRT SNMP/AirOS SNMP)'))
print(getattr(s, 'OPENWISP_CONTROLLER_API', '未设置(默认 True)'))
"

实测回显:

未设置(默认 30)
未设置(内置 SSH/OpenWRT SNMP/AirOS SNMP)
未设置(默认 True)

⚠️ 注意:OPENWISP_CONTROLLER_WHOIS_ENABLED 默认 False。若开启,必须同时配置 OPENWISP_CONTROLLER_WHOIS_GEOIP_ACCOUNT 与 OPENWISP_CONTROLLER_WHOIS_GEOIP_KEY,否则组件会抛 ImproperlyConfigured,导致后台加载失败。

九、时区、语言、静态与媒体目录

这四项决定“界面长什么样、文件放哪里”,属于上线前必须确认的基础项。

TIME_ZONE = "Asia/Shanghai"
LANGUAGE_CODE = "zh-hans"
USE_TZ = True
USE_I18N = True

STATIC_URL = "/static/"
MEDIA_URL = "/media/"
STATIC_ROOT = os.path.join(BASE_DIR, "static")
MEDIA_ROOT = os.path.join(BASE_DIR, "media")

验证时区与本地时间:

cd /opt/openwisp/app
sudo -u www-data /opt/openwisp/venv/bin/python manage.py shell -c "
from django.utils import timezone
print(timezone.localtime().isoformat())
"

实测回显:

2026-10-28T02:13:11.289809+08:00

+08:00 证明 Asia/Shanghai 已生效;数据库存 UTC(USE_TZ=True),页面按本地时区渲染。

验证语言:登录后访问设备列表,页面标题实测为 选择 Device 来修改 | OpenWISP Admin,中文菜单与“登录 | OpenWISP Admin”登录页说明 zh-hans 已生效。若想保持英文界面,改回 en-gb 并重启即可。

静态与媒体目录验证:

du -sh /opt/openwisp/app/static
sudo -u www-data /opt/openwisp/venv/bin/python manage.py findstatic admin/css/base.css --verbosity 2 | head -5

实测回显:

31M	/opt/openwisp/app/static
Found 'admin/css/base.css' here:
  /opt/openwisp/venv/lib/python3.10/site-packages/django/contrib/admin/static/admin/css/base.css
  • STATIC_ROOT 是 collectstatic 的输出目录,不是源目录;源文件在各 Python 包的 static/ 下。
  • MEDIA_ROOT 是用户上传目录,必须对 www-data 可写。实测上传探针文件后通过 Nginx 访问返回 200 12:
echo "media-probe" > /opt/openwisp/app/media/probe.txt
sudo chown www-data:www-data /opt/openwisp/app/media/probe.txt
curl -s -o /dev/null -w "%{http_code} %{size_download}\n" -H "Host: openwisp.example.com" http://127.0.0.1/media/probe.txt

实测回显:

200 12

💡 说明:MEDIA_URL 只影响 URL 前缀,实际文件由 Nginx 的 location /media/ { alias ... } 直接返回,不经过 uWSGI。若把 MEDIA_ROOT 改到 Nginx 未配置的路径,页面上的图片与固件包会 404。

十、邮件与 RADIUS 联动

10.1 邮件

OpenWISP 用邮件发送邀请、通知与密码重置。配置项如下:

EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST = "127.0.0.1"
EMAIL_PORT = 25
EMAIL_USE_TLS = False
DEFAULT_FROM_EMAIL = "openwisp@openwisp.example.com"

实测发送测试邮件(本机未运行 SMTP 服务):

cd /opt/openwisp/app
sudo -u www-data /opt/openwisp/venv/bin/python manage.py sendtestemail admin@example.com

实测回显:

    raise err
  File "/usr/lib/python3.10/socket.py", line 833, in create_connection
    sock.connect(sa)
ConnectionRefusedError: [Errno 111] Connection refused

这说明配置本身被正确读取,失败原因是 127.0.0.1:25 没有监听。两种修复:安装并启动本机 MTA(如 Postfix,监听 25);或把 EMAIL_HOST/EMAIL_PORT 指向企业 SMTP,并按需设置 EMAIL_USE_TLS/EMAIL_HOST_USER/EMAIL_HOST_PASSWORD(密钥类用环境变量注入,不写死在 settings)。

10.2 RADIUS 联动

Controller 本身不做 802.1X 或热点认证,认证由独立的 openwisp-radius 模块提供 REST API,FreeRADIUS 通过 rlm_rest 调用。本文实测环境未安装 openwisp-radius(pip list 中无该包),以下参数取自官方 settings 文档(查询日期 2026-10-28),配置方式为在同一个 settings.py 中追加:

参数默认值作用
FREERADIUS_ALLOWED_HOSTS[]允许调用 RADIUS API 的 FreeRADIUS 主机 IP/网段
OPENWISP_RADIUS_APITrue是否启用 RADIUS REST API
OPENWISP_RADIUS_API_BASEURL/API 对外基地址(独立域名时改成 https://radius.example.com)
OPENWISP_RADIUS_API_URLCONFNone独立 API 实例的 urlconf

同机部署的最小写法:

INSTALLED_APPS += ["openwisp_radius"]

FREERADIUS_ALLOWED_HOSTS = ["127.0.0.1"]
OPENWISP_RADIUS_API = True
OPENWISP_RADIUS_API_BASEURL = "https://openwisp.example.com"

联动要点:

  • FREERADIUS_ALLOWED_HOSTS 必须填 FreeRADIUS 所在主机地址;同机填 127.0.0.1,跨机填内网 IP,绝不能留空。
  • 客户端地址取 REMOTE_ADDR,若 FreeRADIUS 前面有反向代理,代理必须把真实地址写入 REMOTE_ADDR,X-Forwarded-For 不被采信。
  • RADIUS 与 Controller 共用 PostgreSQL 时,openwisp_radius 的迁移与 Controller 迁移在同一库执行,升级时按依赖顺序 migrate 即可。
  • 安装该模块后需要重启三个服务,并用 manage.py showmigrations openwisp_radius 确认迁移全部应用。

⚠️ 注意:不要在未安装 openwisp-radius 的情况下把 OPENWISP_RADIUS_* 写进 INSTALLED_APPS,否则 manage.py check 会报 ModuleNotFoundError: No module named 'openwisp_radius'。

十一、生产配置模板

以下模板面向“4 vCPU、16 GB 内存、NVMe SSD、500 台 OpenWrt 设备”的生产场景,在本文基础上补齐 HTTPS 安全项、连接复用与日志轮转。安全项单独放在 settings_hardened.py 便于灰度:

from .settings import *  # noqa

SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_HSTS_SECONDS = 31536000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
SECURE_CONTENT_TYPE_NOSNIFF = True
X_FRAME_OPTIONS = "DENY"

DATABASES["default"]["CONN_MAX_AGE"] = 60

实测校验(--settings=openwisp2.settings_hardened):

cd /opt/openwisp/app
sudo -u www-data /opt/openwisp/venv/bin/python manage.py check --deploy --settings=openwisp2.settings_hardened

实测输出节选:

WARNINGS:
?: Geocoding service is experiencing issues or is not properly configured

System check identified 1 issue (0 silenced).

对比未加固配置的 5 条告警(HSTS、SSL 重定向、Session Cookie、CSRF Cookie、地理编码),加固后只剩地理编码一条,说明 4 条 HTTPS 告警已被消除。

模板选择说明:

场景建议值理由
500 台设备、4 vCPUuWSGI processes=4、threads=2每进程约 50 MB,4 进程够用
数据库同机、16 GBCONN_MAX_AGE=60减少握手;连接数 4×2+2 可控
有 TLS 终止SECURE_PROXY_SSL_HEADER 必须有否则 Django 认为请求是 HTTP,重定向死循环
无 TLS(内网测试)不要启用 SECURE_SSL_REDIRECT否则登录页 301 到 https 无法访问
需要审计LOGGING 保留文件 handler + 轮转默认只输出控制台,journald 也能收

⚠️ 注意:SECURE_HSTS_SECONDS=31536000 一旦下发,浏览器会在一年内强制 HTTPS,且 includeSubDomains 会影响所有子域。上线前确认域名与证书全部就绪,否则回退非常麻烦。

十二、常见问题

12.1 改了 settings 但页面没变化

原因:uWSGI 是多进程常驻,不会自动重载;Celery worker 也在启动时读取配置。

处理:systemctl restart uwsgi-openwisp celery-openwisp celery-beat-openwisp,再用 manage.py shell 读一次生效值确认。

12.2 check --deploy 报 5 条安全告警

现象:W004(HSTS)、W008(SSL 重定向)、W012(Session Cookie Secure)、W016(CSRF Cookie Secure)加一条地理编码告警。

处理:按第十一章模板补齐 4 个 HTTPS 项;地理编码告警按 12.3 处理。补齐后实测只剩 1 条。

12.3 地理编码告警是否必须消除

现象:?: Geocoding service is experiencing issues or is not properly configured。

原因:组件注册的地理编码健康检查访问 geocode.arcgis.com,隔离网络返回 Network is unreachable。

处理:不影响启动与业务。要么放通该域名,要么忽略并在设备位置手工填经纬度。

12.4 会话频繁掉线

排查顺序:redis-cli info keyspace 看 db8 是否有键;redis-cli config get maxmemory-policy 看是否 allkeys-lru;检查是否有人执行了 redis-cli flushall。若是内存淘汰导致,给会话单独实例或改 volatile-lru。

12.5 修改 LANGUAGE_CODE 后部分页面仍是英文

原因:部分第三方包(如 DRF 浏览页、django-allauth 邮件模板)自带翻译缺失,或浏览器 Accept-Language 优先。

处理:USE_I18N=True 时以请求语言为准;确认浏览器语言为中文,或在 MIDDLEWARE 前加 LocaleMiddleware 并设置 LANGUAGE_COOKIE_NAME 固定语言。

十三、参考链接

  • Controller 全部配置项:https://openwisp.io/docs/stable/controller/user/settings.html
  • RADIUS 配置项:https://openwisp.io/docs/stable/radius/user/settings.html
  • Django settings 参考:https://docs.djangoproject.com/en/5.2/ref/settings/
  • Django 缓存框架:https://docs.djangoproject.com/en/5.2/topics/cache/
  • Celery 配置:https://docs.celeryq.dev/en/stable/userguide/configuration.html
  • Channels 层:https://channels.readthedocs.io/en/latest/topics/channel_layers.html
  • PostGIS 文档:https://postgis.net/documentation/

站内延伸阅读:《OpenWISP 介绍与选型指南》、《OpenWISP 1.3.2 Ubuntu 22.04 安装指南》、《OpenWISP 1.3.2 常用 CLI 与运维命令详解》。