NetBox 生产部署指南:使用 Gunicorn 搭建 WSGI 服务并纳入 systemd 托管
【免费下载链接】netboxThe premier source of truth powering network automation. Open source under Apache 2. Try NetBox Cloud free: https://netboxlabs.com/products/free-netbox-cloud/项目地址: https://gitcode.com/gh_mirrors/ne/netbox
本文是 NetBox 官方安装流程的第 4 步(对应 docs/installation/4a-gunicorn.md),讲解如何将 NetBox 这一 Django 应用以 WSGI 形式跑在 Gunicorn 之上,并通过 systemd 将 Web 服务与后台任务 worker 一并托管。读完本文,你将掌握 NetBox 官方默认的 Gunicorn 配置逐项含义、netbox.service与netbox-rq.service两个 systemd 单元的部署与调参方法、启动/验证/排障的完整命令链,以及它如何与后续的 nginx/Apache 反向代理衔接。
一、Gunicorn 在 NetBox 应用栈中的位置
NetBox 本质上是构建在 Django 之上的 Python Web 应用,而 Django 应用对外提供的是 WSGI(Web Server Gateway Interface) 接口,因此 NetBox 必须运行在某个 WSGI 服务器之后。Gunicorn 正是扮演这个角色:它是一个纯 Python 实现的 WSGI HTTP 服务器,负责接收来自前端 HTTP 服务器的代理请求,并调用 NetBox 的 WSGI 应用入口处理请求。
从官方架构说明(见 docs/installation/index.md)可以看到完整的数据流:
- nginx / Apache(HTTP 反向代理)接收外部 HTTPS 请求;
- gunicorn(WSGI HTTP 服务器)承接反向代理转发的请求;
- rqworker(后台 worker)消费 Redis 队列中的任务,与 Web 进程共享同一个 NetBox 应用;
- NetBox(Django 应用)处理业务逻辑,读写 PostgreSQL,并借助 Redis 做缓存与任务排队。
其中 gunicorn 与 rqworker 都由 systemd 托管,是本篇的核心内容。
NetBox 的 WSGI 应用入口位于 netbox/netbox/wsgi.py,其内容非常精简:设置DJANGO_SETTINGS_MODULE为netbox.settings,然后通过django.core.wsgi.get_wsgi_application()构建 application 对象。Gunicorn 启动时正是通过netbox.wsgi这个模块路径加载该应用。
值得注意的是,Gunicorn 会随 NetBox 自动安装,无需单独安装。在仓库根目录的 requirements.txt 中可以看到gunicorn==26.2.0这一依赖项(本文撰写时仓库所锁定版本)。因此只要你按 docs/installation/3-netbox.md 跑过upgrade.sh完成虚拟环境构建,/opt/netbox/venv/bin/gunicorn就已就位。
说明:NetBox 官方同时支持 uWSGI 作为备选 WSGI 服务器。如果计划使用 uWSGI,请直接参考对应文档;本文后续所有命令与配置文件均针对 Gunicorn。
二、配置 Gunicorn:复制官方默认配置
NetBox 发行包内置了一份面向生产环境的 Gunicorn 默认配置。使用它的方式是把它从contrib目录复制到 NetBox 根目录,而不是直接引用原文件:
sudo cp /opt/netbox/contrib/gunicorn.py /opt/netbox/gunicorn.py之所以强调“复制一份”而非“原地引用”,官方文档给出的理由是:确保你后续对配置的本地修改不会在未来的 NetBox 升级中被覆盖。这一点在 docs/installation/upgrading.md 的升级流程中也有呼应——升级新版本时需显式执行sudo cp /opt/netbox-$OLDVER/gunicorn.py /opt/netbox/把旧的 gunicorn 配置带过来。
这份默认配置位于仓库的 contrib/gunicorn.py,完整内容如下:
# The IP address (typically localhost) and port that the NetBox WSGI process should listen on bind = '127.0.0.1:8001' # Number of gunicorn workers to spawn. This should typically be 2n+1, where # n is the number of CPU cores present. workers = 5 # Number of threads per worker process threads = 3 # Timeout (in seconds) for a request to complete timeout = 120 # The maximum number of requests a worker can handle before being respawned max_requests = 5000 max_requests_jitter = 500 # Uncomment this line to accept HTTP headers containing underscores, e.g. for remote # authentication support. See https://docs.gunicorn.org/en/stable/settings.html#header-map # header-map = 'dangerous'官方默认配置足以支撑绝大多数初次安装场景;若需调整监听地址/端口或做性能调优,编辑这份文件即可。以下逐项说明各参数的作用与调优建议。
bind:监听地址与端口
bind = '127.0.0.1:8001'指定 Gunicorn 进程监听的 IP 与端口。默认绑定到本机回环地址127.0.0.1的8001端口——这是一个关键的安全设计:WSGI 服务本身不直接暴露给外部网络,而是由前端 HTTP 服务器(nginx/Apache)通过反向代理访问。8001这个端口号与官方 contrib/nginx.conf 中proxy_pass http://127.0.0.1:8001;保持一致,修改端口时务必同步修改代理配置。
workers:工作进程数
workers = 5定义 Gunicorn 派生的 worker 进程数量。官方配置注释给出了经验公式:2n+1,其中 n 为服务器 CPU 核心数。例如 2 核机器建议 5 个 worker、4 核机器建议 9 个 worker。由于每个 worker 是独立的 Python 进程,会占用一定的内存(从后文systemctl status输出可以看到单实例约 500MB 级别的常驻内存),调大 workers 时需权衡内存容量。
threads:每进程线程数
threads = 3指定每个 worker 进程内运行的线程数量。启用多线程可以让单个 worker 并发处理多个请求,在 I/O 密集场景(NetBox 大量数据库与 Redis 交互)下有助于提升吞吐,同时比单纯增加进程数更节省内存。
timeout:请求超时
timeout = 120表示单个请求允许的最大处理时间(秒)。如果 worker 在 120 秒内未完成响应,Gunicorn 会终止该 worker 并重启它。NetBox 某些重操作(如大范围数据导入、配置渲染)可能耗时较长,若遇到“worker 被频繁杀掉”的现象,可以适当调大此值。
max_requests 与 max_requests_jitter:防内存泄漏的滚动重启
max_requests = 5000与max_requests_jitter = 500组合使用:每个 worker 在处理完 5000 个请求后会被回收重建,且实际阈值会在 0–500 的范围内随机抖动。这套机制用于规避长时间运行导致的 Python 进程内存膨胀问题——即使应用存在轻微内存泄漏,也会在达到阈值时通过重启 worker 得到缓解;引入 jitter(抖动)则是为了避免所有 worker 在同一时刻集体重启造成服务空窗。
header-map:远程认证专用选项
文件中被注释掉的header-map = 'dangerous'用于启用对含下划线 HTTP 头的接收。这一选项主要服务于远程认证场景——例如某些 SSO 反向代理通过X-Remote-User这类带下划线的请求头传递用户身份。默认情况下 Gunicorn 出于安全考量会拒绝此类头部(对应 WSGI 规范中关于 HTTP 头字段命名的限制);只有在明确需要远程认证支持时才取消注释启用它。
三、使用 systemd 托管 Gunicorn 与后台 worker
NetBox 官方建议用 systemd 同时管理两个服务:Web 应用进程(Gunicorn)与后台任务 worker(RQ worker)。
部署服务单元文件
首先把发行包内置的两个 systemd 单元复制到/etc/systemd/system/,并重新加载 systemd 守护进程:
sudo cp -v /opt/netbox/contrib/*.service /etc/systemd/system/ sudo systemctl daemon-reload警告:务必检查用户与组。发行包自带的 service 文件假定服务以
netbox用户和netbox组运行。如果你的安装环境使用了不同的用户名/组名,必须同步修改两个 service 文件中的User=与Group=字段。这一假设与 docs/installation/3-netbox.md 中创建系统用户netbox的步骤相对应。
解析 netbox.service
仓库中的 contrib/netbox.service 控制 Gunicorn 进程,关键配置如下:
[Unit] Description=NetBox WSGI Service Documentation=https://docs.netbox.dev/ After=network-online.target Wants=network-online.target [Service] Type=simple User=netbox Group=netbox PIDFile=/var/tmp/netbox.pid WorkingDirectory=/opt/netbox # Remove the following line if using uWSGI instead of Gunicorn ExecStart=/opt/netbox/venv/bin/gunicorn --pid /var/tmp/netbox.pid --pythonpath /opt/netbox/netbox --config /opt/netbox/gunicorn.py netbox.wsgi # Uncomment the following line if using uWSGI instead of Gunicorn #ExecStart=/opt/netbox/venv/bin/uwsgi --ini /opt/netbox/uwsgi.ini Restart=on-failure RestartSec=30 PrivateTmp=true [Install] WantedBy=multi-user.target逐项说明:
Type=simple:systemd 将ExecStart启动的 gunicorn 主进程视为服务主进程,不做额外 fork 探测;User=netbox/Group=netbox:以低权限系统用户运行,避免以 root 暴露 Web 服务;PIDFile=/var/tmp/netbox.pid:与命令行中--pid参数配套,供 systemd 追踪主进程;WorkingDirectory=/opt/netbox:服务工作目录;ExecStart一行是核心:调用虚拟环境中的 gunicorn 可执行文件,通过--pythonpath /opt/netbox/netbox指定 Django 项目路径,--config /opt/netbox/gunicorn.py指定第二节复制的配置文件,最后的netbox.wsgi即 WSGI 应用模块(对应 netbox/netbox/wsgi.py);Restart=on-failure+RestartSec=30:进程异常退出后 30 秒自动重启;PrivateTmp=true:为服务提供独立的临时目录命名空间,提升安全性;- 文件中同时保留了 uWSGI 的注释行,仅当切换 uWSGI 时才需要取消注释并注释掉 gunicorn 行。
解析 netbox-rq.service
仓库中的 contrib/netbox-rq.service 控制 NetBox 的后台任务 worker:
[Unit] Description=NetBox Request Queue Worker Documentation=https://docs.netbox.dev/ After=network-online.target Wants=network-online.target [Service] Type=simple User=netbox Group=netbox WorkingDirectory=/opt/netbox ExecStart=/opt/netbox/venv/bin/python3 /opt/netbox/netbox/manage.py rqworker high default low Restart=on-failure RestartSec=30 PrivateTmp=true [Install] WantedBy=multi-user.target核心是ExecStart中的python3 manage.py rqworker high default low:通过 Django 管理命令启动 RQ worker,并依次监听high、default、low三个优先级队列。NetBox 的异步任务(如 Webhook 投递、脚本/报告执行、配置渲染等)都会写入这些队列(Redis 的tasks数据库),由该 worker 消费执行——所以 Web 服务与 worker 必须同时运行,NetBox 才能完整工作。
启动并设置开机自启
sudo systemctl enable --now netbox netbox-rqenable --now一步完成两件事:注册开机自启(对应单元文件中的WantedBy=multi-user.target)并立即启动服务。
验证服务状态
使用systemctl status确认 WSGI 服务正在运行:
systemctl status netbox.service正常输出类似于:
● netbox.service - NetBox WSGI Service Loaded: loaded (/etc/systemd/system/netbox.service; enabled; preset: enabled) Active: active (running) since Mon 2026-01-26 11:00:00 CST; 7s ago Docs: https://docs.netbox.dev/ Main PID: 7283 (gunicorn) Tasks: 6 (limit: 4545) Memory: 556.1M (peak: 556.3M) CPU: 3.387s CGroup: /system.slice/netbox.service ├─7283 /opt/netbox/venv/bin/python3 /opt/netbox/venv/bin/gunicorn --pid /var/tmp/netbox.pid --pythonpath /opt/netbox/netbox> ├─7285 /opt/netbox/venv/bin/python3 /opt/netbox/venv/bin/gunicorn --pid /var/tmp/netbox.pid --pythonpath /opt/netbox/netbox> ├─7286 /opt/netbox/venv/bin/python3 /opt/netbox/venv/bin/gunicorn --pid /var/tmp/netbox.pid --pythonpath /opt/netbox/netbox> ├─7287 /opt/netbox/venv/bin/python3 /opt/netbox/venv/bin/gunicorn --pid /var/tmp/netbox.pid --pythonpath /opt/netbox/netbox> ├─7288 /opt/netbox/venv/bin/python3 /opt/netbox/venv/bin/gunicorn --pid /var/tmp/netbox.pid --pythonpath /opt/netbox/netbox> └─7289 /opt/netbox/venv/bin/python3 /opt/netbox/venv/bin/gunicorn --pid /var/tmp/netbox.pid --pythonpath /opt/netbox/netbox> Jan 26 11:00:00 netbox systemd[1]: Started netbox.service - NetBox WSGI Service. ...解读这份输出:
Active: active (running)表示服务健康;Main PID: 7283 (gunicorn)是 gunicorn 主进程;CGroup列表中出现 1 个主进程 + 5 个 worker 子进程,正好对应配置中workers = 5的默认值——这是验证配置是否生效的直观手段;Tasks: 6与Memory: 556.1M反映服务进程数与内存占用,可作为调整 worker 数量的依据。
故障排查
如果 NetBox 服务启动失败,使用journalctl查看日志定位问题:
journalctl -eu netbox-e直接从日志尾部开始显示,-u netbox仅过滤该单元。常见的启动失败原因包括:configuration.py中数据库/Redis 连接信息有误、netbox用户对目录无权限、端口被占用等,日志中通常会有明确的 Python traceback 可供定位。
四、与 HTTP 反向代理对接
WSGI 服务验证通过后,下一步是安装 HTTP 服务器(详见 docs/installation/5-http-server.md)。以官方 contrib/nginx.conf 为例,反向代理的关键段落如下:
location / { # Remove these lines if using uWSGI instead of Gunicorn proxy_pass http://127.0.0.1:8001; proxy_set_header X-Forwarded-Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; ... }nginx 将外部请求转发到 Gunicorn 监听的127.0.0.1:8001,并透传原始 Host、客户端 IP 与协议信息——NetBox(Django)依赖这些X-Forwarded-*头正确识别真实客户端与请求协议。如果修改了 gunicorn.py 中的 bind 端口,必须同步修改此处的proxy_pass。
若外部可以访问但返回502 Bad Gateway,按 docs/installation/5-http-server.md 的排查清单依次检查:
- WSGI worker 是否在运行:
systemctl status netbox应显示active (running); - 反向代理是否指向 Gunicorn 实际监听端口(默认 8001);
- SELinux 是否拦截反向代理连接,必要时执行
setsebool -P httpd_can_network_connect 1放行。
五、升级与日常维护
Gunicorn 的配置与 service 文件在 NetBox 升级时需要特别留意(详见 docs/installation/upgrading.md):
- gunicorn.py 属于本地配置:升级新版本时,需要把旧版本中的
gunicorn.py复制到新版本根目录,避免本地调优丢失:sudo cp /opt/netbox-$OLDVER/gunicorn.py /opt/netbox/ - service 文件以 contrib 目录为准:升级后对比
contrib/下新增的示例单元文件,必要时同步更新/etc/systemd/system/中的副本; - 升级完成后重启两个服务:
sudo systemctl restart netbox netbox-rq注意必须同时重启两者——只重启 Web 服务而不重启 worker,会导致 Web 端与后台队列消费端运行在不同代码版本上。
六、小结与下一步
至此,你已完成 NetBox 生产部署链条中承上启下的一环:Gunicorn 作为 WSGI 服务器承载 Django 应用,配合 rqworker 消费后台任务队列,两者统一由 systemd 托管并支持开机自启、崩溃自动重启与日志排障。其核心工作流可概括为:
- 复制 contrib/gunicorn.py 为本地配置,按 CPU/内存调整
workers、threads、timeout等参数; - 复制 contrib/netbox.service 与 contrib/netbox-rq.service 到 systemd 目录,核对
User/Group后enable --now; - 用
systemctl status netbox验证 worker 数量与内存,用journalctl -eu netbox排障; - 继续 HTTP 服务器安装,让 nginx/Apache 代理到
127.0.0.1:8001对外提供 HTTPS 访问。
完整安装流程的其余步骤可参考 docs/installation/index.md 中的清单:PostgreSQL、Redis、NetBox 本体、WSGI 服务器(本文)、HTTP 服务器与可选的 LDAP 认证。
【免费下载链接】netboxThe premier source of truth powering network automation. Open source under Apache 2. Try NetBox Cloud free: https://netboxlabs.com/products/free-netbox-cloud/项目地址: https://gitcode.com/gh_mirrors/ne/netbox
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考