新手?请先阅读 👋

从没听说过 Marzban、"VPS" 或"面板"?没关系——本页用最通俗的话把整个思路讲清楚。零基础也能看懂。

一句话概括:NexusPanel 是一款让你运营自己的 VPN 服务并出售访问权限的软件——有点像经营一家自己的小型 Netflix,只不过你卖的是一条私密、不被封锁、速度更快的互联网连接。

你租一台便宜的服务器,在上面装好 NexusPanel,就得到一个简洁的网页控制台。在这个控制台里你创建客户,每位客户都会拿到一个链接,把它粘贴到手机上的一款免费 App 里。他们点一下"连接"——网络就通过你的服务器走了。你按月向他们收费。整个生意就是这么简单。

开店类比

如果你能想象经营一家小店,那你已经理解了 NexusPanel。下面把整套东西对应起来:

🧑‍💼

老板

你经营这门生意、定价、添加客户。你不需要是程序员。

🖥️
VPS

你的店面

你在数据中心租用的一台电脑(约 5 美元/月)。你的面板就跑在这里。供应商:Hetzner、Contabo、DigitalOcean……

🎛️
NexusPanel

你的收银台 + 货架

你在浏览器中登录的控制面板。添加客户、查看流量、收款——全在这里完成。

🌍
节点

海外分店

比如部署在德国或芬兰的一台额外服务器,让客户可以选择从哪里连接。可选——一开始可以一个都不要。

🔗
订阅链接

会员卡

你交给每位客户的一条网页链接。它包含了他们所有的连接配置——这就是他们唯一需要的东西。

📱
客户端 App

客户的入口

一款免费 App(Happ、v2rayNG、Streisand……)。他们把链接粘贴一次、点击连接,就好了。你永远不用碰他们的手机。

那么"Marzban"是什么?
Marzban 是一款很受欢迎的免费工具,多年来人们一直用它来做完全相同的事情。它能用——但一切都得靠你自己:没有技术支持、需要手动更新,也没有任何现代的反封锁功能。NexusPanel 就是它的成熟、有支持的升级版。如果你已经在跑 Marzban,可以用一条命令把所有东西迁移过来,你的客户毫无察觉(他们的链接照常可用)。如果你从未接触过——那更好,你从零开始,直接跳过那些麻烦的部分。

钱到底是怎么流动的

  1. 有人想要私密或不被封锁的互联网并向你付款(通过内置的 Telegram 机器人自动收取加密货币,或以你喜欢的任意方式收款)。
  2. 你打开 NexusPanel 为他创建一个用户——设置有效期和流量额度。大约只需 10 秒。
  3. 你把订阅链接发给他。
  4. 他把链接粘贴到一款免费 App 里并点击连接。他就通过你的服务器上线了。
  5. 下个月他再次付款以保持有效。你想要多少客户就重复多少次。
你不必弄懂底层技术
VLESSXrayRealityHysteria 这些词,只是数据穿行所经过的不同种类的隧道而已。NexusPanel 会选择合理的默认值——你完全可以在不了解它们含义的情况下经营整门生意。等你有兴趣了,术语表会用一句话解释每一个。

准备好了?选择你的起点

前往从哪开始,从三条路径中选一条:试用免费版(无需安装)、在新服务器上全新安装,或从 Marzban 迁移。

你会遇到的术语 📖

本文档中的每一个行话,都用一句通俗的话解释。现在快速浏览一遍;以后哪个词把你绊住了再回来查。

VPS virtual private server
你在数据中心按月租用的一台电脑。你的面板就跑在上面。每月约 4–6 美元就足够起步了。
Panel(面板)
你登录进去运营一切的网页控制台——也就是 NexusPanel 本身。它运行在你的 VPS 上。
Node(节点)
位于另一个地区的额外服务器,连接到你的面板,让客户可以选择从哪里连接。完全可选。
User(用户) 即客户
你出售访问权限的一个人。每位用户都有到期日期、流量额度和自己的订阅链接。
Subscription link(订阅链接) "sub link"
你给客户的那一条 URL。他们的 App 读取它来学习如何连接。如果你从 Marzban 迁移,这些链接照常可用。
Client app(客户端 App)
客户安装的免费 App——例如 Happv2rayNGStreisandHiddify。他们把订阅链接粘贴进去一次即可。
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 / 设备限制)
对一个客户同时可使用多少台手机或电脑的上限——防止共享密码吃掉你的带宽。
最难的部分到此结束
如果上面这些大致能理解,你就懂得足够运营 NexusPanel 了。前往从哪开始选一条路径吧。

从哪开始

三条路径。选最适合你的那一条,10 分钟内即可运行起来。

NexusPanel 是一个多租户 VPN 面板——你出售子账户,你的客户通过任意 v2ray 客户端连接,你在一个控制面板里管理一切。如果你是新手,最快了解它能做什么的方式就是免费试用。如果你已经在跑 Marzban,迁移工具会用一条命令把所有东西迁移过来——用户、管理员、主机、证书,连你现有的订阅 URL 都照常可用。

路径 A · 无需安装

试用免费版

打开 Telegram 机器人,输入 /start,领取一个 14 天试用授权。你可以用这个授权搭建自己的面板,在付费之前先亲自体验一遍。

⏱ 2 分钟 💳 无需信用卡
打开 Telegram 机器人 →
路径 B · 新 VPS

在全新服务器上安装

在一台干净的 Ubuntu 20.04+ VPS 上执行一条命令。脚本会询问你的授权、域名和管理员密码——仅此而已。只要你把域名指向服务器,SSL 就会自动配置。

⏱ 5 分钟 🖥 最低 1 GB 内存
查看安装命令 ↓
路径 C · 来自 Marzban

从 Marzban 迁移

同一台 VPS,无需重新配置客户端。迁移工具采用预演优先且可逆的设计——在动任何东西之前你都能预览每一处改动,并且在最终切换前的任何时刻都能回滚。从 Remnawave 面板迁移同样支持,见从 Remnawave 迁移

⏱ 10 分钟 🔁 可续传 + 可逆
迁移指南 ↓
为什么迁移是安全的
该工具从不写入你的 Marzban 数据库。它会把 Marzban 快照成一份只读副本,从该副本构建 Nexus 状态,只在最后一步才切换容器。如果在切换前发现任何不对,你可以中止,Marzban 会原封不动地继续运行。迁移后你现有的订阅 URL 也会继续工作——Nexus 会沿用 Marzban 的 JWT 密钥,所以你的用户手上已有的每一条 https://your-panel/sub/<token> 链接都仍能正常解析。

你需要准备什么

  • 一台 Ubuntu 20.04+(或任意 Debian 系发行版)的 VPS,最低 1 GB 内存,建议 2 GB
  • 该 VPS 的 root SSH 访问权限
  • 一个指向该 VPS 的域名(可选——可获得真实、无警告的 HTTPS 证书;没有域名也一样能用 HTTPS,只是使用自签名证书,浏览器会有一次性警告)
  • 一个 NexusPanel 授权(从 Telegram 机器人领取,免费 14 天试用即可)

如何获取帮助

如果出了任何问题,请按顺序尝试:

  1. 查看面板日志:cd /opt/panel && docker compose logs --tail 100
  2. 阅读本文档的相关章节(左侧侧边栏)
  3. 在 Telegram 上联系我们——链接在机器人里,响应时间以小时计而非天

什么是 NexusPanel

通俗地说
它就是你登录进去运营 VPN 生意的控制面板:添加客户、发放连接链接、查看谁在线、收款——全在一处完成。对这一切都陌生?从新手?请先阅读开始。

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 GB2 GB+
CPU1 vCPU2 vCPU
磁盘10 GB20 GB+(SSD)
Docker20.10+最新稳定版
域名可选推荐(用于 SSL)
注意
如果系统中尚未安装 Docker 和 Docker Compose,快速安装脚本会自动安装。

快速安装

在一台全新的 VPS 上运行这一条命令,即可使用默认设置安装 NexusPanel:

bash
curl -sL https://nexuspanel.store/install | bash

脚本会提示你输入:

  1. 授权密钥与客户端 ID — 来自 @nexuspanelpayment_bot(免费 14 天试用密钥同样适用,但安装脚本始终需要一个密钥——不存在无授权安装)
  2. 域名 — 用于通过 Let's Encrypt 配置 SSL(仅用 IP 则跳过)
  3. 管理员用户名与密码 — 用于控制面板
  4. 面板端口 — 默认 8443

随后它会:

  1. 如缺失则安装 Docker 与 Docker Compose
  2. 拉取 ghcr.io/haitovs/nexus:latest(经 Cython 保护的生产镜像)
  3. 创建 /opt/panel/,包含 .envdocker-compose.yml(容器名:nexus-panel
  4. 生成启用访问日志的 xray_config.json(IP/设备限制强制执行所必需)
  5. 启动面板并打印控制面板 URL + 登录凭据
更新通知
安装完成后,面板每 6 小时向你的授权服务器发送一次心跳。自动更新默认关闭:当有新版本发布时,面板会显示“有可用更新”提示,你在主机上运行 nexus update 来应用更新。

一键安装(详细)

安装脚本接受可选参数来自定义安装过程:

bash
# 推荐 —— 传入你的授权密钥 + 客户端 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/)访问。

仅用 IP 安装时的“不安全”警告
没有域名时,面板依然通过 HTTPS 提供服务,但使用的是自签名证书(Let's Encrypt 需要域名才能签发真实证书)。首次打开面板时,浏览器会一次性显示“不安全”/“您的连接不是私密连接”警告——点击 Advanced → Proceed(Chrome)或 Visit this website(Safari)继续即可。这是预期行为,也是安全的:连接仍然是加密的,只是证书没有由公共证书颁发机构签名。之后为服务器绑定域名即可获得无警告的证书。

面板初始步骤

登录后,按以下顺序最快建立第一条可用连接:

  1. 创建一个用户 — 面板 → UsersAdd User。设置到期时间和流量限额,然后复制订阅链接,交给客户端应用(Happ、v2rayNG、Streisand 等)。
  2. 添加一个节点(可选)— 面板 → NodesAdd New Node,复制生成的快速安装命令,在节点服务器上运行,然后回到面板填写 Name + Address 完成连接。详见节点安装
  3. 设置订阅域名 — 如果订阅链接要从与管理面板不同的主机/域名提供,请在环境变量编辑器(Settings → Env)中设置 XRAY_SUBSCRIPTION_URL_PREFIX,并使用 Save & Restart——该设置只有完整重启后才会生效。

手动安装

上面的安装脚本是官方支持的方式——它会自动完成私有镜像仓库的认证、写出可用的 .env,并配置好防火墙。如果你想手动完成这一切:

bash
# 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:

bash
# 安装 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 任务用于自动续期:

bash
0 3 * * * certbot renew --quiet && docker compose -C /opt/nexuspanel restart

使用 PostgreSQL

对于生产环境部署,建议使用 PostgreSQL 而非 SQLite。设置 BACKEND_MODE=modern,并使用面板实际内置的驱动——psycopg2(同步),而不是 asyncpg

bash
# 在 .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:

bash
# 在安装目录下(例如 /opt/panel)
cp docker-compose.modern.yml docker-compose.yml
docker compose up -d
未安装 asyncpg
面板内置的是 psycopg2-binary,不是 asyncpg——使用 postgresql+asyncpg:// 会因找不到驱动而失败。请始终使用 postgresql+psycopg2://

Docker Compose 示例

Classic(SQLite)—— 安装程序实际写出的文件

yaml — /opt/panel/docker-compose.yml
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_HOST0.0.0.0服务器绑定地址
UVICORN_PORT8000HTTP 端口
UVICORN_UDSUnix 域套接字路径(覆盖 host/port)
UVICORN_SSL_CERTFILESSL 证书路径(fullchain.pem)
UVICORN_SSL_KEYFILESSL 私钥路径
UVICORN_SSL_CA_TYPEpublicCA 类型:publicprivate
DASHBOARD_PATH/dashboard/网页控制面板的 URL 路径
ALLOWED_ORIGINS以逗号分隔的 CORS 来源
SUDO_USERNAME初始超级管理员用户名
SUDO_PASSWORD初始超级管理员密码
JWT_ACCESS_TOKEN_EXPIRE_MINUTES1440令牌过期时间(分钟,默认 24 小时)

数据库

变量默认值说明
SQLALCHEMY_DATABASE_URLsqlite:///db.sqlite3数据库连接字符串
SQLALCHEMY_POOL_SIZE10连接池大小
SQLIALCHEMY_MAX_OVERFLOW30连接池之外的最大连接数
BACKEND_MODEclassicclassic(SQLite/Postgres,默认)或 modern(增加 Redis 支持的事件队列)
REDIS_URLRedis 连接字符串;当 BACKEND_MODE=modern 时必填
PostgreSQL 连接字符串
异步 PostgreSQL 请使用 postgresql+asyncpg://user:pass@host:5432/dbname
Modern 后端模式
设置 BACKEND_MODE=modern 并提供 REDIS_URL 以启用 Redis 支持的事件队列。使用 docker-compose.modern.yml,它会随面板一起部署一个 redis:7 服务。大多数部署并不需要这个。

Xray

变量默认值说明
XRAY_JSONxray_config.jsonXray 核心配置文件路径
XRAY_EXECUTABLE_PATH/usr/local/bin/xrayXray 二进制文件路径
XRAY_ASSETS_PATH/usr/local/share/xraygeoip.dat 和 geosite.dat 的路径
XRAY_SUBSCRIPTION_URL_PREFIX订阅链接的公开 URL 前缀(例如 https://sub.example.com)。改动仅在面板完整重启后生效——请使用环境变量编辑器中的 保存并重启,而非容器重启。
XRAY_SUBSCRIPTION_PATHsub订阅的 URL 路径段
XRAY_EXCLUDE_INBOUND_TAGS以空格分隔的、需排除的入站标签
XRAY_FALLBACKS_INBOUND_TAG用于回退路由的入站标签

订阅

变量默认值说明
SUB_PROFILE_TITLESubscription客户端 App 中显示的名称
SUB_SUPPORT_URL包含在订阅信息中的支持链接
SUB_UPDATE_INTERVAL12客户端自动更新间隔(小时)
EXTERNAL_CONFIG用于客户端集成的外部配置 URL
USE_CUSTOM_JSON_DEFAULTfalse为默认客户端启用自定义 JSON 配置
USE_CUSTOM_JSON_FOR_V2RAYNfalse为 V2RayN 启用自定义 JSON
USE_CUSTOM_JSON_FOR_V2RAYNGfalse为 V2RayNG 启用自定义 JSON
USE_CUSTOM_JSON_FOR_STREISANDfalse为 Streisand 启用自定义 JSON
USE_CUSTOM_JSON_FOR_HAPPfalse为 Happ 启用自定义 JSON
SUB_RATE_LIMIT_PER_MINUTE60每个 IP 每分钟最多拉取订阅的次数(进程内,重启后重置)
SUB_ENABLE_ETAGtrue返回 ETag / 处理 If-None-Match,在订阅未变更时节省带宽
SUB_GZIP_MIN_SIZE512对大于此字节数的订阅响应进行 Gzip 压缩

模板

变量默认值说明
CUSTOM_TEMPLATES_DIRECTORY/var/lib/panel/templates/自定义模板的基目录
SUBSCRIPTION_PAGE_TEMPLATEsubscription/index.html用户订阅页面的模板
HOME_PAGE_TEMPLATEhome/index.html面板首页的模板
CLASH_SUBSCRIPTION_TEMPLATEclash/default.ymlClash 订阅模板
CLASH_SETTINGS_TEMPLATEclash/settings.ymlClash 设置模板
V2RAY_SUBSCRIPTION_TEMPLATEv2ray/default.jsonV2Ray 订阅模板
V2RAY_SETTINGS_TEMPLATEv2ray/settings.jsonV2Ray 设置模板
SINGBOX_SUBSCRIPTION_TEMPLATEsingbox/default.jsonSing-box 订阅模板
SINGBOX_SETTINGS_TEMPLATEsingbox/settings.jsonSing-box 设置模板
MUX_TEMPLATEmux/default.json多路复用配置模板
USER_AGENT_TEMPLATEuser_agent/default.jsonUser-agent 解析模板
GRPC_USER_AGENT_TEMPLATEuser_agent/grpc.jsongRPC user-agent 模板

Telegram

变量默认值说明
TELEGRAM_API_TOKEN来自 @BotFather 的机器人令牌
TELEGRAM_ADMIN_ID以逗号分隔的管理员 Telegram 用户 ID
TELEGRAM_LOGGER_CHANNEL_ID用于日志消息的频道 ID
TELEGRAM_DEFAULT_VLESS_FLOWxtls-rprx-vision机器人创建用户时的默认 VLESS flow
TELEGRAM_PROXY_URLTelegram API 连接的代理 URL

通知

变量默认值说明
NOTIFY_STATUS_CHANGEtrue用户状态变更时通知
NOTIFY_USER_CREATEDtrue创建新用户时通知
NOTIFY_USER_UPDATEDtrue修改用户时通知
NOTIFY_USER_DELETEDtrue删除用户时通知
NOTIFY_USER_DATA_USED_RESETtrue用量重置时通知
NOTIFY_USER_SUB_REVOKEDtrue订阅被吊销时通知
NOTIFY_IF_DATA_USAGE_PERCENT_REACHEDtrue达到流量阈值时通知
NOTIFY_IF_DAYS_LEFT_REACHEDtrue达到到期阈值时通知
NOTIFY_LOGINtrue管理员登录时通知
LOGIN_NOTIFY_WHITE_LIST从登录通知中排除的 IP
NOTIFY_DAYS_LEFT3,7剩余天数通知阈值
NOTIFY_REACHED_USAGE_PERCENT80,90用量百分比阈值
RECURRENT_NOTIFICATIONS_TIMEOUT180重复通知之间的间隔(分钟)
NUMBER_OF_RECURRENT_NOTIFICATIONS3每个事件的最大重复通知次数
DISCORD_WEBHOOK_URL用于 Telegram 风格通知的 Discord webhook
WEBHOOK_ADDRESS遗留:以逗号分隔的静态 webhook URL。新部署请优先使用控制面板的 Webhook 界面。
WEBHOOK_SECRET遗留:用于 WEBHOOK_ADDRESS 投递的 HMAC 密钥。控制面板 webhook 按端点分别管理密钥。

品牌定制(白标)

变量默认值说明
BRAND_NAMEPanel在界面和邮件中显示的面板名称
BRAND_LOGO_URL自定义 logo 图片的 URL
BRAND_FAVICON_URL自定义 favicon 的 URL

安全

变量默认值说明
CAPTCHA_PROVIDERdisabled验证码提供方:disabledturnstilebuiltin
TURNSTILE_SITE_KEYCloudflare Turnstile 站点密钥
TURNSTILE_SECRET_KEYCloudflare Turnstile 私密密钥
LOGIN_RATE_LIMIT10/minute每个时间窗内的最大登录尝试次数
LOGIN_LOCKOUT_THRESHOLD10触发锁定前的失败尝试次数
LOGIN_LOCKOUT_DURATION_MINUTES30锁定时长(分钟)

日志

变量默认值说明
LOG_LEVELINFO日志级别:DEBUG、INFO、WARNING、ERROR
LOG_FORMATtext日志格式:textjson
LOG_FILE_PATH将日志写入文件(在 stdout 之外)
LOG_MAX_SIZE_MB10轮转前的最大日志文件大小
LOG_BACKUP_COUNT5保留的已轮转日志文件数量

指标(Prometheus)

变量默认值说明
METRICS_ENABLEDfalse启用 Prometheus /metrics 端点
METRICS_TOKEN抓取指标所需的 Bearer 令牌

其他变量

变量默认值说明
ACTIVE_STATUS_TEXTActive有效状态的自定义标签
EXPIRED_STATUS_TEXTExpired已过期状态的自定义标签
LIMITED_STATUS_TEXTLimited受限状态的自定义标签
DISABLED_STATUS_TEXTDisabled已禁用状态的自定义标签
ONHOLD_STATUS_TEXTOn-Hold挂起状态的自定义标签
USERS_AUTODELETE_DAYS-1N 天后自动删除已过期用户(-1 = 禁用)
USER_AUTODELETE_INCLUDE_LIMITED_ACCOUNTSfalse自动删除时包含流量受限的用户
JOB_CORE_HEALTH_CHECK_INTERVAL10健康检查间隔(秒)
JOB_RECORD_NODE_USAGES_INTERVAL30节点用量记录间隔
JOB_RECORD_USER_USAGES_INTERVAL10用户用量记录间隔
JOB_REVIEW_USERS_INTERVAL10用户审查/到期检查间隔
JOB_SEND_NOTIFICATIONS_INTERVAL30通知派发间隔
DISABLE_RECORDING_NODE_USAGEfalse禁用节点用量记录
DEBUGfalse启用带热重载的调试模式
DOCSfalse/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 / HostTLS 服务器名称指示(SNI)和 HTTP Host 头
Security / ALPN / FingerprintTLS 配置: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 字段:

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 将用户加入某个组。一个用户最多只能属于一个组。

bash — 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。

bash — API
# 创建一个入站集合
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_agentequals / contains / regextemplate / status / headers
client_osequals / contains / regextemplate / 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 升序求值。首个匹配者生效。

bash — API
# 创建一条规则:向 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

将范围留空即可接收所有事件。投递失败时以指数退避重试;超过最大尝试次数后,该事件被标记为失败并丢弃。

bash — API
# 注册一个端点
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 分享给最终用户。

客户端平台说明
HappiOS / macOS / Windows / Android推荐 — 原生订阅 URL、HWID 绑定、离线缓存
v2RayTuniOS / macOS / Android热门 iOS 客户端,支持 VLESS-Reality
Karing全平台基于 Sing-box,跨平台体验出色
ShadowrocketiOS美区 App Store 售价 $2.99 — 极其稳定的 iOS 客户端
V2rayNGAndroid经典 Android 客户端
FlClashXWindows / macOS / Linux / Android兼容 Mihomo/Clash
StreisandiOS / macOS支持自定义 JSON — 设置 USE_CUSTOM_JSON_FOR_STREISAND=true

授权系统

NexusPanel 使用一个中央授权服务器(nexuspanel.store)来验证安装并推送更新。这就是客户分级、计费和保持更新的方式。

心跳如何工作

  • 面板每 6 小时调用一次授权服务器上的 POST /api/validate,附带其 license_idclient_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/月无限1030 天/月
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 KeyClient ID

宽限期

如果你的授权过期,面板会以宽限模式继续运行 72 小时,让你可以在不中断服务的情况下续期。此后 API 将切换为只读,直到恢复一个有效授权为止。

IP 与设备限制的强制执行

NexusPanel 通过解析 Xray 访问日志,实时强制执行每个用户的 IP 和设备限制——而不仅仅是在订阅导入时。这正是让 ip_limitdevice_limit 真正生效的机制。

它如何工作

  1. Xray 为每个被接受的连接向 $XRAY_ACCESS_LOG 写入一行。
  2. enforce_limits 任务每 60 秒运行一次,跟踪读取日志(带偏移量跟踪、感知轮转),并从最近 LIMIT_WINDOW_SECONDS(默认 600 = 10 分钟)内提取 (user_id, client_ip) 对。
  3. 对每个用户,统计唯一 IP 数量。如果该数量超过 ip_limit(若未设置 ip_limit 则用 device_limit),该用户当前为 active ip_limit_mode == "limit",则该用户被切换为 limited 状态。
  4. 所有出现过的 IP 都会被写入 user_ip_history。可通过 GET /api/v1/user/{username}/ips 查看每个用户的 IP。

所需的 xray 配置

默认安装会自动启用此功能。对于已有安装,面板会在启动时自动修补你的 xray_config.json 以添加访问日志路径。手动配置:

json
{
  "log": {
    "loglevel": "warning",
    "access": "/var/lib/panel/xray-access.log"
  }
}

可调参数

环境变量默认值用途
XRAY_ACCESS_LOG/var/log/xray/access.logXray 访问日志文件路径
LIMIT_WINDOW_SECONDS600统计唯一 IP 的滚动时间窗
LIMIT_ENFORCE_INTERVAL60强制执行任务的运行频率(秒)

备份

NexusPanel 通过 backup APScheduler 任务,每天在 03:00 UTC 自动进行一次数据库备份。

备份存放在哪里

  • 本地文件:/var/lib/panel/backups/backup_YYYYMMDD_HHMMSS.sqlite3(PostgreSQL 则为 .sql
  • 保留最近 7 份备份;更旧的会被自动清理
  • 如果配置了 TELEGRAM_API_TOKENTELEGRAM_ADMIN_ID,每份备份还会作为文档推送到你的 Telegram,从而拥有一份服务器外的副本

手动备份

bash
# 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

恢复

  1. 停止面板:cd /opt/panel && docker compose down
  2. 替换数据库文件:cp /path/to/backup.sqlite3 /var/lib/panel/db.sqlite3
  3. 重启: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> 格式。

TODO — 尚未翻译成中文
本节("经营你的业务")尚未翻译。以下为英文原文,先看着用。

Run Your Business

Your First Customer

  1. Dashboard → UsersAdd User.
  2. Give them a username, pick an expiry date and a data limit (or leave both unlimited), and pick which protocols they get.
  3. Save — the panel generates their subscription link immediately.
  4. 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 标签页会改为生成一条已内嵌面板证书、可直接粘贴的命令。无需手动写入证书文件。

  1. 控制面板 → 节点添加新节点Manual 标签页
  2. 点击 复制安装命令 — 该命令已包含证书、端口、API 端口和面板地址
  3. 粘贴并在节点服务器上运行
  4. 在面板中输入节点的 IP 和端口 → 添加节点
bash — 生成命令示例
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
防火墙
在节点服务器上,对面板 IP 开放入站的 TCP 62060TCP 62061。同时对最终用户开放任意代理端口(443、80 等)。

节点的 Docker Compose

这是安装程序在 /opt/nexus-panel-node/docker-compose.yml 实际生成的文件——供你手动调整时参考:

yaml — /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)。

多个节点

要在不同地区添加节点:

  1. 使用生成的一行命令在每台服务器上安装节点服务
  2. 在面板中,用每个节点的公网 IP 和端口添加它
  3. 分配一个国家旗帜 — 同时驱动可视化网格和区域化订阅重排序
  4. 拖放以设置网格中的显示顺序
  5. 为每个节点设置一个用量系数(例如 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 访问令牌:

POST /api/v1/admin/token
bash
curl -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 验证码。

2FA 端点
POST /api/v1/admin/2fa/setup — 生成 TOTP 密钥 + 恢复码
POST /api/v1/admin/2fa/enable — 验证验证码并激活 2FA
POST /api/v1/admin/2fa/disable — 停用 2FA

用户

POST /api/v1/user

创建一个带协议、流量额度、到期、设备限制和 IP 限制的新用户。

GET /api/v1/users

列出所有用户。对非 sudo 账户会自动按管理员限定作用域。

GET /api/v1/user/{username}

获取详细的用户信息,包括用量统计和订阅链接。

PUT /api/v1/user/{username}

更新用户字段(流量额度、到期、状态、协议等)。

DELETE /api/v1/user/{username}

永久删除一个用户及其所有关联数据。

批量操作

POST /api/v1/users/bulk/update
POST /api/v1/users/bulk/delete
POST /api/v1/users/bulk/reset

导出

GET /api/v1/export/users

将所有用户下载为 CSV 文件。

GET /api/v1/export/subscription-links

将所有订阅链接导出为纯文本。

管理员

POST /api/v1/admin

创建一个带角色(owneradminreseller)、max_users 和 max_traffic_bytes 的新管理员。

GET /api/v1/admins

列出所有管理员账户。

节点

GET /api/v1/inbounds

列出所有协议入站。

GET /api/v1/hosts

获取主机配置(仅限 sudo)。

数据分析

GET /api/v1/analytics/summary

控制面板概览统计。

GET /api/v1/analytics/protocols

协议分布明细。

GET /api/v1/analytics/nodes/load

每个节点的连接数和带宽。

GET /api/v1/analytics/nodes/uptime

节点在线时长百分比。

GET /api/v1/analytics/users/expiring?days=30

在指定天数内即将到期的用户。

GET /api/v1/analytics/users/top?limit=10

按带宽消耗排名的消耗大户。

会话

GET /api/v1/sessions/active?hours=24

最近 N 小时内的活跃设备会话。

GET /api/v1/sessions/user/{username}

某个特定用户的会话。

DELETE /api/v1/sessions/{session_id}

强制断开一个设备会话。

系统

GET /api/v1/system

系统统计,包括 CPU、内存和带宽。非 sudo 管理员对敏感指标看到的是清零值。

GET /api/v1/health

健康检查端点,返回数据库和 Xray 核心状态。

GET /metrics

Prometheus 兼容的指标端点。需要 METRICS_ENABLED=true 和用于认证的 METRICS_TOKEN

完整 API 文档
要查看完整的请求/响应模式,请在你的 .env 中启用 DOCS=true,并访问 http://your-panel/docs 查看交互式 Swagger UI。

Telegram 机器人

配置

  1. 打开 Telegram 并给 @BotFather 发消息
  2. 发送 /newbot 并按提示创建你的机器人
  3. 复制机器人令牌(例如 123456789:AAAA...
  4. 获取你的 Telegram 用户 ID(给 @userinfobot 发消息)
  5. 添加到你的 .env
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 集成
设置 DISCORD_WEBHOOK_URL 即可在 Discord 频道中收到相同的通知。Discord 嵌入消息包含同样丰富的字段。

订阅分发渠道

通过审查者无法封锁的基础设施来分发订阅 URL。

当你的面板域名在俄罗斯、伊朗、中国或土库曼斯坦被封锁时,客户就拉不到他们的订阅更新。订阅分发渠道通过把每个用户的配置发布到 Google / Cloudflare / GitHub / Telegram 基础设施上的一个静态文件来解决这个问题——这些主机名审查者无法一刀切地封锁,否则会破坏数以百万计用户在用的主流应用。

授权要求
订阅分发渠道需要 Pro 授权等级。较低等级时,控制面板会显示付费墙横幅。

它如何工作

  1. 你在 设置 → 订阅分发渠道 中配置一个或多个渠道。
  2. 每个用户在该渠道上获得一个稳定的公开 URL(例如 https://firebasestorage.googleapis.com/…?alt=media&token=…)。
  3. 用户表中每一行用户上的 ⊞(网格)图标会打开一个弹层,列出所有可用 URL——直连、Happ 加密以及每个已配置的渠道。两次点击即可复制或显示二维码。
  4. 当你编辑主机或 Xray 配置时,面板会通过后台工作进程,在约 10–30 秒内自动把所有活跃用户重新发布到 Firebase(及其他渠道)。常规配置编辑后无需手动回填。

可用渠道

渠道提供方免费额度最适合
Firebase StorageGoogleSpark 方案约 5 万次轮询/天主要的反审查渠道
Firebase HostingGoogle与 Storage 相同的 Spark 方案同一 Google 项目下的第二个 Firebase 出口(*.web.app)——不同的 SNI 和边缘 CDN,Storage 被封锁时仍可访问。发布是整站级别的,不是按用户,因此是批量更新而非每次编辑都发布。
Cloudflare R2Cloudflare10 GB/月,无出口费用次要渠道;与 Firebase 不同的供应商
GitHub GistGitHub / Microsoft无限公开 gist低保真回退;极其耐用
GitLab SnippetGitLab无限公开 snippet即使在土库曼斯坦的重度封锁窗口期也确认可达——作为 Firebase 无法访问时的第二镜像
Telegram 分发Telegram免费当其他一切都失效时的应急分发
Nginx 代理池你的 VPSVPS 的成本对中继拥有完全的运营者控制权
从面板端测试,而非你的笔记本
测试按钮(每个渠道行上的刷新图标)会上传一个真实的测试数据块,并从面板的出站网络——而非你的浏览器——把它取回。这一点很重要:你本地的 DNS 可能正常,而你客户所在地区却封锁了该 URL。测试所衡量的,是面板服务器能否访问该 URL,而这正是决定订阅更新能否送达的关键。

Firebase Storage

推荐的首个渠道。免费额度可覆盖约每天 5 万次订阅轮询。托管在 Google 的 IP 段上——审查者无法一刀切封锁,否则会破坏 Google Maps、Gmail 以及无数其他应用。

在 console.firebase.google.com 进行一次性配置

  1. 创建项目 — Add project → 命名(例如 nexus-subs)→ Spark 方案(免费)→ Create。
  2. 启用 Storage — Build → Storage → "Get started" → "Start in production mode" → 选择地区 → Done。
  3. 设置存储规则 — Storage → Rules → 替换为:
firebase rules
rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /sub_{file=**} {
      allow read: if true;
      allow write: if false;
    }
  }
}
  1. 生成服务账号密钥 — Project Settings(⚙)→ Service accounts → "Generate new private key" → Download。请当作密码一样对待。
  2. 查找存储桶名称 — Storage → 顶部会显示 gs://your-project.firebasestorage.app。复制 gs:// 之后的部分。

在面板中

  1. 设置 → 订阅分发渠道 → Firebase Storage → ⚙
  2. 粘贴存储桶名称服务账号 JSON(整个文件内容)
  3. 开启启用,设置优先级(数值越小越优先;10 是个不错的起点)
  4. 保存 → 点击测试(刷新图标)

读懂测试结果

一次通过的测试看起来是这样:

result
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 秒完成。

方案变更时 URL 保持稳定
对于给定用户,Firebase URL 永不改变——只会覆盖数据块的内容。客户把 URL 导入 VPN 客户端一次,之后每次方案变更都会自动更新,无需他们做任何操作。

Cloudflare R2

兼容 S3 的对象存储,无出口费用。作为 Firebase 之外的次要渠道使用——不同的供应商意味着针对其中一个的特定地区封锁不会同时拖垮两个。

在 dash.cloudflare.com 配置

  1. R2(左侧栏)→ Create bucket → 命名(例如 nexus-subs)。
  2. 打开存储桶 → Settings → Public access → 启用。复制 https://pub-<id>.r2.dev URL。
  3. R2 页面右上角 → Manage R2 API tokens → Create token → Object Read & Write(限定到你的存储桶)→ 保存 Access Key ID + Secret。
  4. 你的 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
不要为 R2 绑定自定义域名
自定义域名会在 DNS 层被封锁。共享的 pub-<id>.r2.dev 主机名享有与 Firebase 相同的反封锁优势——它与成千上万个其他 R2 存储桶共享。

GitHub Gist

免费、由 GitHub 托管(Microsoft 的 IP)。极其耐用——一个不花钱的优质低优先级回退选项。

配置

  1. github.com/settings/tokens → Personal access tokens → Tokens (classic) → Generate new token。
  2. 名称:nexus-gists。范围:仅勾选 gist。有效期:1 年(在日历上记下续期)。
  3. 复制 ghp_… 令牌——你无法再次看到它。

在面板中

设置 → 订阅分发渠道 → GitHub Gist → ⚙ → 粘贴 PAT → 保存 → 测试。

Telegram 分发

恰恰在其他渠道不可用的那些时间窗里,它在 IR/RU/TM 仍可访问。这是"面板着火了、用户别无他法"的回退渠道。

这是分发,不是自动更新
用户得到的是一个 t.me/<bot>?start=sub_<token> 深链,而非自更新 URL。他们点击一次,机器人就私信给他们一个含其配置的 .txt 文件。只有在你已接好机器人的 /start 处理程序时,才把优先级设得非常高(优先级数值很小)——否则它会指向一个不回复的机器人。

配置 — 专用机器人(推荐)

  1. 在 Telegram 上给 @BotFather 发消息 → /newbot → 取一个名称和用户名(必须以 bot 结尾)。
  2. 复制 BotFather 给你的令牌。
  3. 设置 → 订阅分发渠道 → Telegram → ⚙:
    • 机器人用户名:不带 @
    • 机器人令牌:从 BotFather 粘贴
  4. 保存 → 测试。测试会调用 getMe 并断言返回的用户名与你粘贴的一致。

如果你已在 .env 中为通知分发设置了 TELEGRAM_API_TOKEN,可以把机器人令牌字段留空——该渠道会回退到使用那个环境变量。出于安全考虑不推荐这样做:泄露的通知机器人令牌也会暴露订阅文件。

Nginx 代理池

当静态存储渠道全部宕机或被特定地区封锁时,回退到你自己那批便宜的中继 VPS。池中每台主机都拥有自己的域名;面板按权重把用户分配到各主机。

预先开通

开通一些便宜的 VPS(Hetzner CCX13 / Contabo / 等——每台 €4–5/月)。在每台上:

bash
# 在每台全新的代理主机上以 root 运行
curl -sSL https://your-panel.tld/setup_proxy.sh | bash

在面板中

设置 → 订阅分发渠道 → Nginx-proxy → ⚙。配置为 JSON:

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 订阅条目,但无法创建或管理入站。

需要 UDP 防火墙
Hysteria2 使用 UDP。为某个节点添加主机之前,请确保该 UDP 端口(例如 2053)在你主机服务商的控制面板中已开放——Contabo、Aeza、PTR 默认都会拦截 UDP。

添加 Hysteria2 入站

控制面板 → 设置Hysteria2添加入站

需要 sudo 管理员
Hysteria2 入站只能由 sudo(超级)管理员创建和管理。非 sudo 管理员看不到也无法编辑 hy2 入站。
字段备注
Tag(标签)hy2-main任意唯一名称
Listen port(监听端口)2053UDP — 必须在防火墙中开放
Obfs type(混淆类型)salamander推荐 — 在 CN/IR/RU 对 DPI 隐藏 UDP
Obfs password(混淆密码)强随机值openssl rand -hex 24
Masquerade URL(伪装 URL)https://www.bing.comhysteria 在面对 DPI 探测时伪装成的 HTTPS 站点
SNIbing.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 管理员凭据):

bash
# 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、更新一条主机条目即可。

端口约定
TCP 入站:中转端口 50031–50036 → 节点端口 31–36(与节点 id 对应)。Hysteria2 UDP 入站:端口 50041+ 按入站分配。所有这些都由面板数据库状态自动生成——你永远不用手动编辑它们。

初始配置

从面板生成一条一次性安装命令,然后以 root 身份粘贴到全新的 VPS 上:

  1. 在面板中,前往 设置 → 中转服务器 并点击 生成安装命令
  2. 复制所显示的命令——它看起来像:
bash
curl -fsSLk https://panel.example.com:8443/api/v1/middle-server/i/<token> | sudo bash

该令牌为一次性使用,30 分钟后过期。shell 历史中不会出现任何凭据。

手动 / 脚本化安装(无面板界面访问权限)
bash
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 和打印出的端口。

重新运行是安全的
脚本在应用新规则前会先清空现有规则。每当你添加节点、添加 Hysteria2 入站或更改节点 IP 时都可随时运行它。

切换到新的中转服务器

当当前中转服务器被封锁,或你想迁移到另一台 VPS 时:

  1. SSH 登录新 VPS 并运行上面那条相同的命令
  2. 在面板 → 主机页,编辑每一个地址指向旧中转服务器 IP 的主机,改为新 IP。端口保持不变。
  3. 完成——无需更改节点,无需用户重新配置
别忘了 Hysteria2 主机
如果你有通过中转服务器路由的 Hysteria2 主机,也要更新这些地址。
TODO — 尚未翻译成中文
本节("前置分发与反审查")尚未翻译。以下为英文原文,先看着用。

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: HealthySuspect (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 迁移

通俗地说
已经在跑 Marzban?这会用一条命令把所有东西迁移到 NexusPanel——你的客户、设置,乃至他们现有的链接。你的客户什么都不用做,也察觉不到任何变化。它会先预览每一处改动,并且直到最后一步之前都能撤销,所以试一试很安全。

nexus cli migrate 工具把一个运行中的 Marzban 安装迁移到 NexusPanel,且最终用户无需任何重新配置。它运行在与 Nexus 相同的主机上,直接读取 Marzban 的数据目录,并使用一个 9 阶段的原子状态机,在 finalize 命令之前都支持完整回滚。

JWT 兼容性
迁移工具会提取 Marzban 的 JWT_SECRET_KEY 并将其作为 MARZBAN_LEGACY_JWT_SECRET 存入 Nexus 的环境变量。每一条现有的 Marzban 订阅 URL 从第一天起就照常可用 — 用户永远不需要重新导入任何东西。

前置条件

  • Marzban 版本 0.6.0–0.8.4(官方安装脚本、marzbanmarzban_cli
  • NexusPanel 安装在同一台主机上,或能够读取 /var/lib/marzban/
  • 有足够的空闲磁盘用于存放 Marzban SQLite 数据库的快照

第 1 步:预演

务必先做预演。它会快照 Marzban 的数据库、把每一项导入重放到一份草稿副本中,并在数秒内完成。不会向 Nexus 或 Marzban 写入任何东西。

bash
# 查看发现了什么
nexus cli migrate discover

# 演练:在草稿数据库上快照 + 导入 + 验证,无任何副作用
nexus cli migrate run --dry-run

阅读位于 /var/lib/nexus/migration/dryrun-<ts>.json 的预演报告。确认用户数量、管理员列表,以及 MARZBAN_LEGACY_JWT_SECRET 已被提取。在继续之前修复任何被标记的错误。

第 2 步:正式切换

bash
# 正式运行 — 停止 Marzban、导入、重启 Nexus
nexus cli migrate run --yes

关键路径(MARZBAN_STOP → NEXUS_RESTART)耗时约 15–30 秒。节点 VPN 流量不间断——节点独立于面板运行。只有订阅 URL 端点会短暂不可用。

如果 VERIFY 失败,自动回滚会触发:Nexus 配置被恢复,Marzban 被重启。查看 docker logs nexus-panel --tail 200 找出根本原因,然后重新运行。

bash
# 在生产环境观察几个小时后:
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 会打印一张已迁移主机的表。核对它们,然后:

  1. 测试一条遗留的 Marzban 订阅 URL — 它必须返回有效配置(JWT 兼容性检查)
  2. 检查用户数量:docker exec nexus-panel sqlite3 /var/lib/panel/db.sqlite3 'SELECT COUNT(*) FROM users;'
  3. 运行 nexus cli migrate post-cutover 以扫描残留的 Marzban 守护进程(marzguard、certbot cron 钩子)
  4. 如果你使用 Hysteria2:添加入站 + 为每个节点添加一个主机(参见 Hysteria2 章节
  5. 通过 控制面板 → 节点 重新添加节点(新证书,端口 62060/62061)
  6. 稳定后运行 nexus cli migrate finalize 以释放快照
bash — 快速验证
# 健康检查
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 迁移

通俗地说
已经在跑 Remnawave 面板?用一条命令把用户迁移过来——包括他们各自的订阅链接。默认是预演模式:只连接、提取并报告将要导入的内容(以及任何用户名冲突),不写入任何数据;确认无误后加 --run 才会真正执行。

nexus cli migrate remnawave 通过 Remnawave 的管理员 REST API 读取源面板(而非直连数据库),所以只需要面板 URL 和一个管理员账号:

bash
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 等):

  1. 在控制面板中前往 设置
  2. 点击 启用 2FA
  3. 用你的身份验证器 App 扫描二维码
  4. 输入 6 位验证码以确认
  5. 恢复码保存在安全的地方

通过 API:

bash
# 生成 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

env
CAPTCHA_PROVIDER="turnstile"
TURNSTILE_SITE_KEY="0x4AAAAAAA..."
TURNSTILE_SECRET_KEY="0x4AAAAAAA..."

内置验证码

env
CAPTCHA_PROVIDER="builtin"

内置验证码无需任何外部服务,会生成简单的数学题挑战。

速率限制

登录端点的速率限制默认启用:

env
LOGIN_RATE_LIMIT="10/minute"
LOGIN_LOCKOUT_THRESHOLD=10
LOGIN_LOCKOUT_DURATION_MINUTES=30

10 次失败尝试后,该 IP 会被锁定 30 分钟。速率限制器在内存中(按进程),服务器重启后重置。

SSL / TLS

对于生产环境部署,始终使用 HTTPS。可选方案包括:

  • 直接 SSL — 设置 UVICORN_SSL_CERTFILEUVICORN_SSL_KEYFILE
  • 反向代理 — 在前端使用 Nginx 或 Caddy 进行 SSL 终止
  • Cloudflare — 以 Full (Strict) SSL 模式通过 Cloudflare 代理

Nginx 反向代理示例

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:

bash
curl -X PUT /api/v1/admin/admin \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"password": "newSecurePassword123"}'

如何备份

SQLite

bash
# 为获得干净的备份,请先停止面板
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

bash
docker compose exec db pg_dump -U nexus nexuspanel > /backups/db-$(date +%Y%m%d).sql
提示
同时也要备份你的 .envxray_config.json 以及任何自定义模板。

如何更新

bash
cd /opt/nexuspanel

# 拉取最新镜像
docker compose pull

# 用新版本重启
docker compose up -d

# 查看日志了解迁移状态
docker compose logs -f panel

数据库迁移会在启动时自动运行。更新前请始终备份你的数据库。

如何添加自定义模板

自定义模板让你能够控制面向各类客户端的订阅输出:

  1. 在模板目录中创建你的模板文件:
bash
mkdir -p /var/lib/nexuspanel/templates/clash
nano /var/lib/nexuspanel/templates/clash/custom.yml
  1. .env 中引用该模板:
env
CUSTOM_TEMPLATES_DIRECTORY="/var/lib/panel/templates/"
CLASH_SUBSCRIPTION_TEMPLATE="clash/custom.yml"

模板支持 Jinja2 语法,可访问用户数据、代理配置和面板设置。

订阅页面定制

面向用户的订阅页面(在浏览器中访问订阅链接时显示)完全可定制:

  1. 复制默认模板作为起点:
bash
cp -r /opt/nexuspanel/app/templates/subscription \
  /var/lib/nexuspanel/templates/subscription
  1. 编辑 /var/lib/nexuspanel/templates/subscription/index.html
  2. .env 中设置:
env
SUBSCRIPTION_PAGE_TEMPLATE="subscription/index.html"

可用的模板变量包括:usersub_urlclash_urlsingbox_urlusageexpire_datebrand_name


NexusPanel 文档 — 用心打造。