A wrapper for the proxmox api
Project description
proxio
An async Python wrapper for the Proxmox API, built on httpx and pydantic.
Installation
pip install proxio
Requires Python 3.8+.
Authentication
proxio uses Proxmox API tokens. Create one in the Proxmox web UI under Datacenter → Permissions → API Tokens → Add.
The token string must be in the format:
user@realm!tokenid=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Quick Start
import asyncio
from proxio.client import ProxmoxClient
async def main():
async with ProxmoxClient(
host="192.168.1.10",
token="root@pam!mytoken=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
verify=False, # set True to verify TLS certificate
) as client:
async for node in client.get_nodes():
print(node)
asyncio.run(main())
ProxmoxClient
ProxmoxClient(host, token, verify=True, trust_env=True)
| Parameter | Description |
|---|---|
host |
Hostname or IP of the Proxmox server (without scheme or port) |
token |
API token string in user@realm!tokenid=secret format |
verify |
Verify TLS certificate (default True) |
trust_env |
Respect proxy environment variables (default True) |
Client methods
| Method | Description |
|---|---|
get_nodes() |
Async generator yielding all Node objects in the cluster |
get_node(name) |
Return a single Node by name, raises LookupError if not found |
next_vmid() |
Return the next free VMID in the cluster |
Node
Represents a Proxmox node. Returned by client.get_nodes() / client.get_node().
Static fields
| Field | Type | Description |
|---|---|---|
name |
str |
Node name |
node_type |
str |
Node type |
maxcpu |
int |
Number of CPUs |
maxmem |
int |
Maximum memory in bytes |
maxdisk |
int |
Maximum disk in bytes |
Node methods
| Method | Description |
|---|---|
get_status() |
Returns status string (e.g. "online", "offline") |
get_cpu() |
Current CPU usage (float) |
get_mem() |
Current memory usage in bytes |
get_disk() |
Current disk usage in bytes |
get_uptime() |
Uptime in seconds |
get_runtime() |
Raw runtime dict from the API |
list_vms(template=None, name=None) |
List VMs; filter by template flag or name (supports glob patterns) |
get_vm(vmid=None, name=None) |
Get a single VM by VMID and/or name (glob supported), raises LookupError |
VirtualMachine
Represents a QEMU virtual machine on a node.
Static fields
| Field | Type | Description |
|---|---|---|
vmid |
int |
VM ID |
name |
str |
VM name |
node |
str |
Node the VM lives on |
cpus |
int |
Number of CPUs |
maxmem |
int |
Allocated memory in bytes |
maxdisk |
int |
Allocated disk in bytes |
tags |
str |
Comma-separated tags |
template |
bool |
Whether the VM is a template |
agent |
VmAgent |
Guest agent interface |
Power state methods
| Method | Description |
|---|---|
start(timeout=300) |
Start VM and block until running |
stop(timeout=300) |
Stop VM and block until stopped |
shutdown(timeout=300) |
Graceful shutdown, block until stopped |
reset(timeout=300) |
Reset VM |
suspend(timeout=300) |
Suspend VM |
resume(timeout=300) |
Resume VM |
Runtime methods
| Method | Description |
|---|---|
get_status() |
Returns status string (e.g. "running", "stopped") |
get_cpu() |
Current CPU usage (float) |
get_mem() |
Current memory usage in bytes |
get_uptime() |
Uptime in seconds |
get_runtime() |
Raw runtime dict from the API |
get_config() |
Raw config response from the API |
Lifecycle methods
| Method | Description |
|---|---|
clone(name, *, newid, description, snapname, target, pool, full, storage, bwlimit, timeout) |
Clone VM, returns new VirtualMachine |
migrate(data, timeout=600) |
Migrate VM to another node |
delete(timeout=300) |
Delete VM |
snapshot(snapname, description, timeout) |
Create a snapshot |
rollback(snapname, timeout) |
Rollback to a snapshot |
list_snapshots() |
List snapshots (raw response) |
VmAgent
Accessed via vm.agent. Provides access to the QEMU guest agent.
| Method | Description |
|---|---|
ping() |
Verify the guest agent is responsive |
exec(command, args, input_data, timeout, poll_interval) |
Execute a command in the guest, returns dict with exitcode, out-data, err-data |
get_osinfo() |
OS information from the guest |
get_hostname() |
Hostname from the guest, or None if not running |
get_network_interfaces() |
Network interface list from the guest |
get_fsinfo() |
Filesystem information from the guest |
get_users() |
Logged-in users from the guest |
set_user_password(username, password, crypted) |
Set a guest user password |
file_read(path) |
Read a file from the guest, returns bytes |
file_write(path, content) |
Write bytes to a file in the guest |
Examples
List all nodes
import asyncio
from proxio.client import ProxmoxClient
async def main():
async with ProxmoxClient(host="192.168.1.10", token="root@pam!mytoken=...", verify=False) as client:
async for node in client.get_nodes():
print(node.name, await node.get_status())
asyncio.run(main())
List VMs on a node
node = await client.get_node("pve")
vms = await node.list_vms()
for vm in vms:
print(vm.vmid, vm.name, await vm.get_status())
Filter VMs by name (glob)
vms = await node.list_vms(name="web-*")
Clone a VM from a template
template = await node.get_vm(name="ubuntu-template")
new_vm = await template.clone("my-new-vm", full=True, storage="local-lvm")
await new_vm.start()
Run a command in a guest
result = await vm.agent.exec("hostname")
print(result["out-data"])
Using a .env file (examples)
Copy examples/.env.example to examples/.env and fill in your credentials:
PROX_API_TOKEN=root@pam!mytokenid=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
PROX_HOST=192.168.1.10
Then run:
uv run examples/list_nodes.py
Development
Run tests
pytest --cov=proxio --cov-report=term
Build
hatch build
Publish
hatch publish
GitHub Flow & Publishing to PyPI
How it works
Publishing is fully automated via GitHub Actions using PyPI Trusted Publishing (OIDC) — no API tokens or passwords are needed.
The workflow (.github/workflows/publish.yml) triggers automatically when a GitHub Release is published:
- Tests run — the full test suite must pass on Ubuntu before anything is published.
- Build —
hatch buildproduces an sdist and a wheel. - Publish — the package is uploaded to PyPI using a short-lived OIDC token issued by GitHub. This requires the
releaseenvironment to be configured on PyPI.
One-time PyPI setup (Trusted Publishing)
- Go to pypi.org → your project → Manage → Publishing.
- Add a new Trusted Publisher with these values:
- Owner:
rogerbrinkmann - Repository:
proxio - Workflow filename:
publish.yml - Environment:
release
- Owner:
- Create a
releaseenvironment in your GitHub repo under Settings → Environments.
Releasing a new version
- Bump the version in
proxio/__init__.py:__version__ = "0.1.0"
- Commit and push to
main. - On GitHub, go to Releases → Draft a new release.
- Create a new tag matching the version (e.g.
v0.1.0), fill in the release notes, and click Publish release. - The workflow starts automatically — tests run, then the package is built and uploaded to PyPI.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file proxio-0.0.4.tar.gz.
File metadata
- Download URL: proxio-0.0.4.tar.gz
- Upload date:
- Size: 16.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dad23f32b49a22f079c486f42774d2a115844b04735ac241a5457cdae761490d
|
|
| MD5 |
674be31d9e7191b7a43d78944c6c583f
|
|
| BLAKE2b-256 |
8635c02232af8767d300c9c4d4b6c3ad47b88b634b45ab111d14395a43acc3b3
|
Provenance
The following attestation bundles were made for proxio-0.0.4.tar.gz:
Publisher:
publish.yml on RogerBCode/proxio
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
proxio-0.0.4.tar.gz -
Subject digest:
dad23f32b49a22f079c486f42774d2a115844b04735ac241a5457cdae761490d - Sigstore transparency entry: 1340473994
- Sigstore integration time:
-
Permalink:
RogerBCode/proxio@1627a7628ad19d3768d678dfae92153c54885aa0 -
Branch / Tag:
refs/tags/0.0.4 - Owner: https://github.com/RogerBCode
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@1627a7628ad19d3768d678dfae92153c54885aa0 -
Trigger Event:
release
-
Statement type:
File details
Details for the file proxio-0.0.4-py3-none-any.whl.
File metadata
- Download URL: proxio-0.0.4-py3-none-any.whl
- Upload date:
- Size: 16.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f7610affc1edfc869d4627bc1dc1ca411bb3acb40b60e29bb60fc9164495d417
|
|
| MD5 |
bf810f9ed59bf9dac3ad0dd9f4b545c2
|
|
| BLAKE2b-256 |
3729eb431d3de8c193c10df4820f4f3f23f80ae26d7407451bba82df0d86b473
|
Provenance
The following attestation bundles were made for proxio-0.0.4-py3-none-any.whl:
Publisher:
publish.yml on RogerBCode/proxio
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
proxio-0.0.4-py3-none-any.whl -
Subject digest:
f7610affc1edfc869d4627bc1dc1ca411bb3acb40b60e29bb60fc9164495d417 - Sigstore transparency entry: 1340473998
- Sigstore integration time:
-
Permalink:
RogerBCode/proxio@1627a7628ad19d3768d678dfae92153c54885aa0 -
Branch / Tag:
refs/tags/0.0.4 - Owner: https://github.com/RogerBCode
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@1627a7628ad19d3768d678dfae92153c54885aa0 -
Trigger Event:
release
-
Statement type: