Installation¶
System Requirements¶
- Python >= 3.10
- pip (bundled with Python)
- git (required for development install and setuptools-scm versioning)
Production Install¶
Install from PyPI:
Install with extras for additional backends and integrations:
pip install underwrite[serve] # HTTP daemon (uvicorn + FastAPI)
pip install underwrite[risk] # ML risk scoring (numpy, scikit-learn)
pip install underwrite[otlp] # OpenTelemetry tracing
pip install underwrite[vault] # HashiCorp Vault secrets backend
pip install underwrite[aws] # AWS S3 export (boto3)
pip install underwrite[gcs] # GCS export (google-cloud-storage)
pip install underwrite[security] # Security audit tooling (bandit, pip-audit)
pip install underwrite[all] # All extras except [dev] and [security]
Development Install¶
Quick Start (recommended)¶
This idempotent script:
- Checks prerequisites (Python >= 3.10, pip, git)
- Creates a
.venvvirtual environment - Upgrades pip, setuptools, and wheel
- Installs the package in editable mode with
[dev]extras - Installs pre-commit hooks (ruff lint + format, mypy)
- Copies
.env.exampleto.envif not present - Validates the environment (import check, version, tool availability)
Manual Setup¶
Extras Reference¶
| Extra | Packages | Purpose |
|---|---|---|
[dev] |
pytest, pytest-cov, hypothesis, ruff, mypy, bandit, pip-audit, httpx | |
[risk] |
numpy, scikit-learn | ML-based default probability scoring |
[serve] |
uvicorn, fastapi | HTTP daemon for REST API |
[otlp] |
opentelemetry-api, opentelemetry-sdk, opentelemetry-exporter-otlp-proto-grpc, opentelemetry-instrumentation-fastapi | Distributed tracing via OTLP |
[vault] |
hvac | HashiCorp Vault secrets backend |
[aws] |
boto3 | AWS S3 export (audit, reporting) |
[gcs] |
google-cloud-storage | GCS export (audit, reporting) |
[security] |
bandit, pip-audit | Static analysis and dependency auditing |
[all] |
otlp + serve + vault + aws + gcs | Everything except dev and security |
Note:
[mutation]extra providesmutmutfor mutation testing but is not included in[all].
Docker¶
Build the image:
Run the HTTP daemon:
The Docker image uses a multi-stage build (Python 3.12-slim):
- Builder stage: builds the wheel and installs the package with
[serve,otlp,vault]extras - Runtime stage: copies only the installed site-packages, runs as non-root
underwriteuser, exposes port 8080, includes a health check on/healthz
Docker Compose¶
This starts a single underwrite container with:
- Port mapping:
8000:8080 - Sqlite store backed by a named volume mounted at
/data - Services:
mechanism,audit,risk,fraud - Rate limit of 100 req/s
- Environment variables read from your
.envfile
Verify Installation¶
Expected output resembles 0.1.dev65+gad81577c8.d20260608 (version is driven by git tags via setuptools-scm).
Configuration¶
Copy the environment template and adjust for your local setup:
All settings are documented with inline comments in .env.example. The runtime reads environment variables prefixed with UNDERWRITE_ (e.g. UNDERWRITE_STORE_BACKEND, UNDERWRITE_LOG_LEVEL). Alternatively, a underwrite.json configuration file can be created via underwrite init.