Arcane Mage - Fluxnode Provisioning Library and Tools
Introduction
This is experimental software. There may be rough edges. If you spot something that is not quite right - please open an issue.
Arcane Mage is a Python library and suite of tools for automating Fluxnode installation and configuration. It can be used as a standalone CLI/TUI application or imported as a library for custom automation workflows.
Features:
- Fully automated A to Z Proxmox installs, including Secure Boot key enrollment
- Async Proxmox VE API client with token and password authentication
- Pydantic-validated configuration models loadable from YAML
- Custom async FAT12 writer for config disk image creation
- Yescrypt password hashing for Linux shadow-compatible hashes
- TUI (Textual) and CLI (Typer) interfaces with rich-formatted output
- TPM 2.0 keyring backend for headless Linux credential storage
Installation
Install uv - https://docs.astral.sh/uv/getting-started/installation/
# Library only (for use as a dependency)
uv add arcane-mage
# With CLI support
uv add "arcane-mage[cli]"
# With TUI support (includes CLI)
uv add "arcane-mage[tui]"
# Install as a standalone tool
uv tool install "arcane-mage[tui]"
# Run once without installing
uvx --with "arcane-mage[tui]" arcane-mage
Library Usage
arcane-mage exposes a public API for programmatic Fluxnode provisioning:
from arcane_mage import (
ArcaneOsConfigGroup,
Provisioner,
ProxmoxApi,
TIER_CONFIG,
get_latest_iso_version,
)
Loading Configuration
Node configurations are defined in YAML and loaded into Pydantic-validated models:
from arcane_mage import ArcaneOsConfigGroup
# Load from the default fluxnodes.yaml
group = ArcaneOsConfigGroup.from_fs()
# Load from a specific file
group = ArcaneOsConfigGroup.from_fs(Path("my_nodes.yaml"))
for node in group:
print(node.fluxnode.identity.flux_id)
See the examples directory for sample YAML configurations.
Connecting to Proxmox
from arcane_mage import ProxmoxApi
# Parse and connect with a token string
token = ProxmoxApi.parse_token("automation@pam!arcane=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")
if token:
api = ProxmoxApi.from_token("https://pve.local:8006", token)
print(token.user) # "automation@pam"
print(token.username) # "automation"
# Password authentication
creds = ProxmoxApi.parse_user_pass("automation:secret")
if creds:
api = await ProxmoxApi.from_user_pass("https://pve.local:8006", creds)
# Use as an async context manager
async with api:
res = await api.get_vms("pve1")
# A failed call is an ApiFailure (status, error, timed_out); past this check
# it is an ApiSuccess whose payload has the endpoint's type, here list[VmSummary].
if not res:
print(f"Unable to list VMs: {res.error}")
else:
for vm in res.payload:
print(vm["vmid"], vm.get("name"), vm["status"])
Every call validates Proxmox's answer against the endpoint's shape. An answer missing a field arcane-mage relies on comes back as an ApiFailure saying which field; fields arcane-mage does not name are kept as Proxmox sent them.
Provisioning Nodes
from arcane_mage import ArcaneOsConfigGroup, Provisioner, ProxmoxApi
token = ProxmoxApi.parse_token("automation@pam!arcane=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")
api = ProxmoxApi.from_token(url, token)
async with api:
provisioner = Provisioner(api)
group = ArcaneOsConfigGroup.from_fs()
for node in group:
success = await provisioner.provision_node(
node,
callback=lambda ok, msg: print(f"{'OK' if ok else 'FAIL'}: {msg}"),
)
The provisioner handles the full workflow: API validation, storage checks, VM config generation, FAT12 config disk creation, EFI upload, VM creation, and cleanup.
Discovery
Match existing VMs on a hypervisor against your configuration:
discovery = await provisioner.discover_nodes(group)
if discovery:
for node in discovery.nodes:
print(node.fluxnode.identity.flux_id)
Other Utilities
from arcane_mage import HashedPassword, TIER_CONFIG, get_latest_iso_version
# Yescrypt password hashing (Linux shadow-compatible)
hashed = HashedPassword("my_password").hash()
# Hardware tier specs (cumulus, nimbus, stratus)
print(TIER_CONFIG["cumulus"]) # {'memory_mb': 8192, 'scsi_gb': 220, 'cpu_cores': 4}
# Fetch latest FluxOS ISO version
version = await get_latest_iso_version()
CLI Usage
Launch the interactive TUI:
arcane-mage tui
arcane-mage tui -c my_nodes.yaml
Stored Hypervisors
Hypervisors added via the TUI are stored in ~/.fluxnode_creator.yaml with credentials in your system keyring. Use --hypervisor / -H to reference them by name instead of passing --url and --token:
arcane-mage ping -H pve1
arcane-mage validate -H pve1 -c my_nodes.yaml
arcane-mage provision -H pve1 -c my_nodes.yaml --start
Commands
Test connectivity and authentication:
arcane-mage ping -H pve1
Provision nodes:
arcane-mage provision -H pve1 -c my_nodes.yaml --start
Pre-flight validation (checks API, storage, ISO, network without provisioning):
arcane-mage validate -H pve1 -c my_nodes.yaml
Check which configured nodes are already provisioned:
arcane-mage status -H pve1 -c my_nodes.yaml
Deprovision (stop and delete) VMs:
# From config file
arcane-mage deprovision -H pve1 -c my_nodes.yaml
# Target a specific VM by name or ID
arcane-mage deprovision -H pve1 --vm-name mynode
arcane-mage deprovision -H pve1 --vm-id 105
# Skip confirmation
arcane-mage deprovision -H pve1 --vm-name mynode --force
Authentication
All commands that connect to Proxmox also accept explicit credentials:
arcane-mage ping \
--url https://pve.local:8006 \
--token 'automation@pam!arcane=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
Or via environment variables:
export ARCANE_MAGE_URL=https://pve.local:8006
export ARCANE_MAGE_TOKEN='automation@pam!arcane=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
arcane-mage validate -c my_nodes.yaml
Or pipe the token via stdin:
cat /path/to/token | arcane-mage provision -c my_nodes.yaml
Credential resolution order: --token > stdin > ARCANE_MAGE_TOKEN env var > --hypervisor stored credential.
JSON Output
All Proxmox commands support --json for machine-readable output (useful for Ansible):
arcane-mage validate -H pve1 -c my_nodes.yaml --json
arcane-mage status -H pve1 -c my_nodes.yaml --json
Run the following for help:
arcane-mage --help
arcane-mage provision --help
Configuration
Node configurations are defined in YAML. See docs/configuration.md for the full schema reference and examples/ for ready-to-use templates.
Proxmox Setup
See docs/proxmox-setup.md for hypervisor setup instructions (user, API token, storage, permissions).
Credential Storage
Arcane Mage uses your system's secure keyring to store API credentials, with a built-in TPM 2.0 backend for headless Linux servers. See docs/keyring.md for details and troubleshooting.
Ansible
The runonflux.arcane_mage collection wraps validation, provisioning, status, deprovisioning and ISO lookup as Ansible modules. See ansible_collection/runonflux/arcane_mage/README.md.
Contributing
See CONTRIBUTING.md for setup, the checks a pull request must pass, and how we write comments and commit messages.
Metadata
Release files for arcane-mage 3.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| arcane_mage-3.0.0.tar.gz | 99.6 kB | Without provenance | Details for arcane_mage-3.0.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| arcane_mage-3.0.0-py3-none-any.whl | Python 3 | none | any | Details for arcane_mage-3.0.0-py3-none-any.whl |
Total release size: 208.6 kB
Release files / arcane_mage-3.0.0.tar.gz
| Download URL | arcane_mage-3.0.0.tar.gz |
|---|---|
| Size | 99.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4198c3503a761bf7484a8becc22c04bb85fb156c1130e7b063916633beb7243f
|
|
BLAKE2b-256 checksum How to use checksums |
cac0e228684959ee0322ffca4fdb6ca27a70d86d7c61fef9d15d65a79fbde902
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.3 {"installer":{"name":"uv","version":"0.13.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / arcane_mage-3.0.0-py3-none-any.whl
| Download URL | arcane_mage-3.0.0-py3-none-any.whl |
|---|---|
| Size | 109.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
777ed843a5068c1ab406cbdae8cf949752da3c2ab38263885ee59c71ee6b8dc7
|
|
BLAKE2b-256 checksum How to use checksums |
b94194e96d61a762d7466a63fcdc882164b7e0671ffe55783a3cd760d7bf610e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.3 {"installer":{"name":"uv","version":"0.13.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for arcane-mage 3.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.