OPNsense API Python Wrapper Generator
Auto-generate Python client libraries for the OPNsense API by parsing controller source code from specific OPNsense versions.
Overview
This tool downloads OPNsense source code from GitHub, parses PHP controller files to extract API endpoint definitions, and generates a type-hinted Python client library that mirrors the OPNsense API structure.
Features
- Version-agnostic API: Auto-detects OPNsense version, no version-specific imports needed
- Auto-generation: Automatically generates Python client on first use if spec exists
- Full type hints: Generated code uses Python 3.12+ type annotations with Pydantic models
- OpenAPI-based: Generates OpenAPI 3.0 specs from OPNsense PHP source code
- IDE support: Complete autocomplete and type checking in modern IDEs
- Async support: Built-in async/await support for all endpoints
- Battle-tested: Uses openapi-python-client for reliable code generation
Installation
# Clone the repository
git clone <repo-url>
cd opn-sense
# Install with uv
just install
# Or manually
uv pip install -e ".[dev]"
Quick Start
Complete Setup (Easiest)
The fastest way to get started is using the setup command, which does everything in one step:
# Complete setup for OPNsense 25.7.6: download, generate spec, build client
uv run opnsense-openapi setup 25.7.6
This command:
- Downloads OPNsense source code
- Generates OpenAPI specification
- Builds Python client
Use the API Client
import os
from opnsense_openapi import OPNsenseClient
# Initialize client with auto-detection
client = OPNsenseClient(
base_url=os.getenv("OPNSENSE_URL"),
api_key=os.getenv("OPNSENSE_API_KEY"),
api_secret=os.getenv("OPNSENSE_API_SECRET"),
verify_ssl=False,
auto_detect_version=True, # Automatically detect OPNsense version
)
# Access the API - automatically generates client if needed
# If the OpenAPI spec exists but the Python client hasn't been generated yet,
# it will be automatically generated on first access (takes ~2 minutes)
api = client.api
# Call any API function - no version-specific imports needed!
info = api.core.firmware_info()
aliases = api.firewall.alias_search_item()
print(f"OPNsense version: {info.product_version}")
print(f"Aliases: {aliases.rows if aliases else []}")
Note: The first time you access client.api, if the OpenAPI spec exists for your version, the Python client will be automatically generated. This takes about 2 minutes. Subsequent uses are instant.
If you don't have the OpenAPI spec yet (because you skipped the setup command), you'll get a helpful error message with the exact commands to run:
opnsense-openapi setup <version>
# or step-by-step:
opnsense-openapi download <version>
opnsense-openapi generate <version>
See Generated Client Usage for complete documentation.
Accessing OPNsense Through an SSH Tunnel
When the OPNsense instance is only reachable through a bastion host, use an SSH SOCKS proxy or a local port-forward.
Option A — SOCKS proxy (ssh -D): remote DNS, best when the OPNsense
hostname only resolves inside the remote network:
# In a separate terminal, open the SOCKS proxy:
ssh -D 1080 -N user@bastion
# Install SOCKS support first:
# pip install "opnsense-openapi[socks]"
from opnsense_openapi import OPNsenseClient
client = OPNsenseClient(
base_url="https://opnsense.internal",
api_key="your-key",
api_secret="your-secret",
proxy="socks5h://127.0.0.1:1080", # 'socks5h' resolves DNS through the tunnel
verify_ssl=False,
)
Option B — local port-forward (ssh -L): no proxy needed, point
base_url directly at the forwarded port:
# Forward local port 8443 to opnsense:443 through the bastion:
ssh -L 8443:opnsense.internal:443 -N user@bastion
from opnsense_openapi import OPNsenseClient
client = OPNsenseClient(
base_url="https://localhost:8443",
api_key="your-key",
api_secret="your-secret",
verify_ssl=False,
)
CLI Commands
Complete Setup (Recommended)
opnsense-openapi setup [VERSION] [OPTIONS]
Options:
-o, --output PATH Output directory for generated client
-c, --cache PATH Cache directory for source files (default: tmp/opnsense_source)
--force Re-download source even when cached
--meta TEXT Meta type: none, poetry, setup, pdm, uv (default: setup)
--overwrite Overwrite existing client directory
One command to do it all! This convenience command runs all three steps:
- Downloads OPNsense source code
- Generates OpenAPI specification
- Builds Python client
Use this when setting up a new OPNsense version for the first time.
Example:
opnsense-openapi setup 25.7.6
Download Controller Sources
opnsense-openapi download [VERSION] [OPTIONS]
Options:
-d, --dest PATH Override the cache directory (default: tmp/opnsense_source)
--force / --no-force Re-download files even if cached
The command clones https://github.com/opnsense/core at the requested tag, caches
it locally, and extracts the controller files that downstream parsing and code
generation steps consume.
Generate OpenAPI Spec
opnsense-openapi generate [VERSION] [OPTIONS]
Options:
-o, --output PATH Output directory for OpenAPI spec (default: specs/)
-c, --cache PATH Cache directory for source files (default: tmp/opnsense_source)
--force Re-download source even when cached
Generates an OpenAPI 3.0 specification from OPNsense controller source code. The spec is saved to the specs directory and can be used for client generation or documentation.
Build Python Client (Optional)
opnsense-openapi build-client [OPTIONS]
Options:
-v, --version TEXT OPNsense version (e.g., '25.7.6'). Auto-detects if not specified.
-o, --output PATH Output directory for generated client
--meta TEXT Meta type: none, poetry, setup, pdm, uv (default: setup)
--overwrite Overwrite existing client directory
--no-auto-detect Disable auto-detection (requires --version)
Note: This command is optional because the Python client is automatically generated when you first access client.api if the OpenAPI spec exists. Only use this command if you want to:
- Pre-generate the client before first use
- Customize the generation options (meta type, output path)
- Regenerate/overwrite an existing client
Serve Documentation
opnsense-openapi serve-docs [OPTIONS]
Options:
-v, --version TEXT OPNsense version (e.g., '25.7.6'). Auto-detects if not specified.
-p, --port INTEGER Port to run server on (default: 8080)
-h, --host TEXT Host to bind to (default: 127.0.0.1)
-l, --list List available spec versions and exit
--no-auto-detect Disable auto-detection (requires --version)
Launch a local Swagger UI server to browse the generated OpenAPI documentation.
If credentials are provided via environment variables (OPNSENSE_URL, OPNSENSE_API_KEY, OPNSENSE_API_SECRET), it acts as a proxy to the OPNsense instance, allowing you to test API calls directly from the browser.
Display Tool Version
opnsense-openapi --version
Development
Running Tests
# Run all tests
just test
# Run with coverage
just coverage
Code Quality
# Format code
just format
# Lint code
just lint
Architecture
Components
-
Downloader (
src/opnsense_openapi/downloader/)- Clones OPNsense core repository from GitHub
- Manages version-specific source code cache
- Supports tag-based version selection
-
Parser (
src/opnsense_openapi/parser/)- Parses PHP controller files using regex
- Extracts namespace, class, and method information
- Determines HTTP methods and parameters
-
Generator (
src/opnsense_openapi/generator/)- Generates OpenAPI 3.0 specifications from PHP source
- Infers response schemas from controller patterns
- Creates reusable spec files for each version
-
Client (
src/opnsense_openapi/client/)- Base HTTP client with OPNsense authentication
- Handles API key/secret via Basic Auth
- Auto-generates Python client on first use
- Provides version-agnostic API access
How It Works
Quick Setup (Recommended):
opnsense-openapi setup 25.7.6
Or step-by-step:
- Download: Clone OPNsense core repository for specified version
- Parse: Scan
src/opnsense/mvc/app/controllers/OPNsense/*/Api/for controllers - Extract: Parse controller classes to find public
*Action()methods - Generate Spec: Create OpenAPI 3.0 specification from parsed controllers
- Auto-Generate Client: When accessing
client.api, automatically generate Python client if spec exists - Use: Call API methods with full type hints and IDE autocomplete
The auto-generation step (5) happens seamlessly on first use. If the OpenAPI spec exists for your version, the Python client is generated automatically (takes ~2 minutes). Subsequent uses are instant.
URL Mapping
OPNsense API URLs follow the pattern:
/api/{module}/{controller}/{command}/[params]
For example:
- PHP:
OPNsense\Firewall\Api\AliasController::searchItemAction() - URL:
/api/firewall/alias/searchItem - Python:
api.firewall.alias_search_item()
The version-agnostic wrapper automatically maps Python function names to API endpoints.
Example: Generated Code Structure
src/opnsense_openapi/
├── generated/
│ └── v25_7_6/ # Version-specific generated client
│ └── opnsense_openapi_client/
│ ├── __init__.py
│ ├── client.py # HTTP client
│ ├── models/ # Response models
│ └── api/ # API endpoints
│ ├── core/ # Core module
│ │ ├── core_firmware_info.py
│ │ └── core_firmware_status.py
│ └── firewall/ # Firewall module
│ ├── firewall_alias_search_item.py
│ └── firewall_alias_get_item.py
└── client/
├── base.py # OPNsenseClient with auto-detection
└── generated_api.py # Version-agnostic wrapper
# Users access via version-agnostic API:
# api.core.firmware_info()
# api.firewall.alias_search_item()
Limitations
- Requires git to be installed for downloading OPNsense source
- Requires
openapi-python-clientfor auto-generating Python clients - First-time client generation takes ~2 minutes (subsequent uses are instant)
- Some complex XML model definitions may not parse perfectly
- Requires access to OPNsense instance for version auto-detection
Contributing
See CLAUDE.md for development guidelines and coding standards.
License
MIT License. See LICENSE.
Metadata
Release files for opnsense-openapi 0.5.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 | |
|---|---|---|---|
| opnsense_openapi-0.5.0.tar.gz | 2.7 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| opnsense_openapi-0.5.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 5.0 MB
Release files / opnsense_openapi-0.5.0.tar.gz
| Download URL | opnsense_openapi-0.5.0.tar.gz |
|---|---|
| Size | 2.7 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
aef96d96d88e9ec71165c8cf662cc297947e5c458c4ad3c27bd7ab3851e7680a
|
|
BLAKE2b-256 checksum How to use checksums |
cdcaa9fd7329ded21cdc8e726e97ad22b93df899b50da804c05606be489543c5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 4, 2026.
Transparency logRelease files / opnsense_openapi-0.5.0-py3-none-any.whl
| Download URL | opnsense_openapi-0.5.0-py3-none-any.whl |
|---|---|
| Size | 2.2 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
fb300b81874b17785672339e3d2910b5f4f200e141970420a1b2c962e76dc929
|
|
BLAKE2b-256 checksum How to use checksums |
2931be405c9f9a6489a66d6d46460427f243a558ec26f595f56921f2767041df
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 4, 2026.
Transparency log