PVE 宿主机上编辑 /etc/pve/lxc/容器ID.conf,添加

lxc.cgroup2.devices.allow: c 10:200 rwm
lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file

如果不开启,就会创建tun设备失败。

进入lxc执行ip转发设置

  • 永久开启:

    echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
    
  • 实际情况,由于这个容器并没有启动标准的 Linux 初始化系统(没有运行 OpenRC 或 Systemd)。它开机后,内核直接把 PID 1 交给了 Entrypoint 里的命令。也就是说,它根本不会去读取 /etc/local.d 或者 /etc/init.d 里的任何自启动脚本。所以上面设置的开启转发并没有在启动的时候加载

  • 为了加载转发设置,需要执行sysctl -p

    • 在 PVE 网页端,双击Entrypoint那一行进行编辑
    • 将原本的内容:./entrypoint.sh
    • 修改为(利用 shell 将两个命令串联):/bin/sh -c "sysctl -p; ./entrypoint.sh"

页面设置-基础信息

experimental设置

  • 2026-03-28-lxc容器项目创建-20260404181641-2026-04-04-18-16-45

启用 (Enable):

打开。 如果不打开,下方的设置都不会生效。

外部控制器 (External Controller):

默认是 127.0.0.1:9090

  • 本地使用: 保持默认 127.0.0.1:9090
  • 远程控制: 如果你想在另一台电脑或手机上访问这个 PVE 上的控制面板,请改为 0.0.0.0:9090(表示监听所有网卡)。

密钥 (Secret):

选填,建议填一个简单的密码。

  • 这是访问控制面板时的验证密码。留空则不需要密码。

外部界面 (External UI):

填写存放面板文件的目录名,例如 ui

  • 如果你已经手动下载了面板文件(如 yacd),请填入文件夹名称。
界面下载地址:

推荐填入以下常用的面板地址之一(如果你还没下载的话):

  • https://github.com/MetaCubeX/Yacd-meta/archive/gh-pages.zip
  • https://github.com/MetaCubeX/metacubexd/archive/gh-pages.zip

默认模式:

通常填 rule(绕过大陆/按规则分流),也可以填 global(全局)或 direct(直连)。

允许来源(Allowed Origins)

这个选项对应配置中的 access_control_allow_origin,本质上是处理 CORS(跨域资源共享) 的。

  • 具体意义: 当你使用浏览器访问控制面板(比如 Yacd)时,浏览器会出于安全考虑,检查该网页是否有权向 9090 端口发送请求。
  • 填写建议:
    • 一般留空: 留空在大多数 sing-box 版本中默认表示允许所有。
    • 填写 * 明确表示允许任何域名的网页来连接这个后端(最省事,推荐)。
    • 特定场景: 如果你把控制面板托管在一个特定的域名上(如 http://my-dashboard.com),出于安全考虑,你可以只填这个域名。

允许私有网络(Allow Private Network)

这是为了适配现代浏览器(尤其是 Chrome)的一个新安全特性:私有网络访问限制 (PNA)

  • 具体意义: 谷歌浏览器现在默认禁止“公网网页”直接请求你“内网地址”的资源。
    • 例如:你访问的是 http://yacd.haishanh.com(公网地址),但你填写的后端是 http://192.168.3.242:9090(私有内网地址)。
    • 如果没有开启这个开关,浏览器会报 Preflight request error,导致你连不上后端。
  • 填写建议: 保持开启(蓝色)
    • 尤其是在你使用在线版控制面板,或者跨设备(用手机访问 PVE 上的 sing-box)时,这个选项非常关键。

页面设置-设置

订阅

  • 地址:监听地址,默认留空即可
  • 端口:默认2096
  • 域名:根据实际情况填写,直接填写域名,不带任何端口号
    • 可以填写TLS节点里设置的地址,比如node.example.com
    • 可以在NPM里设置转发,然后填写NPM里设置的域名,比如sub.example.cn
    • 也可以留空,直接用ip访问 或者 直接使用npm代理的域名进行访问
    • 如果 域名留空,并且订阅URL也为空,那最终进行拼接的时候,它会识别sui所在的ip,最终拼接得到的订阅地址就是:http://192.168.3.254:2096/sub/username
  • SSL.key及SSL.cert:如果不是通过类似nginx代理的,并且需要使用https的,就应该填写域名证书存放的真实地址
  • 默认路径:自由设置,比如/sub/
  • 订阅URL:
    • 如果此处不填写,
      • 最终订阅地址形式:域名+端口+默认路径+用户名的拼接
        • 订阅地址:https://sub.example.cn:port/sub/用户名
        • json订阅地址:订阅地址+"?format=json"
        • https://sub.example.cn:port/sub/用户名?format=json
    • 此处填写具体的订阅地址
      • 一旦这里写了地址之后,最终的定义地址就以此处的为准,不再进行 域名+端口+默认路径+用户名 拼接
      • 地址填写的时候,应该是能访问sui所在的2096端口对应的地址,并且要带上默认路径,比如:https://sub.example.cn:port/sub/
      • 最终订阅地址;
        • 订阅地址订阅URL+用户名
        • json订阅地址:订阅地址+?format=json
  • 建议:
    • 如果是在局域网内部署,并且希望公网访问,直接填写订阅URL,这样可以省去好多未知拼接问题
    • 比如在局域网内的NPM映射了sub.example.cn192.168.3.254:2096,并且在路由器中进行了NAT转发,针对NPM所在的内网ip比如192.168.3.253,设置公网1443与内网443的转发,那么订阅URL直接填写https://sub.example.cn:1443/sub/

JSON订阅

  • 就是把诸如DNSroute等信息一并写入订阅信息中,拉取订阅获取到的是一个可运行的完整的config.json 2026-03-28-lxc容器项目创建-20260405173618-2026-04-05-17-36-21
  • json订阅地址:订阅地址+?format=json
    • https://sub.example.cn:port/sub/用户名?format=json