145 lines
4.7 KiB
Markdown
145 lines
4.7 KiB
Markdown
# Proxmox client API
|
|
|
|
The ProxMenu client uses two HTTPS requests. It never receives Git
|
|
credentials.
|
|
|
|
## Exchange a deployment code
|
|
|
|
`POST https://tapm.example.com/api/v1/exchange`
|
|
|
|
```json
|
|
{
|
|
"code": "TAPM-ABCDE-FGHIJ",
|
|
"host_fingerprint": "sha256-of-the-host-machine-id",
|
|
"hostname": "pve01",
|
|
"installation_id": "123e4567-e89b-42d3-a456-426614174000",
|
|
"requested_action": "install-rmm",
|
|
"requested_package": ""
|
|
}
|
|
```
|
|
|
|
Successful response:
|
|
|
|
```json
|
|
{
|
|
"session_token": "opaque-session-token",
|
|
"expires_at": "2026-07-25T23:30:00Z",
|
|
"packages": [
|
|
{
|
|
"slug": "sentinelone-linux",
|
|
"display_name": "SentinelOne Linux Agent",
|
|
"version": "26.1.1.31",
|
|
"sha256": "64-lowercase-hexadecimal-characters",
|
|
"download_url": "https://tapm.example.com/api/v1/packages/sentinelone-linux"
|
|
}
|
|
],
|
|
"actions": [
|
|
"install-rmm",
|
|
"install-acronis",
|
|
"install-screenconnect"
|
|
]
|
|
}
|
|
```
|
|
|
|
The first exchange enrolls that host against the authorization. Reusing the
|
|
same code and host fingerprint does not consume another host slot. A different
|
|
fingerprint consumes one slot until the configured limit is reached.
|
|
Package authorizations grant access by stable package slug. The version,
|
|
filename, and checksum in a response are resolved from the current package
|
|
catalog when the code is exchanged; replacing a package does not require a new
|
|
authorization code.
|
|
When `requested_action` or `requested_package` is present, the broker validates
|
|
that entitlement before enrolling the host. Older clients may omit both fields,
|
|
but current clients should always identify what they intend to use.
|
|
Current V2 clients also send their random `installation_id`. A successful
|
|
code exchange marks the matching fleet record as verified; it does not expose
|
|
or replace the host's fleet credential.
|
|
|
|
An installer must proceed only when its required package slug or action slug is
|
|
present in this response. The current action slugs are:
|
|
|
|
- `install-rmm`
|
|
- `install-acronis`
|
|
- `install-screenconnect`
|
|
|
|
## Download a package
|
|
|
|
Send the session from the exchange:
|
|
|
|
```sh
|
|
curl --fail --location \
|
|
--header "Authorization: Bearer SESSION_TOKEN" \
|
|
--output /tmp/package.deb \
|
|
'https://tapm.example.com/api/v1/packages/sentinelone-linux'
|
|
```
|
|
|
|
The client must calculate SHA-256 after download and compare it to the value
|
|
returned by the exchange. It must delete the file and stop if the values differ.
|
|
The server also returns the expected value in `X-TAPM-SHA256`.
|
|
|
|
## Status behavior
|
|
|
|
- `400`: malformed request
|
|
- `403`: invalid, expired, revoked, or exhausted authorization
|
|
- `429`: too many failed exchanges from the source address; retry after the
|
|
`Retry-After` interval
|
|
- `502`: private package registry unavailable
|
|
|
|
Codes and sessions expire at the same authorization deadline. Revoking an
|
|
authorization immediately invalidates all of its sessions.
|
|
|
|
## Fleet registration
|
|
|
|
V2 clients register a locally generated installation identity:
|
|
|
|
`POST https://tapm.example.com/api/v1/hosts/register`
|
|
|
|
```json
|
|
{
|
|
"schema_version": 1,
|
|
"installation_id": "123e4567-e89b-42d3-a456-426614174000",
|
|
"hostname": "pve01",
|
|
"credential": "64-lowercase-hexadecimal-characters",
|
|
"proxmenu_version": "2026.7.26-7",
|
|
"git_commit": "40-lowercase-hexadecimal-characters",
|
|
"pve_version": "pve-manager/9.0.3/abc~1",
|
|
"os_version": "Debian GNU/Linux 13 (trixie)",
|
|
"kernel_version": "6.14.11-2-pve",
|
|
"architecture": "amd64",
|
|
"clustered": false
|
|
}
|
|
```
|
|
|
|
The first request returns `201`; subsequent authenticated registrations return
|
|
`200`. The broker stores a SHA-256 digest of the 256-bit random credential, not
|
|
the credential itself. New registrations are limited per privacy-preserving
|
|
HMAC of the source address to reduce anonymous registry abuse.
|
|
|
|
## Fleet lifecycle events
|
|
|
|
`POST https://tapm.example.com/api/v1/hosts/events`
|
|
|
|
The request uses `Authorization: Bearer HOST_CREDENTIAL`. Its body has the same
|
|
schema and platform metadata as registration, omits `credential`, and adds:
|
|
|
|
```json
|
|
{
|
|
"event": "run_completed",
|
|
"result": "success",
|
|
"error_code": "",
|
|
"duration_seconds": 19
|
|
}
|
|
```
|
|
|
|
Accepted events are `run_started`, `run_completed`, `run_failed`, and
|
|
`upgraded`. Events are best-effort and are sent only while TA-ProxMenu is
|
|
running; there is no resident monitoring service.
|
|
|
|
The fleet API stores the reported hostname as a limited operational identifier.
|
|
It deliberately does not accept or store machine IDs, MAC addresses, usernames,
|
|
VM/container inventory, deployment tokens, credentials, or command output. The
|
|
portal shows hostname, random installation ID, first and last activity,
|
|
verification status, software/platform versions, cluster mode, and the latest
|
|
structured result. A record becomes verified only after the same installation
|
|
ID is included in a successful deployment-code exchange.
|