新手?请先阅读 👋
从没听说过 Marzban、"VPS" 或"面板"?没关系——本页用最通俗的话把整个思路讲清楚。零基础也能看懂。
一句话概括:NexusPanel 是一款让你运营自己的 VPN 服务并出售访问权限的软件——有点像经营一家自己的小型 Netflix,只不过你卖的是一条私密、不被封锁、速度更快的互联网连接。
你租一台便宜的服务器,在上面装好 NexusPanel,就得到一个简洁的网页控制台。在这个控制台里你创建客户,每位客户都会拿到一个链接,把它粘贴到手机上的一款免费 App 里。他们点一下"连接"——网络就通过你的服务器走了。你按月向他们收费。整个生意就是这么简单。
开店类比
如果你能想象经营一家小店,那你已经理解了 NexusPanel。下面把整套东西对应起来:
老板
你经营这门生意、定价、添加客户。你不需要是程序员。
你的店面
你在数据中心租用的一台电脑(约 5 美元/月)。你的面板就跑在这里。供应商:Hetzner、Contabo、DigitalOcean……
你的收银台 + 货架
你在浏览器中登录的控制面板。添加客户、查看流量、收款——全在这里完成。
海外分店
比如部署在德国或芬兰的一台额外服务器,让客户可以选择从哪里连接。可选——一开始可以一个都不要。
会员卡
你交给每位客户的一条网页链接。它包含了他们所有的连接配置——这就是他们唯一需要的东西。
客户的入口
一款免费 App(Happ、v2rayNG、Streisand……)。他们把链接粘贴一次、点击连接,就好了。你永远不用碰他们的手机。
钱到底是怎么流动的
- 有人想要私密或不被封锁的互联网并向你付款(通过内置的 Telegram 机器人自动收取加密货币,或以你喜欢的任意方式收款)。
- 你打开 NexusPanel 为他创建一个用户——设置有效期和流量额度。大约只需 10 秒。
- 你把订阅链接发给他。
- 他把链接粘贴到一款免费 App 里并点击连接。他就通过你的服务器上线了。
- 下个月他再次付款以保持有效。你想要多少客户就重复多少次。
VLESS、Xray、Reality 或 Hysteria 这些词,只是数据穿行所经过的不同种类的隧道而已。NexusPanel 会选择合理的默认值——你完全可以在不了解它们含义的情况下经营整门生意。等你有兴趣了,术语表会用一句话解释每一个。
准备好了?选择你的起点
前往从哪开始,从三条路径中选一条:试用免费版(无需安装)、在新服务器上全新安装,或从 Marzban 迁移。
你会遇到的术语 📖
本文档中的每一个行话,都用一句通俗的话解释。现在快速浏览一遍;以后哪个词把你绊住了再回来查。
- VPS virtual private server
- 你在数据中心按月租用的一台电脑。你的面板就跑在上面。每月约 4–6 美元就足够起步了。
- Panel(面板)
- 你登录进去运营一切的网页控制台——也就是 NexusPanel 本身。它运行在你的 VPS 上。
- Node(节点)
- 位于另一个地区的额外服务器,连接到你的面板,让客户可以选择从哪里连接。完全可选。
- User(用户) 即客户
- 你出售访问权限的一个人。每位用户都有到期日期、流量额度和自己的订阅链接。
- Subscription link(订阅链接) "sub link"
- 你给客户的那一条 URL。他们的 App 读取它来学习如何连接。如果你从 Marzban 迁移,这些链接照常可用。
- Client app(客户端 App)
- 客户安装的免费 App——例如 Happ、v2rayNG、Streisand、Hiddify。他们把订阅链接粘贴进去一次即可。
- Marzban
- 许多运营者最初使用的那款较老的、免费的、需要自己动手的面板。NexusPanel 是它升级、有支持的继任者——还能用一条命令导入 Marzban 的整套配置。
- License(授权)
- 你运行 NexusPanel 的钥匙。可从 Telegram 机器人领取免费 14 天试用或购买付费方案。没有授权时,面板以试用模式运行。
- Domain(域名)
- 像
panel.yoursite.com这样指向你 VPS 的名字。浏览器小锁标志(HTTPS)需要它。可选,但强烈建议配置。 - SSL / HTTPS
- 浏览器里的那个小锁——加密技术,保护登录安全。当你有域名时,NexusPanel 会自动配置好。
- Xray
- 底层那个免费引擎,真正负责传输加密流量。你很少会直接接触它。
- VLESS / VMess / Trojan / Shadowsocks
- Xray 可以使用的不同种类的隧道。可以想成不同品牌的汽车——都能把你送到目的地。VLESS 通常是默认选项。
- Reality / XHTTP / ECH / Finalmask
- 让你的流量看起来像普通网页浏览的小技巧,从而更难被封锁。可逐主机开关;一开始用默认值就行。
- Hysteria 2
- 一种不同的、非常快的隧道类型,在网络糟糕或被限速的环境下表现尤为出色。可选;与 Xray 并行运行。
- Middle server(中转服务器)
- 放在你真实服务器前面、用来躲避封锁的一台便宜中继。属于进阶功能——在真正需要之前可以忽略它。
- Inbound / Host(入站 / 主机)
- 进入你服务器的一个具体"入口门"(协议 + 端口 + 配置)。面板自带了合理的配置;想要更多时再添加。
- Admin / Reseller(管理员 / 分销商)
- 你创建的额外登录账户。分销商在你设定的限额内管理自己的客户——当有人在你名下销售时很方便。
- IP / device limit(IP / 设备限制)
- 对一个客户同时可使用多少台手机或电脑的上限——防止共享密码吃掉你的带宽。
从哪开始
三条路径。选最适合你的那一条,10 分钟内即可运行起来。
NexusPanel 是一个多租户 VPN 面板——你出售子账户,你的客户通过任意 v2ray 客户端连接,你在一个控制面板里管理一切。如果你是新手,最快了解它能做什么的方式就是免费试用。如果你已经在跑 Marzban,迁移工具会用一条命令把所有东西迁移过来——用户、管理员、主机、证书,连你现有的订阅 URL 都照常可用。
试用免费版
打开 Telegram 机器人,输入 /start,领取一个 14 天试用授权。你可以用这个授权搭建自己的面板,在付费之前先亲自体验一遍。
在全新服务器上安装
在一台干净的 Ubuntu 20.04+ VPS 上执行一条命令。脚本会询问你的授权、域名和管理员密码——仅此而已。只要你把域名指向服务器,SSL 就会自动配置。
查看安装命令 ↓从 Marzban 迁移
同一台 VPS,无需重新配置客户端。迁移工具采用预演优先且可逆的设计——在动任何东西之前你都能预览每一处改动,并且在最终切换前的任何时刻都能回滚。从 Remnawave 面板迁移同样支持,见从 Remnawave 迁移。
迁移指南 ↓https://your-panel/sub/<token> 链接都仍能正常解析。
你需要准备什么
- 一台 Ubuntu 20.04+(或任意 Debian 系发行版)的 VPS,最低 1 GB 内存,建议 2 GB
- 该 VPS 的 root SSH 访问权限
- 一个指向该 VPS 的域名(可选——可获得真实、无警告的 HTTPS 证书;没有域名也一样能用 HTTPS,只是使用自签名证书,浏览器会有一次性警告)
- 一个 NexusPanel 授权(从 Telegram 机器人领取,免费 14 天试用即可)
如何获取帮助
如果出了任何问题,请按顺序尝试:
- 查看面板日志:
cd /opt/panel && docker compose logs --tail 100 - 阅读本文档的相关章节(左侧侧边栏)
- 在 Telegram 上联系我们——链接在机器人里,响应时间以小时计而非天
什么是 NexusPanel
NexusPanel 是一款为 VPN 服务商和网络管理员打造的、现代、功能丰富的代理管理面板。它提供统一的控制面板,跨多台服务器管理用户、节点、订阅和数据分析。
在底层,完整的功能集包括:
- 多协议支持 — 通过 Xray-core 支持 VMess、VLESS、Trojan、Shadowsocks,外加作为独立 sidecar 的 Hysteria 2。传输与混淆扩展(XHTTP、Reality、ECH、TLS 分片、Finalmask)在面板中按主机配置。
- 分布式节点 — 从单一面板连接数量不限的远程服务器
- 真实的按用户限制 — 流量、到期、IP 与设备上限,通过解析 Xray 访问日志真正强制执行
- 管理员角色与主机作用域 — 业主、管理员、分销商三级,带流量配额;可将特定主机分配给特定管理员
- REST API — 75+ 个端点,用于自动化与集成
- Grafana 风格的数据分析 — 流量随时间变化、用户增长、协议/状态环形图、消耗大户排行、节点带宽负载(自动刷新)
- Telegram 机器人 — 面向客户的支付机器人(通过 NOWPayments 收取加密货币)外加管理员通知
- 授权系统 — 试用 → 付费分级,6 小时心跳并提供 Docker 镜像更新通知
- 加密 Happ 链接 — 真正的 RSA-4096
happ://crypt4/深链,隐藏底层订阅 URL - 2FA — 带二维码和恢复码的 TOTP
- 移动端就绪 — 响应式控制面板,带底部栏导航和溢出抽屉
- 代码保护 — 敏感的 Python 模块经 Cython 编译为
.so二进制文件 - 应用内可操作通知 — 即将到期的用户、流量达上限、离线节点、授权到期
系统要求
| 组件 | 最低配置 | 推荐配置 |
|---|---|---|
| 操作系统 | Ubuntu 20.04+ / Debian 11+ | Ubuntu 22.04 LTS |
| 内存 | 1 GB | 2 GB+ |
| CPU | 1 vCPU | 2 vCPU |
| 磁盘 | 10 GB | 20 GB+(SSD) |
| Docker | 20.10+ | 最新稳定版 |
| 域名 | 可选 | 推荐(用于 SSL) |
快速安装
在一台全新的 VPS 上运行这一条命令,即可使用默认设置安装 NexusPanel:
curl -sL https://nexuspanel.store/install | bash
脚本会提示你输入:
- 授权密钥与客户端 ID — 来自 @nexuspanelpayment_bot(免费 14 天试用密钥同样适用,但安装脚本始终需要一个密钥——不存在无授权安装)
- 域名 — 用于通过 Let's Encrypt 配置 SSL(仅用 IP 则跳过)
- 管理员用户名与密码 — 用于控制面板
- 面板端口 — 默认 8443
随后它会:
- 如缺失则安装 Docker 与 Docker Compose
- 拉取
ghcr.io/haitovs/nexus:latest(经 Cython 保护的生产镜像) - 创建
/opt/panel/,包含.env和docker-compose.yml(容器名:nexus-panel) - 生成启用访问日志的
xray_config.json(IP/设备限制强制执行所必需) - 启动面板并打印控制面板 URL + 登录凭据
nexus update 来应用更新。
一键安装(详细)
安装脚本接受可选参数来自定义安装过程:
# 推荐 —— 传入你的授权密钥 + 客户端 ID(来自 @nexuspanelpayment_bot) curl -sL https://nexuspanel.store/install | bash -s -- \ --license YOUR_LICENSE_KEY \ --client YOUR_CLIENT_ID \ --domain panel.example.com \ --port 8443 # 同样效果,用环境变量代替参数 curl -sL https://nexuspanel.store/install | LICENSE_ID=YOUR_LICENSE_KEY CLIENT_ID=YOUR_CLIENT_ID DOMAIN=panel.example.com bash # 仅用 IP(无域名)—— 只需省略 --domain,依然会启用 HTTPS(自签名证书) curl -sL https://nexuspanel.store/install | bash -s -- \ --license YOUR_LICENSE_KEY \ --client YOUR_CLIENT_ID
授权密钥与客户端 ID 为必填项 — 请从 @nexuspanelpayment_bot 获取。运行 bash -s -- --help 可查看所有参数(--port 默认为 8443,另外还有 --username、--password、--ssl、--migrate)。
脚本结束时会打印面板地址、管理员用户名和密码——用这些登录,不要沿用文档中的示例值(如 myadmin/securepass123),它们不会生效。
面板可通过 https://YOUR_DOMAIN:8443/dashboard/(或仅用 IP 安装时 https://YOUR_IP:8443/dashboard/)访问。
面板初始步骤
登录后,按以下顺序最快建立第一条可用连接:
- 创建一个用户 — 面板 → Users → Add User。设置到期时间和流量限额,然后复制订阅链接,交给客户端应用(Happ、v2rayNG、Streisand 等)。
- 添加一个节点(可选)— 面板 → Nodes → Add New Node,复制生成的快速安装命令,在节点服务器上运行,然后回到面板填写 Name + Address 完成连接。详见节点安装。
- 设置订阅域名 — 如果订阅链接要从与管理面板不同的主机/域名提供,请在环境变量编辑器(Settings → Env)中设置
XRAY_SUBSCRIPTION_URL_PREFIX,并使用 Save & Restart——该设置只有完整重启后才会生效。
手动安装
上面的安装脚本是官方支持的方式——它会自动完成私有镜像仓库的认证、写出可用的 .env,并配置好防火墙。如果你想手动完成这一切:
# 1. 镜像是私有的——不先认证直接 `docker pull` 会返回 "denied"。 # 用授权换取一个短期 pull token: curl -s -X POST https://nexuspanel.store/api/registry-token \ -H 'Content-Type: application/json' \ -d '{"license_id":"YOUR_LICENSE_KEY","client_id":"YOUR_CLIENT_ID"}' # → {"token": "...", "username": "..."} —— 用它登录: echo $TOKEN | docker login ghcr.io -u $USERNAME --password-stdin # 2. 拉取镜像 docker pull ghcr.io/haitovs/nexus:latest # 3. 编写 /opt/panel/.env——完整键值见下方“环境变量参考”。最低要求: # UVICORN_PORT、SUDO_USERNAME、SUDO_PASSWORD、SQLALCHEMY_DATABASE_URL、 # LICENSE_ID、CLIENT_ID mkdir -p /opt/panel /var/lib/panel /var/lib/nexus nano /opt/panel/.env # 4. 用下方“Docker Compose 示例”一节中的 docker-compose.yml 启动 cd /opt/panel docker compose up -d # 查看日志 docker compose logs -f
配置 SSL(Certbot)
使用免费的 Let's Encrypt 证书启用 HTTPS:
# 安装 certbot apt install -y certbot # 申请证书(如果占用 80 端口请先停止面板) docker compose down certbot certonly --standalone -d panel.example.com # 添加到 .env UVICORN_SSL_CERTFILE="/etc/letsencrypt/live/panel.example.com/fullchain.pem" UVICORN_SSL_KEYFILE="/etc/letsencrypt/live/panel.example.com/privkey.pem" # 在 docker-compose.yml 中挂载证书并重启 docker compose up -d
添加一个 cron 任务用于自动续期:
0 3 * * * certbot renew --quiet && docker compose -C /opt/nexuspanel restart
使用 PostgreSQL
对于生产环境部署,建议使用 PostgreSQL 而非 SQLite。设置 BACKEND_MODE=modern,并使用面板实际内置的驱动——psycopg2(同步),而不是 asyncpg:
# 在 .env 中设置 BACKEND_MODE=modern SQLALCHEMY_DATABASE_URL="postgresql+psycopg2://nexus:${POSTGRES_PASSWORD}@127.0.0.1:5432/nexus" REDIS_URL="redis://127.0.0.1:6379/0" POSTGRES_PASSWORD=$(openssl rand -hex 24)
不要手写 compose 文件——使用仓库根目录维护的 docker-compose.modern.yml,它会以 network_mode: host 在面板旁一并启动 Postgres 16 + Redis 7:
# 在安装目录下(例如 /opt/panel)
cp docker-compose.modern.yml docker-compose.yml
docker compose up -d
psycopg2-binary,不是 asyncpg——使用 postgresql+asyncpg:// 会因找不到驱动而失败。请始终使用 postgresql+psycopg2://。
Docker Compose 示例
Classic(SQLite)—— 安装程序实际写出的文件
services: panel: image: ghcr.io/haitovs/nexus:latest container_name: nexus-panel restart: always env_file: .env network_mode: host dns: [8.8.8.8, 1.1.1.1] volumes: - /var/lib/panel:/var/lib/panel - /var/lib/nexus:/var/lib/nexus - ./.env:/app/env.live - /var/run/docker.sock:/var/run/docker.sock:ro environment: NEXUS_HOST_ENV_FILE: /app/env.live healthcheck: test: ["CMD", "curl", "-skf", "http://127.0.0.1:8443/api/v1/health"] interval: 30s timeout: 5s start_period: 30s retries: 3
network_mode: host 是必需的——面板以及任何同机部署的节点/middle-relay 都直接在宿主机上绑定端口,而(只读)挂载的 docker socket 正是节点/middle-server 一键 SSH 安装的实现基础。/var/lib/nexus 不是可选项:授权模块的状态缓存就存在这里——不挂载它,面板就无法确认自己已获得授权。请把 healthcheck 中的 8443 换成你实际设置的 UVICORN_PORT;如果你在使用域名,还需挂载 /etc/letsencrypt:/etc/letsencrypt:ro,并让 UVICORN_SSL_CERTFILE/UVICORN_SSL_KEYFILE 指向签发的证书。
完整技术栈(PostgreSQL + Redis)
见上方使用 PostgreSQL一节——请使用仓库维护的 docker-compose.modern.yml,不要手写 Postgres compose 文件。
配置参考
NexusPanel 完全通过环境变量进行配置。在你的 .env 文件中设置,或直接传给 Docker。
.env.example 复制为 .env,并取消注释你需要的变量。所有变量都有合理的默认值。
服务器
| 变量 | 默认值 | 说明 |
|---|---|---|
UVICORN_HOST | 0.0.0.0 | 服务器绑定地址 |
UVICORN_PORT | 8000 | HTTP 端口 |
UVICORN_UDS | — | Unix 域套接字路径(覆盖 host/port) |
UVICORN_SSL_CERTFILE | — | SSL 证书路径(fullchain.pem) |
UVICORN_SSL_KEYFILE | — | SSL 私钥路径 |
UVICORN_SSL_CA_TYPE | public | CA 类型:public 或 private |
DASHBOARD_PATH | /dashboard/ | 网页控制面板的 URL 路径 |
ALLOWED_ORIGINS | — | 以逗号分隔的 CORS 来源 |
SUDO_USERNAME | — | 初始超级管理员用户名 |
SUDO_PASSWORD | — | 初始超级管理员密码 |
JWT_ACCESS_TOKEN_EXPIRE_MINUTES | 1440 | 令牌过期时间(分钟,默认 24 小时) |
数据库
| 变量 | 默认值 | 说明 |
|---|---|---|
SQLALCHEMY_DATABASE_URL | sqlite:///db.sqlite3 | 数据库连接字符串 |
SQLALCHEMY_POOL_SIZE | 10 | 连接池大小 |
SQLIALCHEMY_MAX_OVERFLOW | 30 | 连接池之外的最大连接数 |
BACKEND_MODE | classic | classic(SQLite/Postgres,默认)或 modern(增加 Redis 支持的事件队列) |
REDIS_URL | — | Redis 连接字符串;当 BACKEND_MODE=modern 时必填 |
postgresql+asyncpg://user:pass@host:5432/dbname。
BACKEND_MODE=modern 并提供 REDIS_URL 以启用 Redis 支持的事件队列。使用 docker-compose.modern.yml,它会随面板一起部署一个 redis:7 服务。大多数部署并不需要这个。
Xray
| 变量 | 默认值 | 说明 |
|---|---|---|
XRAY_JSON | xray_config.json | Xray 核心配置文件路径 |
XRAY_EXECUTABLE_PATH | /usr/local/bin/xray | Xray 二进制文件路径 |
XRAY_ASSETS_PATH | /usr/local/share/xray | geoip.dat 和 geosite.dat 的路径 |
XRAY_SUBSCRIPTION_URL_PREFIX | — | 订阅链接的公开 URL 前缀(例如 https://sub.example.com)。改动仅在面板完整重启后生效——请使用环境变量编辑器中的 保存并重启,而非容器重启。 |
XRAY_SUBSCRIPTION_PATH | sub | 订阅的 URL 路径段 |
XRAY_EXCLUDE_INBOUND_TAGS | — | 以空格分隔的、需排除的入站标签 |
XRAY_FALLBACKS_INBOUND_TAG | — | 用于回退路由的入站标签 |
订阅
| 变量 | 默认值 | 说明 |
|---|---|---|
SUB_PROFILE_TITLE | Subscription | 客户端 App 中显示的名称 |
SUB_SUPPORT_URL | — | 包含在订阅信息中的支持链接 |
SUB_UPDATE_INTERVAL | 12 | 客户端自动更新间隔(小时) |
EXTERNAL_CONFIG | — | 用于客户端集成的外部配置 URL |
USE_CUSTOM_JSON_DEFAULT | false | 为默认客户端启用自定义 JSON 配置 |
USE_CUSTOM_JSON_FOR_V2RAYN | false | 为 V2RayN 启用自定义 JSON |
USE_CUSTOM_JSON_FOR_V2RAYNG | false | 为 V2RayNG 启用自定义 JSON |
USE_CUSTOM_JSON_FOR_STREISAND | false | 为 Streisand 启用自定义 JSON |
USE_CUSTOM_JSON_FOR_HAPP | false | 为 Happ 启用自定义 JSON |
SUB_RATE_LIMIT_PER_MINUTE | 60 | 每个 IP 每分钟最多拉取订阅的次数(进程内,重启后重置) |
SUB_ENABLE_ETAG | true | 返回 ETag / 处理 If-None-Match,在订阅未变更时节省带宽 |
SUB_GZIP_MIN_SIZE | 512 | 对大于此字节数的订阅响应进行 Gzip 压缩 |
模板
| 变量 | 默认值 | 说明 |
|---|---|---|
CUSTOM_TEMPLATES_DIRECTORY | /var/lib/panel/templates/ | 自定义模板的基目录 |
SUBSCRIPTION_PAGE_TEMPLATE | subscription/index.html | 用户订阅页面的模板 |
HOME_PAGE_TEMPLATE | home/index.html | 面板首页的模板 |
CLASH_SUBSCRIPTION_TEMPLATE | clash/default.yml | Clash 订阅模板 |
CLASH_SETTINGS_TEMPLATE | clash/settings.yml | Clash 设置模板 |
V2RAY_SUBSCRIPTION_TEMPLATE | v2ray/default.json | V2Ray 订阅模板 |
V2RAY_SETTINGS_TEMPLATE | v2ray/settings.json | V2Ray 设置模板 |
SINGBOX_SUBSCRIPTION_TEMPLATE | singbox/default.json | Sing-box 订阅模板 |
SINGBOX_SETTINGS_TEMPLATE | singbox/settings.json | Sing-box 设置模板 |
MUX_TEMPLATE | mux/default.json | 多路复用配置模板 |
USER_AGENT_TEMPLATE | user_agent/default.json | User-agent 解析模板 |
GRPC_USER_AGENT_TEMPLATE | user_agent/grpc.json | gRPC user-agent 模板 |
Telegram
| 变量 | 默认值 | 说明 |
|---|---|---|
TELEGRAM_API_TOKEN | — | 来自 @BotFather 的机器人令牌 |
TELEGRAM_ADMIN_ID | — | 以逗号分隔的管理员 Telegram 用户 ID |
TELEGRAM_LOGGER_CHANNEL_ID | — | 用于日志消息的频道 ID |
TELEGRAM_DEFAULT_VLESS_FLOW | xtls-rprx-vision | 机器人创建用户时的默认 VLESS flow |
TELEGRAM_PROXY_URL | — | Telegram API 连接的代理 URL |
通知
| 变量 | 默认值 | 说明 |
|---|---|---|
NOTIFY_STATUS_CHANGE | true | 用户状态变更时通知 |
NOTIFY_USER_CREATED | true | 创建新用户时通知 |
NOTIFY_USER_UPDATED | true | 修改用户时通知 |
NOTIFY_USER_DELETED | true | 删除用户时通知 |
NOTIFY_USER_DATA_USED_RESET | true | 用量重置时通知 |
NOTIFY_USER_SUB_REVOKED | true | 订阅被吊销时通知 |
NOTIFY_IF_DATA_USAGE_PERCENT_REACHED | true | 达到流量阈值时通知 |
NOTIFY_IF_DAYS_LEFT_REACHED | true | 达到到期阈值时通知 |
NOTIFY_LOGIN | true | 管理员登录时通知 |
LOGIN_NOTIFY_WHITE_LIST | — | 从登录通知中排除的 IP |
NOTIFY_DAYS_LEFT | 3,7 | 剩余天数通知阈值 |
NOTIFY_REACHED_USAGE_PERCENT | 80,90 | 用量百分比阈值 |
RECURRENT_NOTIFICATIONS_TIMEOUT | 180 | 重复通知之间的间隔(分钟) |
NUMBER_OF_RECURRENT_NOTIFICATIONS | 3 | 每个事件的最大重复通知次数 |
DISCORD_WEBHOOK_URL | — | 用于 Telegram 风格通知的 Discord webhook |
WEBHOOK_ADDRESS | — | 遗留:以逗号分隔的静态 webhook URL。新部署请优先使用控制面板的 Webhook 界面。 |
WEBHOOK_SECRET | — | 遗留:用于 WEBHOOK_ADDRESS 投递的 HMAC 密钥。控制面板 webhook 按端点分别管理密钥。 |
品牌定制(白标)
| 变量 | 默认值 | 说明 |
|---|---|---|
BRAND_NAME | Panel | 在界面和邮件中显示的面板名称 |
BRAND_LOGO_URL | — | 自定义 logo 图片的 URL |
BRAND_FAVICON_URL | — | 自定义 favicon 的 URL |
安全
| 变量 | 默认值 | 说明 |
|---|---|---|
CAPTCHA_PROVIDER | disabled | 验证码提供方:disabled、turnstile 或 builtin |
TURNSTILE_SITE_KEY | — | Cloudflare Turnstile 站点密钥 |
TURNSTILE_SECRET_KEY | — | Cloudflare Turnstile 私密密钥 |
LOGIN_RATE_LIMIT | 10/minute | 每个时间窗内的最大登录尝试次数 |
LOGIN_LOCKOUT_THRESHOLD | 10 | 触发锁定前的失败尝试次数 |
LOGIN_LOCKOUT_DURATION_MINUTES | 30 | 锁定时长(分钟) |
日志
| 变量 | 默认值 | 说明 |
|---|---|---|
LOG_LEVEL | INFO | 日志级别:DEBUG、INFO、WARNING、ERROR |
LOG_FORMAT | text | 日志格式:text 或 json |
LOG_FILE_PATH | — | 将日志写入文件(在 stdout 之外) |
LOG_MAX_SIZE_MB | 10 | 轮转前的最大日志文件大小 |
LOG_BACKUP_COUNT | 5 | 保留的已轮转日志文件数量 |
指标(Prometheus)
| 变量 | 默认值 | 说明 |
|---|---|---|
METRICS_ENABLED | false | 启用 Prometheus /metrics 端点 |
METRICS_TOKEN | — | 抓取指标所需的 Bearer 令牌 |
其他变量
| 变量 | 默认值 | 说明 |
|---|---|---|
ACTIVE_STATUS_TEXT | Active | 有效状态的自定义标签 |
EXPIRED_STATUS_TEXT | Expired | 已过期状态的自定义标签 |
LIMITED_STATUS_TEXT | Limited | 受限状态的自定义标签 |
DISABLED_STATUS_TEXT | Disabled | 已禁用状态的自定义标签 |
ONHOLD_STATUS_TEXT | On-Hold | 挂起状态的自定义标签 |
USERS_AUTODELETE_DAYS | -1 | N 天后自动删除已过期用户(-1 = 禁用) |
USER_AUTODELETE_INCLUDE_LIMITED_ACCOUNTS | false | 自动删除时包含流量受限的用户 |
JOB_CORE_HEALTH_CHECK_INTERVAL | 10 | 健康检查间隔(秒) |
JOB_RECORD_NODE_USAGES_INTERVAL | 30 | 节点用量记录间隔 |
JOB_RECORD_USER_USAGES_INTERVAL | 10 | 用户用量记录间隔 |
JOB_REVIEW_USERS_INTERVAL | 10 | 用户审查/到期检查间隔 |
JOB_SEND_NOTIFICATIONS_INTERVAL | 30 | 通知派发间隔 |
DISABLE_RECORDING_NODE_USAGE | false | 禁用节点用量记录 |
DEBUG | false | 启用带热重载的调试模式 |
DOCS | false | 在 /docs 启用 Swagger UI |
VITE_BASE_API | /api/v1/ | 前端构建的基础 API 路径 |
控制面板
NexusPanel 控制面板是一个基于 React 的现代网页应用,可通过 /dashboard/ 访问。它为管理你的代理基础设施提供了完整的界面。
概览页
控制面板首页一目了然地展示实时统计数据:
- 用户总数 — 有效、已过期、受限、已禁用的数量
- 带宽用量 — 总上传/下载,带趋势图
- 节点状态 — 在线/离线指示,带负载百分比
- 近期活动 — 最新的用户创建、连接和管理员操作
- 协议分布 — 使用中协议的饼图
用户管理
用户页支持完整的生命周期管理:
- 创建用户 — 设置用户名、流量额度、到期日期、协议、设备限制、IP 限制
- 编辑用户 — 修改所有字段,包括状态(有效、禁用、挂起)
- 批量操作 — 选中多个用户进行批量更新、重置用量或删除
- 搜索与筛选 — 按状态、管理员、协议筛选,或按用户名搜索
- 订阅链接 — 复制订阅 URL、生成二维码
- 用量统计 — 每个用户的上传/下载,带历史数据
节点
管理连接到面板的远程 Xray 节点:
- 添加节点 — 提供地址、端口和用量系数
- 连接状态 — 实时在线/离线及延迟
- 国家旗帜 — 根据节点位置自动显示旗帜(60+ 国家)
- 重新排序 — 拖拽或使用箭头按钮设置显示顺序
- 证书 — 查看并复制节点 SSL 证书用于远程配置
- 在线时长追踪 — 每个节点的历史在线时长百分比
主机与高级 TLS 设置
每个 Xray 入站都有一行或多行主机配置,告诉订阅渲染器在客户端配置中应输出什么地址、端口和 TLS 选项。每个主机的完整字段集如下:
| 字段 | 用途 |
|---|---|
| Remark(备注) | 客户端 App 中显示的名称 |
| Address(地址) | 客户端连接的服务器域名或 IP |
| Port(端口) | 覆盖入站的监听端口 |
| SNI / Host | TLS 服务器名称指示(SNI)和 HTTP Host 头 |
| Security / ALPN / Fingerprint | TLS 配置:none / tls / reality;h2/http1.1;Chrome/Firefox/Safari uTLS |
| Allow Insecure(允许不安全) | 跳过 TLS 证书验证(仅在 CDN 后端、证书不暴露时使用) |
| Country code(国家代码) | ISO 3166-1 alpha-2 — 驱动区域化订阅重排序 |
| Allowed / Denied Admins(允许/拒绝的管理员) | 将主机限定给特定子管理员(留空 = 所有管理员) |
ECH(Encrypted Client Hello)
ECH 对被动观察者隐藏 SNI——TLS 握手扩展会用一个发布在 DNS 中的公钥加密。逐主机启用:开启 ECH 并粘贴来自你 CDN/DNS 提供商的 ECHConfig 数据块。需要支持 ECH 的客户端(Happ、Chrome 117+)。
TLS 分片
将 TLS ClientHello 切分成更小的 TCP 分段,绕过对首包的 DPI 特征匹配。在存在基于 SNI 的封锁但无法使用 CDN 时采用。
- 分片大小 — 每个分片的字节数,例如
100-200(随机区间) - 分片延迟 — 分片之间的毫秒数,例如
10-20
TLS 记录分片
在 TLS 记录层而非 TCP 层进行分片。比 ClientHello 分片更激进;在标准 TLS 分片仍被指纹识别时采用。
噪声设置(Noise Settings)
在真正的 TLS 握手之前注入随机噪声数据包,以挫败基于流量的指纹识别。JSON 字段:
[{"type": "rand", "packet": "10-50", "delay": "5-10"}]
类型 rand 发送随机字节;类型 str 发送字面量十六进制字符串。数据包大小和延迟均接受区间记法。
随机 User-Agent
在每次请求时随机化 HTTP User-Agent,以避免在 WS/HTTP 传输上被客户端指纹识别。
会话
监控并管理活跃的设备连接:
- 活跃会话 — 查看当前所有已连接的设备
- 按用户查看会话 — 查看某个特定用户正在使用哪些设备
- 断开连接 — 强制终止单个会话
- IP 历史 — 按 IP 追踪用户的连接历史
数据分析
全面的数据分析面板,包含:
- 汇总 — 用户总数、活跃连接、带宽、收入概览
- 协议分布 — 按协议(VMess、VLESS 等)划分的用量明细
- 节点负载 — 每个节点的连接数和带宽用量
- 节点在线时长 — 24 小时、7 天、30 天周期内的在线时长百分比
- 消耗大户 — 带宽消耗最高的用户
- 即将到期用户 — 在可配置天数内即将到期的用户
管理员管理
基于角色的管理员系统,分为三个等级:
| 角色 | 权限 |
|---|---|
| Owner(业主) | 完全访问:管理管理员、节点、系统设置、所有用户 |
| Admin(管理员) | 管理(全部)用户、查看节点和数据分析、有限的设置 |
| Reseller(分销商) | 仅管理自己的用户,受 max_users 和 max_traffic_bytes 配额限制 |
每个管理员都可以设置配额:
max_users— 管理员可创建的最大用户数max_traffic_bytes— 其所有用户的总流量配额
设置
- 双因素认证 — 在设置页启用/禁用 TOTP 2FA
- Xray 核心配置 — 在双栏布局中编辑原始 Xray JSON(左侧编辑器,右侧实时日志与状态)
- 环境变量编辑器 — 内联编辑 SMTP、令牌、功能开关,并带密钥掩码;保存并重启会让面板自我重启
- Hysteria2 — 在设置页管理 hy2 入站(Standard 及以上)
- 授权信息 — 等级、剩余天数、当前与最大用户数/节点数
用户组
用户组(在 Remnawave 中称为 Squads)让你对用户进行分组,以控制入站可见性和订阅覆盖。Pro 授权,仅限 sudo。
每个组可以执行以下任意或全部操作:
- 入站过滤(
applies_to_inbounds)— 入站标签的 CSV。组内用户只会获得匹配入站的订阅条目。留空 = 所有入站。 - 模板覆盖(
override_template_id)— 为该组成员使用不同的订阅模板。 - 主机覆盖(
override_hosts)— 向成员订阅中注入不同的主机行(例如给某个 VIP 组一个对其他人隐藏的直连 IP 主机)。
可在用户详情页或通过 API 将用户加入某个组。一个用户最多只能属于一个组。
# 列出组 curl /api/v1/user-groups -H "Authorization: Bearer TOKEN" # 创建一个仅获得 hy2 + VLESS-Reality 入站的 VIP 组 curl -X POST /api/v1/user-groups \ -H "Authorization: Bearer TOKEN" \ -H "Content-Type: application/json" \ -d '{"name":"VIP","applies_to_inbounds":"hy2-main,vless-reality"}' # 将用户加入组 curl -X POST /api/v1/user-groups/1/members \ -d '{"username":"alice"}' -H "Authorization: Bearer TOKEN"
入站集合
入站集合是一组带名称的入站标签 CSV,你可以将其分配给某个节点。当节点拥有一个入站集合时,该节点上只会激活这些入站——其余的都会被抑制。用它来为每个节点运行不同的协议组合:例如节点 A 用 VLESS+Trojan,节点 B 用 VLESS+hy2。
Pro 授权,仅限 sudo。
# 创建一个入站集合 curl -X POST /api/v1/inbound-sets \ -H "Authorization: Bearer TOKEN" \ -H "Content-Type: application/json" \ -d '{"name":"UDP nodes","tags":"hy2-main,vmess-ws"}' # 分配给某个节点(在节点上设置 inbound_set_id) curl -X PUT /api/v1/node/1 \ -d '{"inbound_set_id": 2}' -H "Authorization: Bearer TOKEN"
订阅响应规则
订阅规则让你根据用户的客户端来定制其订阅响应的样式。规则匹配请求属性并应用一个动作。
| 匹配字段 | 运算符 | 动作 |
|---|---|---|
user_agent | equals / contains / regex | template / status / headers |
client_os | equals / contains / regex | template / status / headers |
示例:
- 匹配
user_agent contains "Happ"→ 动作template = happ-custom— 向 Happ 客户端提供针对 Happ 优化的模板 - 匹配
client_os equals "iOS"→ 动作headers = {"Content-Type": "text/plain"} - 全局规则(仅限 sudo,
admin_id = NULL)对所有用户生效,无论这些用户归哪个管理员所有
规则按 priority 升序求值。首个匹配者生效。
# 创建一条规则:向 Karing 客户端提供 sing-box 模板 curl -X POST /api/v1/sub-rules \ -H "Authorization: Bearer TOKEN" \ -H "Content-Type: application/json" \ -d '{"name":"Karing","match_field":"user_agent","match_op":"contains", "match_value":"Karing","action":"template","action_arg":"singbox-default"}'
Webhook
NexusPanel 会向你注册的任意 URL 投递签名过的 HTTP POST 事件。每次投递都包含一个 X-Nexus-Signature 头——即用你端点密钥对请求体做的 HMAC-SHA256。
事件范围
| 范围 | 事件 |
|---|---|
user.* | user.created、user.updated、user.deleted、user.expired、user.disabled、user.data_used_reset |
node.* | node.connected、node.disconnected、node.reconnecting |
service.* | service.started、service.stopped |
billing.* | billing.renewed、billing.expired |
errors.* | errors.cert_expired、errors.xray_crash |
hwid.* | hwid.mismatch、hwid.reset |
将范围留空即可接收所有事件。投递失败时以指数退避重试;超过最大尝试次数后,该事件被标记为失败并丢弃。
# 注册一个端点 curl -X POST /api/v1/webhooks \ -H "Authorization: Bearer TOKEN" \ -H "Content-Type: application/json" \ -d '{"url":"https://my-server/hook","scopes":"user.*,node.*"}' # 响应中包含 secret(仅显示一次) # 发送一次测试投递 curl -X POST /api/v1/webhooks/1/test -H "Authorization: Bearer TOKEN" # 在你的处理程序中验证签名(Python 示例) # expected = hmac.new(secret, body, sha256).hexdigest() # assert expected == request.headers["X-Nexus-Signature"]
WEBHOOK_ADDRESS(以逗号分隔的 URL)和 WEBHOOK_SECRET 仍可作为静态环境变量替代方案使用。新部署请使用控制面板界面——它支持按端点设置密钥、范围和投递历史。
客户端页
控制面板 → 客户端 展示一份精选的推荐 VPN 客户端列表,附带平台徽章、下载链接和使用说明。运营者可将此页面 URL 分享给最终用户。
| 客户端 | 平台 | 说明 |
|---|---|---|
| Happ | iOS / macOS / Windows / Android | 推荐 — 原生订阅 URL、HWID 绑定、离线缓存 |
| v2RayTun | iOS / macOS / Android | 热门 iOS 客户端,支持 VLESS-Reality |
| Karing | 全平台 | 基于 Sing-box,跨平台体验出色 |
| Shadowrocket | iOS | 美区 App Store 售价 $2.99 — 极其稳定的 iOS 客户端 |
| V2rayNG | Android | 经典 Android 客户端 |
| FlClashX | Windows / macOS / Linux / Android | 兼容 Mihomo/Clash |
| Streisand | iOS / macOS | 支持自定义 JSON — 设置 USE_CUSTOM_JSON_FOR_STREISAND=true |
授权系统
NexusPanel 使用一个中央授权服务器(nexuspanel.store)来验证安装并推送更新。这就是客户分级、计费和保持更新的方式。
心跳如何工作
- 面板每 6 小时调用一次授权服务器上的
POST /api/validate,附带其license_id、client_id和完整遥测数据(面板版本、Xray 版本、主机名、操作系统、IP、用户总数/活跃数、节点总数/活跃数、总流量、运行时长)。 - 授权服务器存储这些数据并回复
{tier, expires_at, latest_version, update_available, docker_image}。 - 如果
update_available为 true 且启用了AUTO_UPDATE(默认),面板会在后台运行docker compose pull && docker compose up -d --force-recreate— 你无需做任何事。
等级
| 等级 | 价格 | 用户 | 节点 | 时长 |
|---|---|---|---|---|
| Trial(试用) | 免费 | 无限 | 无限 | 14 天 |
| Standard(标准) | $10/月 | 无限 | 10 | 30 天/月 |
| Pro(专业) | $30/月 | 无限 | 无限 | 30 天/月 |
试用版
无需信用卡、无需注册——打开 Telegram 机器人输入 /start,即可获得一个免费 14 天试用授权:无限用户、无限节点,可直接使用控制面板核心功能,足以在真实流量上进行评估。
标准版 — $10/月
面向运营线上服务的运营者。用户数无限,最多 10 个节点,并解锁:
- 所有节点上的 Hysteria 2 协议
- 批量操作(一次性启用/禁用/重置/删除数百个用户)
- 用于自动化和集成的 API 访问
- 多月计费(3/6/12 个月分别享 5%/10%/15% 折扣)
专业版 — $30/月
包含标准版的全部功能,外加无节点上限和完整功能集:
- 跨任意数量国家的无限节点
- ECH(Encrypted Client Hello)— 对 DPI 隐藏 SNI
- Finalmask — 抗指纹识别的传输层
- 白标品牌定制(自定义面板域名 + logo)
- 用于分销商分级的用户组与入站集合
- 带自动生成 iptables 规则的中转服务器中继
- 优先支持
功能对比
| 功能 | 试用 | 标准 | 专业 |
|---|---|---|---|
| 最大用户数 | 无限 | 无限 | 无限 |
| 最大节点数 | 无限 | 10 | 无限 |
| 时长 | 14 天 | 30 天/月 | 30 天/月 |
| 所有协议(VLESS、VMess、Trojan、SS) | ✓ | ✓ | ✓ |
| Hysteria 2 | ✓ | ✓ | ✓ |
| Grafana 风格数据分析 | ✓ | ✓ | ✓ |
| 实时会话视图 | ✓ | ✓ | ✓ |
| 审计日志 | ✓ | ✓ | ✓ |
| Webhook | — | ✓ | ✓ |
| 运营者 CLI | ✓ | ✓ | ✓ |
| 批量操作 | — | ✓ | ✓ |
| API 访问 | — | ✓ | ✓ |
| ECH + Finalmask | — | — | ✓ |
| 白标品牌定制 | — | — | ✓ |
| 用户组与入站集合 | — | — | ✓ |
| 中转服务器中继 | — | — | ✓ |
购买授权
在 Telegram 上打开 @nexuspanelpayment_bot。点击 View Plans,选择一个等级,选择时长(1/3/6/12 个月,折扣递增),选择一种加密货币(USDT TRC20、BTC、ETH、LTC、TRX 以及其他 200+ 种),并向显示的钱包发送所示的精确金额。一旦 NOWPayments 确认,机器人就会发给你 License Key 和 Client ID。
宽限期
如果你的授权过期,面板会以宽限模式继续运行 72 小时,让你可以在不中断服务的情况下续期。此后 API 将切换为只读,直到恢复一个有效授权为止。
IP 与设备限制的强制执行
NexusPanel 通过解析 Xray 访问日志,实时强制执行每个用户的 IP 和设备限制——而不仅仅是在订阅导入时。这正是让 ip_limit 和 device_limit 真正生效的机制。
它如何工作
- Xray 为每个被接受的连接向
$XRAY_ACCESS_LOG写入一行。 enforce_limits任务每 60 秒运行一次,跟踪读取日志(带偏移量跟踪、感知轮转),并从最近LIMIT_WINDOW_SECONDS(默认 600 = 10 分钟)内提取(user_id, client_ip)对。- 对每个用户,统计唯一 IP 数量。如果该数量超过
ip_limit(若未设置ip_limit则用device_limit),且该用户当前为active,且ip_limit_mode == "limit",则该用户被切换为limited状态。 - 所有出现过的 IP 都会被写入
user_ip_history。可通过GET /api/v1/user/{username}/ips查看每个用户的 IP。
所需的 xray 配置
默认安装会自动启用此功能。对于已有安装,面板会在启动时自动修补你的 xray_config.json 以添加访问日志路径。手动配置:
{
"log": {
"loglevel": "warning",
"access": "/var/lib/panel/xray-access.log"
}
}
可调参数
| 环境变量 | 默认值 | 用途 |
|---|---|---|
XRAY_ACCESS_LOG | /var/log/xray/access.log | Xray 访问日志文件路径 |
LIMIT_WINDOW_SECONDS | 600 | 统计唯一 IP 的滚动时间窗 |
LIMIT_ENFORCE_INTERVAL | 60 | 强制执行任务的运行频率(秒) |
备份
NexusPanel 通过 backup APScheduler 任务,每天在 03:00 UTC 自动进行一次数据库备份。
备份存放在哪里
- 本地文件:
/var/lib/panel/backups/backup_YYYYMMDD_HHMMSS.sqlite3(PostgreSQL 则为.sql) - 保留最近 7 份备份;更旧的会被自动清理
- 如果配置了
TELEGRAM_API_TOKEN和TELEGRAM_ADMIN_ID,每份备份还会作为文档推送到你的 Telegram,从而拥有一份服务器外的副本
手动备份
# SQLite docker exec nexus-panel cp /var/lib/panel/db.sqlite3 /var/lib/panel/backups/manual.sqlite3 # 或直接从宿主机抓取该文件 cp /var/lib/panel/db.sqlite3 ~/panel-backup-$(date +%F).sqlite3
恢复
- 停止面板:
cd /opt/panel && docker compose down - 替换数据库文件:
cp /path/to/backup.sqlite3 /var/lib/panel/db.sqlite3 - 重启:
docker compose up -d
BACKUP_DIR — 备份的写入位置(默认 /var/lib/panel/backups)BACKUP_RETENTION — 保留多少份最近备份(默认 7)
加密 Happ 订阅
控制面板中每个用户的 "H" 按钮会使用 RSA-4096 PKCS1v15 和 Happ 的官方公钥,生成一条真正的 happ://crypt4/<base64> 深链。一旦添加到 Happ 客户端,用户便无法查看、编辑或分享其底层订阅 URL。
长度超过 501 字节(RSA-4096 + PKCS1v15 的限制)的订阅 URL,会自动回退到普通的 happ://add/<base64> 格式。
Run Your Business
Your First Customer
- Dashboard → Users → Add User.
- Give them a username, pick an expiry date and a data limit (or leave both unlimited), and pick which protocols they get.
- Save — the panel generates their subscription link immediately.
- Send them the link. They paste it into a client app and they're connected.
Everything here is also available over the Users API for automation.
Device & IP Limits
Device and IP limits (see how enforcement works) aren't just an anti-abuse tool — they're a pricing lever: sell a Personal plan at 1–2 devices, a Family/Team plan at 4–6, and an Unlimited plan at 0 (off) for a premium price.
Set device_limit (or ip_limit) per user. Customers who exceed it are flipped to limited automatically.
Admins & Resellers
Give anyone selling under you their own admin login instead of sharing yours — see Admin Management. Owner sees everything; Admin manages users only; Reseller manages only their own users, capped by max_users and max_traffic_bytes.
Self-Service via Telegram
Once the Telegram bot is connected, customers check usage (/usage), re-fetch their link (/sub), and see connected devices (/devices) without messaging you.
Pricing Your Service
NexusPanel doesn't set your prices. Factor in your costs (VPS, nodes, your NexusPanel license), your differentiation (device slots, node locations, support), and your market. Collect payment however suits you, including a storefront that calls the Users API to provision accounts automatically.
节点
什么是节点
节点是一台运行 Xray 核心、并连回你 NexusPanel 实例的远程服务器。节点让你能够把代理出口分布在多台服务器和多个地理位置,同时从单一控制面板管理一切。
面板通过使用双向 TLS 的安全 gRPC 连接与节点通信。用户配置和流量数据都流经这条通道。
安装节点
控制面板 → 节点 → 添加新节点 会打开一个带两个标签页的窗口——根据面板能否通过 SSH 访问节点服务器,选择合适的方式。
Auto install(推荐)
粘贴一台全新 VPS 的 IP 和 SSH 登录信息(root 密码或私钥),面板会完成剩下的全部工作:通过 SSH 连接、安装 Docker 和已内嵌 mTLS 证书的节点代理、注册节点,并等待其连接成功。全程无需自己复制或运行任何命令——SSH 密码/密钥仅使用一次,且不会被保存。
Manual(备用方案——面板无法通过 SSH 连接节点时使用)
Manual 标签页会改为生成一条已内嵌面板证书、可直接粘贴的命令。无需手动写入证书文件。
- 控制面板 → 节点 → 添加新节点 → Manual 标签页
- 点击 复制安装命令 — 该命令已包含证书、端口、API 端口和面板地址
- 粘贴并在节点服务器上运行
- 在面板中输入节点的 IP 和端口 → 添加节点
curl -sL https://nexuspanel.store/install-node | bash -s -- \ --port 62060 \ --api-port 62061 \ --panel-url 'https://panel.example.com:8443' \ --cert-b64 '<base64-cert>'
安装程序会自动等待 apt/dpkg 锁——可安全地在刚开通的 VPS 上运行。不要省略 --panel-url:缺少它会导致该节点上的 Hysteria 2 认证保持禁用,直到你之后手动设置。
证书与端口
NexusNode 使用面板的签名证书向面板进行身份认证:
- 面板连接端口:
62060 - Xray API 端口:
62061 - 证书 CN:
Panel— 节点配置中的ssl_target_name必须与之匹配 - 证书从
GET /api/v1/node/settings获取一次(或由安装命令直接内嵌),并存储在/var/lib/nexus-panel-node/ssl_client_cert.pem
节点的 Docker Compose
这是安装程序在 /opt/nexus-panel-node/docker-compose.yml 实际生成的文件——供你手动调整时参考:
services: node: image: ghcr.io/haitovs/nexus-node:latest container_name: nexus-panel-node restart: always network_mode: host environment: SERVICE_PORT: 62060 XRAY_API_PORT: 62061 SSL_CERT_FILE: /var/lib/nexus-panel-node/ssl_cert.pem SSL_KEY_FILE: /var/lib/nexus-panel-node/ssl_key.pem SSL_CLIENT_CERT_FILE: /var/lib/nexus-panel-node/ssl_client_cert.pem # Hysteria2 边车 — 留空则禁用,直到提供 --panel-url PANEL_HY2_AUTH_URL: "https://panel.example.com:8443/api/v1/hy2-auth" volumes: - /var/lib/nexus-panel-node:/var/lib/nexus-panel-node - /etc/hysteria:/etc/hysteria
network_mode: host 意味着没有 Docker ports: 映射——节点直接在宿主机上绑定所有端口(服务端口、API 端口,以及用户实际连接的每一个 Xray/Hysteria inbound)。
多个节点
要在不同地区添加节点:
- 使用生成的一行命令在每台服务器上安装节点服务
- 在面板中,用每个节点的公网 IP 和端口添加它
- 分配一个国家旗帜 — 同时驱动可视化网格和区域化订阅重排序
- 拖放以设置网格中的显示顺序
- 为每个节点设置一个用量系数(例如
1.5表示流量按 1.5× 计算)
CF-IPCountry(Cloudflare)或本地 MaxMind 数据库检测。在每一行主机上设置 country_code 即可激活。
节点故障排查
| 问题 | 解决方案 |
|---|---|
| 节点显示"离线" | 检查防火墙是否允许来自面板的 TCP 62060;验证 /var/lib/nexus-panel-node/ssl_client_cert.pem 中的证书 |
| 连接被拒绝 | 确认 Docker 容器正在运行:docker compose ps |
| 证书错误 | 从面板重新复制证书(GET /api/v1/node/settings);验证 ssl_target_name = Panel |
| 高延迟 | 检查面板与节点之间的网络路由;确保已设置 BBR 拥塞控制 + 64 MB 套接字缓冲区 |
| 用户无法通过节点连接 | 验证节点防火墙上的代理端口(443、80 等)已对最终用户开放 |
API 参考
所有 API 端点都在 /api/v1/ 之下。设置 DOCS=true 并访问 /docs 即可启用交互式 Swagger UI。
身份认证
通过提交凭据获取 JWT 访问令牌:
/api/v1/admin/tokencurl -X POST https://panel.example.com:8443/api/v1/admin/token \ -d "username=admin&password=admin&grant_type=password" # 响应: # {"access_token": "eyJ...", "token_type": "bearer"} # 在后续请求中使用该令牌: curl -H "Authorization: Bearer eyJ..." https://panel.example.com:8443/api/v1/system
如果该管理员启用了 2FA,请在 X-TOTP-Code 头中包含 TOTP 验证码。
POST /api/v1/admin/2fa/setup — 生成 TOTP 密钥 + 恢复码POST /api/v1/admin/2fa/enable — 验证验证码并激活 2FAPOST /api/v1/admin/2fa/disable — 停用 2FA
用户
/api/v1/user创建一个带协议、流量额度、到期、设备限制和 IP 限制的新用户。
/api/v1/users列出所有用户。对非 sudo 账户会自动按管理员限定作用域。
/api/v1/user/{username}获取详细的用户信息,包括用量统计和订阅链接。
/api/v1/user/{username}更新用户字段(流量额度、到期、状态、协议等)。
/api/v1/user/{username}永久删除一个用户及其所有关联数据。
批量操作
/api/v1/users/bulk/update/api/v1/users/bulk/delete/api/v1/users/bulk/reset导出
/api/v1/export/users将所有用户下载为 CSV 文件。
/api/v1/export/subscription-links将所有订阅链接导出为纯文本。
管理员
/api/v1/admin创建一个带角色(owner、admin、reseller)、max_users 和 max_traffic_bytes 的新管理员。
/api/v1/admins列出所有管理员账户。
节点
/api/v1/inbounds列出所有协议入站。
/api/v1/hosts获取主机配置(仅限 sudo)。
数据分析
/api/v1/analytics/summary控制面板概览统计。
/api/v1/analytics/protocols协议分布明细。
/api/v1/analytics/nodes/load每个节点的连接数和带宽。
/api/v1/analytics/nodes/uptime节点在线时长百分比。
/api/v1/analytics/users/expiring?days=30在指定天数内即将到期的用户。
/api/v1/analytics/users/top?limit=10按带宽消耗排名的消耗大户。
会话
/api/v1/sessions/active?hours=24最近 N 小时内的活跃设备会话。
/api/v1/sessions/user/{username}某个特定用户的会话。
/api/v1/sessions/{session_id}强制断开一个设备会话。
系统
/api/v1/system系统统计,包括 CPU、内存和带宽。非 sudo 管理员对敏感指标看到的是清零值。
/api/v1/health健康检查端点,返回数据库和 Xray 核心状态。
/metricsPrometheus 兼容的指标端点。需要 METRICS_ENABLED=true 和用于认证的 METRICS_TOKEN。
DOCS=true,并访问 http://your-panel/docs 查看交互式 Swagger UI。
Telegram 机器人
配置
- 打开 Telegram 并给 @BotFather 发消息
- 发送
/newbot并按提示创建你的机器人 - 复制机器人令牌(例如
123456789:AAAA...) - 获取你的 Telegram 用户 ID(给 @userinfobot 发消息)
- 添加到你的
.env:
TELEGRAM_API_TOKEN="123456789:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" TELEGRAM_ADMIN_ID="987654321" TELEGRAM_LOGGER_CHANNEL_ID=-1001234567890
添加令牌后重启面板。机器人将自动启动。
机器人命令
| 命令 | 说明 |
|---|---|
/usage | 查看流量用量和剩余额度 |
/sub | 获取订阅链接和二维码 |
/stats | 面板统计(仅限管理员) |
/devices | 查看已连接的设备 |
/help | 列出所有可用命令 |
/broadcast | 向所有用户发送消息(仅限管理员) |
通知设置
配置后,Telegram 机器人会针对各类事件发送通知。通过 .env 变量逐项控制每种通知类型(参见通知配置)。
通知会发送至:
- 管理员 ID — 直接私信给
TELEGRAM_ADMIN_ID中的每个管理员 - 日志频道 — 所有事件发送至
TELEGRAM_LOGGER_CHANNEL_ID
创建 / 修改提醒中包含的字段
当用户上设置了以下字段时,"用户已创建"和"用户已修改"通知会包含它们:
| 字段 | 显示为 | 何时包含 |
|---|---|---|
| 用户名 | Username: alice | 始终 |
| 流量额度 | Traffic Limit: 50 GB | 始终(未设置时显示 "Unlimited") |
| 到期日期 | Expire Date: 2026-06-01 | 始终(未设置时显示 "Never") |
| 协议 | Proxies: vless, trojan | 始终 |
| 流量额度重置 | Data Limit Reset Strategy: monthly | 始终 |
| 设备限制 | Device Limit: 3 | 仅当 > 0 时 |
| IP 限制 | IP Limit: 5 (limit) | 仅当 > 0 时;模式内联显示 |
| HWID 限制 | HWID Limit: 2 | 仅当 > 0 时 |
| 有后续方案 | Has Next Plan: True | 始终 |
| 备注 | Note: Paid in advance 6mo | 仅当非空时;超过 120 字符会被截断 |
DISCORD_WEBHOOK_URL 即可在 Discord 频道中收到相同的通知。Discord 嵌入消息包含同样丰富的字段。
订阅分发渠道
通过审查者无法封锁的基础设施来分发订阅 URL。
当你的面板域名在俄罗斯、伊朗、中国或土库曼斯坦被封锁时,客户就拉不到他们的订阅更新。订阅分发渠道通过把每个用户的配置发布到 Google / Cloudflare / GitHub / Telegram 基础设施上的一个静态文件来解决这个问题——这些主机名审查者无法一刀切地封锁,否则会破坏数以百万计用户在用的主流应用。
它如何工作
- 你在 设置 → 订阅分发渠道 中配置一个或多个渠道。
- 每个用户在该渠道上获得一个稳定的公开 URL(例如
https://firebasestorage.googleapis.com/…?alt=media&token=…)。 - 用户表中每一行用户上的 ⊞(网格)图标会打开一个弹层,列出所有可用 URL——直连、Happ 加密以及每个已配置的渠道。两次点击即可复制或显示二维码。
- 当你编辑主机或 Xray 配置时,面板会通过后台工作进程,在约 10–30 秒内自动把所有活跃用户重新发布到 Firebase(及其他渠道)。常规配置编辑后无需手动回填。
可用渠道
| 渠道 | 提供方 | 免费额度 | 最适合 |
|---|---|---|---|
| Firebase Storage | Spark 方案约 5 万次轮询/天 | 主要的反审查渠道 | |
| Firebase Hosting | 与 Storage 相同的 Spark 方案 | 同一 Google 项目下的第二个 Firebase 出口(*.web.app)——不同的 SNI 和边缘 CDN,Storage 被封锁时仍可访问。发布是整站级别的,不是按用户,因此是批量更新而非每次编辑都发布。 | |
| Cloudflare R2 | Cloudflare | 10 GB/月,无出口费用 | 次要渠道;与 Firebase 不同的供应商 |
| GitHub Gist | GitHub / Microsoft | 无限公开 gist | 低保真回退;极其耐用 |
| GitLab Snippet | GitLab | 无限公开 snippet | 即使在土库曼斯坦的重度封锁窗口期也确认可达——作为 Firebase 无法访问时的第二镜像 |
| Telegram 分发 | Telegram | 免费 | 当其他一切都失效时的应急分发 |
| Nginx 代理池 | 你的 VPS | VPS 的成本 | 对中继拥有完全的运营者控制权 |
Firebase Storage
推荐的首个渠道。免费额度可覆盖约每天 5 万次订阅轮询。托管在 Google 的 IP 段上——审查者无法一刀切封锁,否则会破坏 Google Maps、Gmail 以及无数其他应用。
在 console.firebase.google.com 进行一次性配置
- 创建项目 — Add project → 命名(例如
nexus-subs)→ Spark 方案(免费)→ Create。 - 启用 Storage — Build → Storage → "Get started" → "Start in production mode" → 选择地区 → Done。
- 设置存储规则 — Storage → Rules → 替换为:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /sub_{file=**} {
allow read: if true;
allow write: if false;
}
}
}
- 生成服务账号密钥 — Project Settings(⚙)→ Service accounts → "Generate new private key" → Download。请当作密码一样对待。
- 查找存储桶名称 — Storage → 顶部会显示
gs://your-project.firebasestorage.app。复制gs://之后的部分。
在面板中
- 设置 → 订阅分发渠道 → Firebase Storage → ⚙
- 粘贴存储桶名称和服务账号 JSON(整个文件内容)
- 开启启用,设置优先级(数值越小越优先;
10是个不错的起点) - 保存 → 点击测试(刷新图标)
读懂测试结果
一次通过的测试看起来是这样:
firebase: end-to-end OK in 1840ms ✓ creds (180ms): bucket reachable ✓ upload (650ms): published to https://firebasestorage.googleapis.com/… ✓ fetch (820ms): GET 200 (87 bytes, attempt 1) ✓ match (1ms): content matches ✓ cleanup (180ms): test blob deleted
| 失败的步骤 | 可能原因 | 解决办法 |
|---|---|---|
creds | 服务账号 JSON 错误或已过期 | 在 Firebase 控制台重新生成密钥 |
upload | 未启用 Storage 或规则有误 | 重新检查配置步骤 2–3 |
fetch | 公开读取规则未生效 | 重新粘贴步骤 3 中的规则 |
match | 边缘缓存提供了陈旧的数据块(罕见) | 通常重试会掩盖此问题;若持续出现请提 bug |
cleanup | 服务账号为只读 | 手动删除 nexus_test_* 数据块 |
应用到现有用户
测试通过后,点击订阅分发渠道卡片底部的回填。这会立即通过后台工作进程为所有活跃用户分发 Firebase 上传。对于 200 个用户,预计需要 30–120 秒完成。
Cloudflare R2
兼容 S3 的对象存储,无出口费用。作为 Firebase 之外的次要渠道使用——不同的供应商意味着针对其中一个的特定地区封锁不会同时拖垮两个。
在 dash.cloudflare.com 配置
- R2(左侧栏)→ Create bucket → 命名(例如
nexus-subs)。 - 打开存储桶 → Settings → Public access → 启用。复制
https://pub-<id>.r2.devURL。 - R2 页面右上角 → Manage R2 API tokens → Create token → Object Read & Write(限定到你的存储桶)→ 保存 Access Key ID + Secret。
- 你的 Account ID 是 R2 控制面板页面右下角的 32 位十六进制字符。
在面板中
设置 → 订阅分发渠道 → Cloudflare R2 → ⚙:
| 字段 | 在哪里找到 |
|---|---|
| Cloudflare account ID | 步骤 4 中的 32 位十六进制 |
| Bucket name | 例如 nexus-subs |
| Access key ID | 来自步骤 3 |
| Secret access key | 来自步骤 3(仅显示一次) |
| Public URL base | 步骤 2 中的 https://pub-<id>.r2.dev |
pub-<id>.r2.dev 主机名享有与 Firebase 相同的反封锁优势——它与成千上万个其他 R2 存储桶共享。
GitHub Gist
免费、由 GitHub 托管(Microsoft 的 IP)。极其耐用——一个不花钱的优质低优先级回退选项。
配置
- github.com/settings/tokens → Personal access tokens → Tokens (classic) → Generate new token。
- 名称:
nexus-gists。范围:仅勾选 gist。有效期:1 年(在日历上记下续期)。 - 复制
ghp_…令牌——你无法再次看到它。
在面板中
设置 → 订阅分发渠道 → GitHub Gist → ⚙ → 粘贴 PAT → 保存 → 测试。
Telegram 分发
恰恰在其他渠道不可用的那些时间窗里,它在 IR/RU/TM 仍可访问。这是"面板着火了、用户别无他法"的回退渠道。
t.me/<bot>?start=sub_<token> 深链,而非自更新 URL。他们点击一次,机器人就私信给他们一个含其配置的 .txt 文件。只有在你已接好机器人的 /start 处理程序时,才把优先级设得非常高(优先级数值很小)——否则它会指向一个不回复的机器人。
配置 — 专用机器人(推荐)
- 在 Telegram 上给
@BotFather发消息 →/newbot→ 取一个名称和用户名(必须以bot结尾)。 - 复制 BotFather 给你的令牌。
- 设置 → 订阅分发渠道 → Telegram → ⚙:
- 机器人用户名:不带 @
- 机器人令牌:从 BotFather 粘贴
- 保存 → 测试。测试会调用
getMe并断言返回的用户名与你粘贴的一致。
如果你已在 .env 中为通知分发设置了 TELEGRAM_API_TOKEN,可以把机器人令牌字段留空——该渠道会回退到使用那个环境变量。出于安全考虑不推荐这样做:泄露的通知机器人令牌也会暴露订阅文件。
Nginx 代理池
当静态存储渠道全部宕机或被特定地区封锁时,回退到你自己那批便宜的中继 VPS。池中每台主机都拥有自己的域名;面板按权重把用户分配到各主机。
预先开通
开通一些便宜的 VPS(Hetzner CCX13 / Contabo / 等——每台 €4–5/月)。在每台上:
# 在每台全新的代理主机上以 root 运行 curl -sSL https://your-panel.tld/setup_proxy.sh | bash
在面板中
设置 → 订阅分发渠道 → Nginx-proxy → ⚙。配置为 JSON:
{
"hosts": [
{ "host": "alpha.shop", "subscription_path": "sub", "weight": 1 },
{ "host": "beta.shop", "subscription_path": "sub", "weight": 1 },
{ "host": "gamma.shop", "subscription_path": "sub", "weight": 5 }
]
}
weight: 5 的主机分到的用户份额是 weight: 1 主机的 5 倍。保存 → 测试会为每个池成员验证 TLS 握手。
订阅分发渠道 — 控制面板界面
订阅弹层(按用户)
用户表中的每一行都有一个 ⊞(网格)图标。点击它会打开一个弹层,列出运营者可以交给客户的每一个 URL:
| 行 | 它是什么 | 复制 + 二维码 |
|---|---|---|
| Direct(直连) | 由面板提供的普通 /sub/<token> URL | 仅复制 |
| Happ(加密) | 经 /user/<u>/encrypt-sub 的 AES-256-CBC 加密形式 | 仅复制 |
| Firebase / R2 / Gist | 来自已启用渠道的静态存储 URL | 复制 + 二维码 |
| Telegram | 指向机器人分发的深链 | 仅复制 |
| Nginx-proxy | 中继 URL | 仅复制 |
弹层打开时 URL 已预先取好,因此复制对手势操作很安全——点击与写入剪贴板之间没有异步延迟。
渠道健康徽章
设置 → 订阅分发渠道 中的每个渠道行,都会显示来自上一次探测的健康徽章。定时任务每 15 分钟运行一次。可随时用测试按钮强制刷新一次探测。
配置变更时自动重新发布
编辑主机或 Xray 核心配置会触发一次自动扇出:所有订阅内容发生变化的活跃用户会在约 10–30 秒内被重新发布到每个已配置的渠道。工作进程会跳过渲染后配置未变化的用户(基于内容哈希的短路判断),所以一次只影响 200 个用户中 50 个的主机编辑,只会产生 50 次 Firebase 写入。
回填
回填按钮(在订阅分发渠道卡片底部)会立即把所有活跃用户上传到所有已启用的渠道。在新增一个渠道后用它一次即可——此后,自动重新发布会让一切保持最新。
Hysteria2
Hysteria2 是一种基于 QUIC/UDP 的协议,在丢包严重的最后一公里网络(移动网络、独联体 4G、伊朗)上,吞吐量可达 TCP 的 3–5×。它作为一个独立守护进程与 Xray 并行运行 — 而非作为 Xray 入站 — 因为 Xray-core 并不原生支持 hysteria2 协议。
授权门槛:Standard 及以上。试用等级可以看到 hy2 订阅条目,但无法创建或管理入站。
2053)在你主机服务商的控制面板中已开放——Contabo、Aeza、PTR 默认都会拦截 UDP。
添加 Hysteria2 入站
控制面板 → 设置 → Hysteria2 → 添加入站
| 字段 | 值 | 备注 |
|---|---|---|
| Tag(标签) | hy2-main | 任意唯一名称 |
| Listen port(监听端口) | 2053 | UDP — 必须在防火墙中开放 |
| Obfs type(混淆类型) | salamander | 推荐 — 在 CN/IR/RU 对 DPI 隐藏 UDP |
| Obfs password(混淆密码) | 强随机值 | openssl rand -hex 24 |
| Masquerade URL(伪装 URL) | https://www.bing.com | hysteria 在面对 DPI 探测时伪装成的 HTTPS 站点 |
| SNI | bing.com | 向客户端呈现的 TLS SNI |
| TLS 证书 / 密钥 | 留空则自动 | 若省略,面板会自动生成一张 10 年期自签名证书 |
创建入站会把配置同步到每个已连接的节点,并在每个节点上启动 hysteria 守护进程。无需 SSH。
为每个节点添加主机
控制面板 → 主机 → 点击 Hysteria2 入站卡片 → 添加主机
为你想要暴露 hy2 的每个节点添加一行主机:
| 字段 | 示例 | 必填 |
|---|---|---|
| Remark(备注) | DE Frankfurt hy2 | 是 |
| Address(地址) | de.example.com | 是 — 节点的公开域名或 IP |
| Port(端口) | 2053 | 是 — 该节点上的 UDP 端口 |
| Country code(国家代码) | DE | 推荐 — 驱动区域化订阅重排序 |
订阅渲染器会自动为每个已启用的主机输出 hy2:// 条目,与现有的 VLESS/VMess 链接并列。客户端在下次订阅刷新时即可看到。
通过 API(需要 sudo 管理员凭据):
# 1. 使用你的超级管理员用户名和密码获取令牌 TOKEN=$(curl -s -X POST /api/v1/admin/token \ -d "username=YOUR_ADMIN&password=YOUR_PASSWORD" \ | jq -r .access_token) # 2. 列出 hy2 入站 curl /api/v1/hy2-inbounds -H "Authorization: Bearer $TOKEN" # 3. 向 id=1 的入站添加一个主机 curl -X POST /api/v1/hy2-inbounds/1/hosts \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"remark":"DE Frankfurt","address":"de.example.com","port":2053,"country_code":"DE"}'
验证与排查
添加主机后,拉取一个订阅 URL——你应能在 VLESS 链接旁看到一条 hy2:// 条目。导入 Nekobox、sing-box 或 Happ 并连接。
| 问题 | 诊断 |
|---|---|
订阅中没有 hy2:// | 检查主机是否已启用且设置了 country_code;验证授权等级为 Standard+ |
| UDP 连接被拒绝 | 测试:从数据中心外部执行 nc -vu <node> 2053。端口未在服务商防火墙中开放。 |
| UDP 超时 | ISP 或中间设备吞掉了 UDP — 尝试 obfs salamander 或换一个端口 |
| TLS 错误 | 自签名证书:确保客户端设置了 allowinsecure: true 或提供证书指纹 |
| 节点上守护进程未启动 | 在节点服务器上执行 docker logs nexus-node 2>&1 | grep hysteria |
中转服务器(NAT 中继)
中转服务器是一台位于你的用户与你的节点之间的便宜 VPS。它通过 iptables DNAT 中继流量,让用户始终连接到一个稳定的 IP,无论由哪个节点为其服务。当某个节点 IP 在某国被封锁时很有用——更换节点、在中转服务器上重新生成 NAT、更新一条主机条目即可。
初始配置
从面板生成一条一次性安装命令,然后以 root 身份粘贴到全新的 VPS 上:
- 在面板中,前往 设置 → 中转服务器 并点击 生成安装命令。
- 复制所显示的命令——它看起来像:
curl -fsSLk https://panel.example.com:8443/api/v1/middle-server/i/<token> | sudo bash
该令牌为一次性使用,30 分钟后过期。shell 历史中不会出现任何凭据。
手动 / 脚本化安装(无面板界面访问权限)
read -p "Panel URL: " _P read -p "Admin username: " _U read -sp "Admin password: " _W; echo curl -fsSL -k -u "$_U:$_W" "$_P/api/v1/middle-server/bootstrap.sh" | sudo bash unset _P _U _W
该脚本是根据你当前的节点 + Hysteria 2 入站列表生成的,所以每当你增减二者之一时都可重新运行它。
该脚本会:
- 安装
iptables-persistent - 应用内核调优(BBR、大缓冲区、conntrack)
- 根据当前面板数据库状态构建所有 DNAT 规则
- 打印一张需要在面板中添加的主机条目表
脚本完成后,前往主机页,按脚本打印的每一行添加一个主机条目,使用中转服务器 IP 和打印出的端口。
切换到新的中转服务器
当当前中转服务器被封锁,或你想迁移到另一台 VPS 时:
- SSH 登录新 VPS 并运行上面那条相同的命令
- 在面板 → 主机页,编辑每一个地址指向旧中转服务器 IP 的主机,改为新 IP。端口保持不变。
- 完成——无需更改节点,无需用户重新配置
Fronting & Censorship Resistance
Fronting makes your customers' traffic look like it's going to Cloudflare, Amazon, Google, Fastly, or Bunny — not to your VPS. NexusPanel's IP-Defender (Dashboard → Defender) watches every fronted host and swaps a blocked one for a healthy one, automatically or with one click. The Defender page is a pipeline: Start here (Overview) → Pipeline (Sources → IP Pool → Hosts) → Infrastructure (Shield status board + Setup for credentials). Provider pages live under Shield.
The IP-Defender
It continuously probes each host: Healthy → Suspect (a sustained run of failed probes, not just one) → Blocked (auto-swap to a healthy address of the same kind) → Cooldown (the old address rests before reuse). Cloudflare, AWS, and Google swap in seconds; Fastly and Bunny don't fast-rotate — re-create the CDN with new edge IPs instead.
Cloudflare
Add a credential under Defender → Setup (provider cloudflare). To front VPN traffic, add a host under Defender → Hosts pointed at your Cloudflare-proxied domain. The separate Shield → Cloudflare card manages the subscription-delivery domain, not VPN fronting.
AWS CloudFront
Create an IAM user with CloudFront + Route 53 permissions, add the access key under Setup (provider aws), then use Defender → Shield → AWS CloudFront to provision a distribution.
Google (Cloud Run)
Create a service account with Cloud Run + DNS permissions, add its JSON key under Setup (provider google), then use Defender → Shield → Google Cloud Run.
Fastly
One-click, like Cloudflare/AWS/Google. Create an API token with global scope, add it under Setup (provider fastly), then Defender → Shield → Fastly → paste your edge IPs and click Create CDN. No fast rotation — re-create with new edge IPs if blocked.
Bunny CDN
Different model: you create the pull zone on bunny.net yourself (Standard tier, WebSockets on, one per-node Edge Rule pointing Host == bunny-<node>.<domain> at http://<node-ip>:2009), add a bunny credential under Setup, then Defender → Shield → Bunny CDN → click Auto-wire per node to adopt it. No fast rotation, same as Fastly.
Azure
Not a CDN front — a rotatable relay VM (like a Middle Server). Create a Service Principal, connect it directly on Defender → Shield → Azure (its own credential form, not through Setup), pick a region, click Create relay, then install the middle agent on the returned IP. Rotate IP swaps it later if blocked.
从 Marzban 迁移
nexus cli migrate 工具把一个运行中的 Marzban 安装迁移到 NexusPanel,且最终用户无需任何重新配置。它运行在与 Nexus 相同的主机上,直接读取 Marzban 的数据目录,并使用一个 9 阶段的原子状态机,在 finalize 命令之前都支持完整回滚。
JWT_SECRET_KEY 并将其作为 MARZBAN_LEGACY_JWT_SECRET 存入 Nexus 的环境变量。每一条现有的 Marzban 订阅 URL 从第一天起就照常可用 — 用户永远不需要重新导入任何东西。
前置条件
- Marzban 版本 0.6.0–0.8.4(官方安装脚本、
marzban或marzban_cli) - NexusPanel 安装在同一台主机上,或能够读取
/var/lib/marzban/ - 有足够的空闲磁盘用于存放 Marzban SQLite 数据库的快照
第 1 步:预演
务必先做预演。它会快照 Marzban 的数据库、把每一项导入重放到一份草稿副本中,并在数秒内完成。不会向 Nexus 或 Marzban 写入任何东西。
# 查看发现了什么 nexus cli migrate discover # 演练:在草稿数据库上快照 + 导入 + 验证,无任何副作用 nexus cli migrate run --dry-run
阅读位于 /var/lib/nexus/migration/dryrun-<ts>.json 的预演报告。确认用户数量、管理员列表,以及 MARZBAN_LEGACY_JWT_SECRET 已被提取。在继续之前修复任何被标记的错误。
第 2 步:正式切换
# 正式运行 — 停止 Marzban、导入、重启 Nexus
nexus cli migrate run --yes
关键路径(MARZBAN_STOP → NEXUS_RESTART)耗时约 15–30 秒。节点 VPN 流量不间断——节点独立于面板运行。只有订阅 URL 端点会短暂不可用。
如果 VERIFY 失败,自动回滚会触发:Nexus 配置被恢复,Marzban 被重启。查看 docker logs nexus-panel --tail 200 找出根本原因,然后重新运行。
# 在生产环境观察几个小时后: nexus cli migrate finalize # 释放快照,关闭本次运行 # 如果你需要撤销(仅限 finalize 之前): nexus cli migrate rollback
迁移内容
| 数据 | 是否迁移 | 备注 |
|---|---|---|
| 用户(用户名、流量、到期) | 是 | 所有资料、配额、UUID 均保留 |
| 用户代理 / 协议 | 是 | VMess、VLESS、Trojan、Shadowsocks |
| 管理员账户 | 是 | 密码一并迁移 |
| 主机(代理出口) | 是 | 所有主机行均复制,Nexus 独有字段默认为关闭 |
| Xray 入站 | 是 | 从 Marzban 的 xray_config.json 复制 |
| Telegram 机器人令牌、NOTIFY_* 开关 | 是 | 写入 Nexus 的 .env |
| JWT 密钥(订阅 URL 兼容) | 是 | 存为 MARZBAN_LEGACY_JWT_SECRET — 现有订阅 URL 照常可用 |
| 通知提醒历史 | 是 | 防止重复触发"3 天后到期"提醒 |
| 节点配置 | 否 | Nexus 使用端口 62060/62061;请通过控制面板用全新证书重新添加节点 |
| Xray routing/dns/outbounds | 否 | 仅迁移入站;迁移后将自定义块粘贴到 设置 → 核心编辑器 |
| Hysteria2 主机 | 否 | Marzban 没有 hy2 — 迁移后通过 控制面板 → 主机 添加 |
迁移后检查清单
nexus cli migrate run --yes 完成后,CLI 会打印一张已迁移主机的表。核对它们,然后:
- 测试一条遗留的 Marzban 订阅 URL — 它必须返回有效配置(JWT 兼容性检查)
- 检查用户数量:
docker exec nexus-panel sqlite3 /var/lib/panel/db.sqlite3 'SELECT COUNT(*) FROM users;' - 运行
nexus cli migrate post-cutover以扫描残留的 Marzban 守护进程(marzguard、certbot cron 钩子) - 如果你使用 Hysteria2:添加入站 + 为每个节点添加一个主机(参见 Hysteria2 章节)
- 通过 控制面板 → 节点 重新添加节点(新证书,端口 62060/62061)
- 稳定后运行
nexus cli migrate finalize以释放快照
# 健康检查 curl -sk https://<your-domain>/api/v1/health # 遗留订阅 URL 必须返回 200 并带有配置内容 curl -sk "https://<your-domain>/sub/<marzban-token>" | head -c 200 # 扫描 Marzban 残留 nexus cli migrate post-cutover
从 Remnawave 迁移
--run 才会真正执行。
nexus cli migrate remnawave 通过 Remnawave 的管理员 REST API 读取源面板(而非直连数据库),所以只需要面板 URL 和一个管理员账号:
nexus cli migrate remnawave run --url https://your-remnawave-panel --username ADMIN --password ...
确认预演报告无误后,加 --run 正式执行。如果某个用户名在 NexusPanel 中已存在,正式运行会直接拒绝,除非你加上 --yes(确认覆盖)。其他参数:--insecure(跳过 TLS 校验,用于 Remnawave 的自签名证书)、--page-size(API 分页大小,默认 250)。
会迁移:用户、流量限额、已用流量、到期时间、状态,以及各协议凭据(VLESS UUID、Trojan 密码、Shadowsocks 密码)。Remnawave 的订阅链接使用一个不透明的短 ID——NexusPanel 会保存它,因此老的 /sub/ 链接继续可用,客户端无需重新配置。不会迁移:用户的 Telegram ID(NexusPanel 没有对应字段,会作为警告报告)以及主机/节点——迁移后请接入 NexusPanel 自己的入站,迁移来的凭据可直接使用。
如需撤销:nexus cli migrate remnawave rollback 只删除本次运行创建的用户和别名,不影响迁移前已有的数据。
安全
双因素认证(2FA)
NexusPanel 支持基于 TOTP 的 2FA(兼容 Google Authenticator、Authy 等):
- 在控制面板中前往 设置
- 点击 启用 2FA
- 用你的身份验证器 App 扫描二维码
- 输入 6 位验证码以确认
- 将恢复码保存在安全的地方
通过 API:
# 生成 TOTP 密钥和恢复码 curl -X POST /api/v1/admin/2fa/setup -H "Authorization: Bearer TOKEN" # 激活 2FA(提供 TOTP 验证码以验证) curl -X POST /api/v1/admin/2fa/enable \ -H "Authorization: Bearer TOKEN" \ -H "Content-Type: application/json" \ -d '{"code": "123456"}' # 使用 2FA 登录 curl -X POST /api/v1/admin/token \ -H "X-TOTP-Code: 123456" \ -d "username=admin&password=admin&grant_type=password"
验证码保护
用验证码保护登录页面免受暴力破解攻击:
Cloudflare Turnstile
CAPTCHA_PROVIDER="turnstile" TURNSTILE_SITE_KEY="0x4AAAAAAA..." TURNSTILE_SECRET_KEY="0x4AAAAAAA..."
内置验证码
CAPTCHA_PROVIDER="builtin"
内置验证码无需任何外部服务,会生成简单的数学题挑战。
速率限制
登录端点的速率限制默认启用:
LOGIN_RATE_LIMIT="10/minute" LOGIN_LOCKOUT_THRESHOLD=10 LOGIN_LOCKOUT_DURATION_MINUTES=30
10 次失败尝试后,该 IP 会被锁定 30 分钟。速率限制器在内存中(按进程),服务器重启后重置。
SSL / TLS
对于生产环境部署,始终使用 HTTPS。可选方案包括:
- 直接 SSL — 设置
UVICORN_SSL_CERTFILE和UVICORN_SSL_KEYFILE - 反向代理 — 在前端使用 Nginx 或 Caddy 进行 SSL 终止
- Cloudflare — 以 Full (Strict) SSL 模式通过 Cloudflare 代理
Nginx 反向代理示例
server { listen 443 ssl http2; server_name panel.example.com; ssl_certificate /etc/letsencrypt/live/panel.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/panel.example.com/privkey.pem; location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }
常见问题
如何修改管理员密码
方案 1:更新 SUDO_PASSWORD 环境变量并重启面板。
方案 2:使用 API:
curl -X PUT /api/v1/admin/admin \ -H "Authorization: Bearer TOKEN" \ -H "Content-Type: application/json" \ -d '{"password": "newSecurePassword123"}'
如何备份
SQLite
# 为获得干净的备份,请先停止面板 docker compose stop panel cp /var/lib/nexuspanel/db.sqlite3 /backups/db-$(date +%Y%m%d).sqlite3 docker compose start panel # 或使用 SQLite 在线备份(无停机) sqlite3 /var/lib/nexuspanel/db.sqlite3 ".backup /backups/db-$(date +%Y%m%d).sqlite3"
PostgreSQL
docker compose exec db pg_dump -U nexus nexuspanel > /backups/db-$(date +%Y%m%d).sql
.env、xray_config.json 以及任何自定义模板。
如何更新
cd /opt/nexuspanel # 拉取最新镜像 docker compose pull # 用新版本重启 docker compose up -d # 查看日志了解迁移状态 docker compose logs -f panel
数据库迁移会在启动时自动运行。更新前请始终备份你的数据库。
如何添加自定义模板
自定义模板让你能够控制面向各类客户端的订阅输出:
- 在模板目录中创建你的模板文件:
mkdir -p /var/lib/nexuspanel/templates/clash nano /var/lib/nexuspanel/templates/clash/custom.yml
- 在
.env中引用该模板:
CUSTOM_TEMPLATES_DIRECTORY="/var/lib/panel/templates/" CLASH_SUBSCRIPTION_TEMPLATE="clash/custom.yml"
模板支持 Jinja2 语法,可访问用户数据、代理配置和面板设置。
订阅页面定制
面向用户的订阅页面(在浏览器中访问订阅链接时显示)完全可定制:
- 复制默认模板作为起点:
cp -r /opt/nexuspanel/app/templates/subscription \ /var/lib/nexuspanel/templates/subscription
- 编辑
/var/lib/nexuspanel/templates/subscription/index.html - 在
.env中设置:
SUBSCRIPTION_PAGE_TEMPLATE="subscription/index.html"
可用的模板变量包括:user、sub_url、clash_url、singbox_url、usage、expire_date 和 brand_name。
NexusPanel 文档 — 用心打造。