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:
version = await api.get_api_version("pve1")
vms = await api.get_vms("pve1")
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.
Metadata
Release files for arcane-mage 2.1.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 | |
|---|---|---|---|
| arcane_mage-2.1.0.tar.gz | 482.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| arcane_mage-2.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 600.4 kB
Release files / arcane_mage-2.1.0.tar.gz
| Download URL | arcane_mage-2.1.0.tar.gz |
|---|---|
| Size | 482.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5ea0b3c994505ec2d84b8149900fd1a0f24a7af45446ddcc5248b1da9e44768c
|
|
BLAKE2b-256 checksum How to use checksums |
e8c15c32ce761eaff537b876ea557fa7bf4ee0276dc900de399f3df005e1da3a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","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-2.1.0-py3-none-any.whl
| Download URL | arcane_mage-2.1.0-py3-none-any.whl |
|---|---|
| Size | 118.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4a61a8c7cd352f9f652f68c96144ecb4fb3315adeccd25fc5c5dd041e13c8988
|
|
BLAKE2b-256 checksum How to use checksums |
17ba314123d28a2686fc5524ec42c3e22bc55e5641dfb56a83d4bbf776ea4fb4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","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}
|