PufferPanel 3.0.9 API 使用详解
PufferPanel 3.0.9 REST API 实战:认证与会话、端点全景、用户/服务器/模板/节点四域实测、请求响应约定与踩坑 FAQ,全示例实测于 Ubuntu 22.04。
PufferPanel 3.0.9 API 使用详解
目标:面向需要用脚本/程序化管理面板的运维与集成开发者,讲清 PufferPanel 3.0.9 REST API 的认证方式、端点全景、请求/响应约定与高频调用实测。文中每个 curl 命令、响应体、状态码均来自 Ubuntu 22.04.5 + PufferPanel 3.0.9 实测环境(实测日期 2026-10-24),示例统一使用管理员账号
admin(密码按安全规范以${PASSWORD}占位展示,实测时为真实值)。
一、环境信息
- 操作系统:Ubuntu 22.04.5 LTS(x86_64)
- 面板版本:PufferPanel 3.0.9(
pufferpanel version→PufferPanel 3.0.9 (94ded99f2d691762c09c6df076a2f76c475b481e)) - API 基地址:
http://127.0.0.1:8080(生产环境替换为https://<域名>,建议反代终结 TLS) - 客户端:curl 7.81(Ubuntu 22.04 自带),认证方式为会话 Cookie
- 测试对象:真实创建的管理员用户、测试用户
gameop、以echotest模板创建的服务器实例echo1(占位进程,见《安装指南》篇)
二、前置条件
- 运行中的面板:3.0.9 服务 active(
systemctl is-active pufferpanel→active),Web 端口可达(默认 8080)。 - 管理员账号:
pufferpanel user add --admin创建;管理员持有全部权限域,可调用全部 API。 - 工具:curl(或任意 HTTP 客户端);WebSocket 场景(控制台实时流)需支持 WS 的客户端,本文聚焦 REST。
- 认证认知:面板登录走
POST /auth/login(不是/api/auth/login,404 踩坑见 §七),成功后以puffer_auth会话 Cookie 访问/api/*。除会话外,面板还支持 OAuth2 客户端、Passkey、免密登录与 TOTP 双因素(来源:Web 前端路由实测枚举/api/self/oauth2、/api/self/otp、/api/self/passkey、/api/self/passwordless/*)。
三、API 总览
面板 REST API 与 Web UI 共用 8080 端口,API 前缀 /api。域全景如下(端点清单经实测与前端资源核对,查询日期 2026-10-24):
| 域 | 前缀 | 说明 | 实测状态 |
|---|---|---|---|
| 认证 | POST /auth/login、/auth/logout | 登录换会话 Cookie / 登出 | ✓ 200 / 200 |
| 当前用户 | GET /api/self | 当前登录者信息与权限域 | ✓ 200 |
| 用户管理 | /api/users、/api/users/:id | 用户 CRUD、权限域管理 | ✓ 创建/列表 200 |
| 服务器 | /api/servers、/api/servers/:id | 服务器 CRUD、电源、控制台、文件、备份、任务 | ✓ 全链路 200/202/204 |
| 节点 | /api/nodes、/api/nodes/:id | 面板所辖节点(含本机 LocalNode)与远程节点注册 | ✓ 200 |
| 模板 | /api/templates/:repoId/:name | 模板仓库(0=Local 本地,1=community 社区源)与模板读写 | ✓ 保存 204/读取 200 |
| 面板配置 | GET /api/config | 面板可见配置(品牌/注册开关/主题等) | ✓ 200 |
| 系统设置 | /api/settings(含 /settings/test/email) | 系统级设置与邮件连通性测试 | 端点实测枚举 |
| 用户偏好 | /api/userSettings | 当前用户界面偏好 | 端点实测枚举 |
另有面板↔守护进程内部调用路径 POST /daemon/server/<id>/start|stop|kill|install(实测日志捕获),供理解架构,外部集成请走 /api/* 公开接口。
3.1 权限域(Scopes)概念
API 鉴权围绕权限域展开:管理员账号登录响应直接携带 "scopes":["admin"];普通用户按授权范围持有 server.view、server.console.send、server.files.edit、server.sftp 等约 30 个作用域(创建用户实测请求体即传入 "scopes":["server.view"])。用低权限会话调用未授权 API 会收到权限错误而非静默放行,集成侧应按最小权限原则为集成账号只授予所需作用域。
四、认证与首次调用
4.1 登录并保存会话
curl -s -X POST http://127.0.0.1:8080/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"${PASSWORD}"}' \
-c /root/ck.txt -i | head -8
实测回显:
HTTP/1.1 200 OK
Content-Type: application/json
Set-Cookie: puffer_auth=<uuid>; Path=/; Expires=...; Max-Age=3600; HttpOnly
Date: Fri, 24 Oct 2026 03:21:14 GMT
Content-Length: 45
{"scopes":["admin"],"needsSecondFactor":false}
要点:会话 Cookie puffer_auth 为 HttpOnly,有效期 3600 秒(1 小时),过期需重新登录;needsSecondFactor 在账号启用 TOTP 后返回 true,需要第二因素(本例账号未启用为 false)。后续所有请求带 -b /root/ck.txt 复用该会话。
4.2 首个业务调用:当前用户
curl -s -b /root/ck.txt http://127.0.0.1:8080/api/self -w "\n[HTTP %{http_code}]\n"
实测回显(节选):
{"id":1,"username":"admin","email":"admin@example.com","scopes":{"global":["admin"],"servers":null},"servers":null}
[HTTP 200]
scopes.global 即权限域,管理员为 ["admin"]。未认证直接调用返回 401(权限拒绝,JSON 错误体,见 §六)。
五、API 域详解(实测)
5.1 用户管理:/api/users
创建用户(用户名/邮箱/密码/权限域,实测创建 gameop):
curl -s -b /root/ck.txt -X POST http://127.0.0.1:8080/api/users \
-H "Content-Type: application/json" \
-d '{"username":"gameop","email":"gameop@example.com","password":"${PASSWORD}","scopes":["server.view"]}' \
-w "\n[HTTP %{http_code}]\n"
实测回显:
{"data":null,"error":null,"scopeMap":null,"user":{"id":2,"username":"gameop","email":"gameop@example.com","scopes":{"global":["server.view"],"servers":null},"servers":null}}
[HTTP 200]
用户列表:
curl -s -b /root/ck.txt http://127.0.0.1:8080/api/users
实测回显(节选,paging 为分页元数据,data 为用户数组):
{"paging":{"offset":0,"size":100,"total":2,"sortField":"","sortOrder":"asc"},"error":null,"data":[{...admin...},{...gameop...}],"scopeMap":null,"user":null}
💡 技术拓展:响应包络统一为
{paging, error, data, scopeMap, user}五段。scopeMap用于带出权限域字典,user在涉及单用户资源时携带主体。分页经查询参数控制偏移与条数(paging段回显当前值),列表接口均可按此遍历。
5.2 模板管理:/api/templates
模板分仓库存储:/api/templates/0 为 Local(本地模板,可在面板内自建),/api/templates/1 为内置 community 仓库源(GitHub pufferpanel/templates v3 分支,实测列表返回该源元数据)。保存本地模板用 PUT(POST 是 404):
curl -s -b /root/ck.txt -X PUT http://127.0.0.1:8080/api/templates/0/echotest \
-H "Content-Type: application/json" \
-d '{"type":"echo","display":"Echo Test","install":[],"run":{"stop":"","pre":[],"post":[],"command":"sleep 600","environmentVars":{}},"environment":{"type":"standard"},"data":{}}' \
-w "\n[HTTP %{http_code}]\n"
实测回显:
[HTTP 204]
204 无响应体即保存成功。读取确认(实测回显为存储后的全量结构,系统补齐了 autostart/autorestart/stats/query/keepAlive 等默认字段):
curl -s -b /root/ck.txt http://127.0.0.1:8080/api/templates/0/echotest
{"name":"echotest","display":"Echo Test","install":[],"uninstall":[],"run":{"stop":"","pre":[],"post":[],"command":"sleep 600","environmentVars":{},"stdin":{"type":"stdin"},"workingDirectory":""},"environment":{"type":"standard"},"data":{},"autostart":false,"autorecover":false,"autorestart":false,"requirements":{},"stats":{"cpuUsage":0,"memoryUsage":0},"query":{"port":0,"ip":""},"keepAlive":false}
Schema 易错点(实测踩坑沉淀):install 必须是数组(每项为安装处理器/操作,可带 condition 条件);type 为模板类型标识。传错结构会收到精确的 Go 校验错误,如 json: cannot unmarshal object into Go struct field Server.install of type []pufferpanel.ConditionalMetadataType——按错误信息反推字段类型即可。
5.3 服务器管理:/api/servers
创建服务器:PUT 到以服务器 ID 命名的路径(幂等语义),完整请求体(实测成功版本):
curl -s -b /root/ck.txt -X PUT http://127.0.0.1:8080/api/servers/echo1 \
-H "Content-Type: application/json" \
-d '{"name":"echo1","node":0,"users":["admin"],"type":"echotest","data":{},"environment":{"type":"standard"},"install":[],"run":{"command":"sleep 600","stop":"","pre":[],"post":[],"environmentVars":{}},"requirements":{}}' \
-w "\n[HTTP %{http_code}]\n"
实测回显:
{"id":"echo1"}
[HTTP 200]
创建请求体关键约定(均为实测踩坑后确认):
node: 0 表示本机 LocalNode(整型,不是字符串);users: 字符串数组(用户名列表),传对象数组会报json: cannot unmarshal object into Go struct field ServerCreation.users of type string;type: 顶层字符串,值为模板名("echotest"),嵌套对象会报ServerCreation.Server.Type.type of type string校验错误;data: 模板变量覆盖(端口/内存等,此处留空使用模板默认)。
查询与权限:
curl -s -b /root/ck.txt "http://127.0.0.1:8080/api/servers/echo1?perms"
实测回显(节选):服务器对象含 id/name/node/users/permissions 与权限映射,?perms 参数令响应额外携带权限表,便于集成侧渲染控制项。
电源操作(均为异步,202 Accepted 即受理):
curl -s -b /root/ck.txt -X POST http://127.0.0.1:8080/api/servers/echo1/install -w "\n[%{http_code}]\n" # 安装钩子
curl -s -b /root/ck.txt -X POST http://127.0.0.1:8080/api/servers/echo1/start -w "\n[%{http_code}]\n" # 启动
curl -s -b /root/ck.txt -X POST http://127.0.0.1:8080/api/servers/echo1/stop -w "\n[%{http_code}]\n" # 优雅停止
curl -s -b /root/ck.txt -X POST http://127.0.0.1:8080/api/servers/echo1/kill -w "\n[%{http_code}]\n" # 强杀
实测回显:install/start/stop 返回 [202],kill 返回 [204]。状态需另行查询:
curl -s -b /root/ck.txt http://127.0.0.1:8080/api/servers/echo1/status
{"running":true,"installing":false}
控制台读取:GET /api/servers/echo1/console 返回 base64 编码的最近日志(daemon.console.buffer 控制容量),实测解码后:
[DAEMON] Installing server
[DAEMON] Server installed
[DAEMON] Starting server
[DAEMON] Starting process: sleep 600
发送命令走 POST /api/servers/echo1/console(body {"command":"..."});实时推流由 WebSocket 提供,本篇以 REST 轮询为准。
资源统计:
curl -s -b /root/ck.txt http://127.0.0.1:8080/api/servers/echo1/stats
{"cpu":0,"memory":1986560}
memory 单位字节(约 1.9MB,符合占位进程预期)。其余子资源(/data 文件、/file/* 归档解压、/backup 备份、/tasks 任务、/flags 运行标志、/query 查询状态)与文件管理器/备份/任务 UI 一一对应,均遵循同一认证与会话约定(来源:3.0.9 源码路由核对 + 前端调用核对,查询日期 2026-10-24)。
5.4 节点与配置:/api/nodes、/api/config
curl -s -b /root/ck.txt http://127.0.0.1:8080/api/nodes
实测回显(节选):返回 LocalNode 对象,含 id: 0、公网地址与端口(按 masterUrl 自动探测生成,Docker 部署实测为 publicHost:<宿主IP>, publicPort:8139)、面向远程节点的 clientId/clientSecret 凭据字段。
curl -s -b /root/ck.txt http://127.0.0.1:8080/api/config
实测回显(节选):
{"general":{"registrationEnabled":false,...},"branding":{"name":"Quzuo Game Panel",...}}
该端点为面板可见配置的权威视图,与《配置参数详解》篇 §五.2 的改值实验互相印证。
六、通用约定
- 方法语义:创建与更新大量使用 PUT(对资源路径幂等写,如
PUT /api/servers/<id>、PUT /api/templates/0/<name>);触发型动作(电源、安装)用 POST;删除为 DELETE。GET 传错方法直接 404,先确认方法再排查路径。 - 状态码:200 成功;204 成功无内容;202 已受理异步执行(电源/安装类,需轮询 status);401 未认证;404 路径不存在;校验失败返回 400/500 级错误,响应体为
{error: <原因>}结构。 - 认证:
puffer_authHttpOnly 会话 Cookie(1 小时有效期),登出POST /auth/logout;集成账号建议单独创建并只授予所需权限域,避免复用管理员会话。 - 分页:列表响应
paging段含 offset/size/total/sortField/sortOrder,遍历按 offset 递增取页。 - 幂等与并发:PUT 幂等语义使重试安全;电源操作为异步受理,勿以 202 判定执行结果,以 status 查询为准。
七、常见问题(FAQ)
Q1:/api/auth/login 返回 404?
登录端点在 /auth/login(不在 /api 前缀下),实测复现 404 后修正。认证类端点(登录/登出)不带 /api 前缀,其余管理域均在 /api/* 下。
Q2:创建服务器报 users 类型错误?
users 是用户名字符串数组:"users":["admin"]。传对象数组([{"username":"admin"}])报 json: cannot unmarshal object into Go struct field ServerCreation.users of type string(实测复现)。
Q3:创建服务器报 Type: required?
顶层 type 必须是模板名字符串:"type":"echotest"。传成 {"type":{"type":"echotest"}} 会触发 ServerCreation.Server.Type.type of type string 校验错误(实测复现)。
Q4:模板保存 POST 404?
本地模板保存用 PUT:PUT /api/templates/0/<名称>(实测 POST 404、PUT 204)。
Q5:stop 之后 running 仍是 true?
stop 走模板定义的优雅停机命令,run.stop 为空时对无响应进程无效(实测 5 秒后仍 {"running":true});强杀用 POST /api/servers/echo1/kill(实测 204,状态立即翻转)。模板层修复见《安装指南》篇 Q6。
Q6:会话突然 401?
会话 1 小时过期(Set-Cookie Max-Age=3600 实测),重新登录换新 Cookie;启用了 TOTP 的账号还需第二因素流程。
Q7:想在日志里看到游戏服务器输出?
开 daemon.console.forward 后服务器输出进入 journald(journalctl -u pufferpanel,实测 [echo1] 前缀输出),REST 侧仍以 /console 轮询为主。
八、参考链接
- PufferPanel 3.0.9 源码(API 路由与结构定义的权威依据):https://github.com/PufferPanel/PufferPanel/tree/v3.0.9
- 官方文档 Configuration(配置与会话参数):https://docs.pufferpanel.com/en/3.x/guides/config.html
- 官方文档 Creating Node(远程节点与 clientId/clientSecret):https://docs.pufferpanel.com/en/3.x/guides/create-node.html
- 模板定义规范(install/run/environment/data 四段结构):https://docs.pufferpanel.com/en/3.x/templates/templates.html
- 站内延伸阅读:《PufferPanel 3.0.9 介绍与选型指南》《PufferPanel 3.0.9 安装指南(Ubuntu 22.04)》《PufferPanel 3.0.9 配置参数详解》