Local reverse proxy for production-like .localhost domains
Project description
Portman
Portman is a lightweight local reverse proxy for production-like .localhost
domains. It lets multi-service development projects use stable names like
api.localhost, app.localhost, and admin.localhost instead of a pile of
remembered ports.
portman.yml
|
v
Browser -> api.localhost:8080 -> Portman -> localhost:8000
Browser -> app.localhost:8080 -> Portman -> localhost:3000
Browser -> admin.localhost:8080 -> Portman -> localhost:9000
Portman is aimed at small teams and solo developers who want cleaner local environments without running a full Nginx, Caddy, Traefik, or Docker routing setup for every project.
Quick Start
Install Portman:
pip install portman
Create portman.yml:
proxy_port: 8080
routes:
api.localhost: 8000
app.localhost: 3000
admin.localhost:
port: 9000
timeout: 60
Start your local services, then start Portman:
portman start --config portman.yml
Open:
http://api.localhost:8080
http://app.localhost:8080
http://admin.localhost:8080
List configured routes and health status:
portman list --config portman.yml
How It Works
Portman binds to 127.0.0.1 on proxy_port, reads the incoming Host header,
and looks up the matching domain in an in-memory route table. Requests are then
forwarded to the configured upstream service on localhost:<port>.
The route table is built from portman.yml at startup. A file watcher monitors
the config file's directory and reloads the table when the config file changes.
Valid reloads replace the route table atomically; invalid reloads are logged and
the previous working routes remain active.
HTTP and WebSocket traffic are both proxied. Portman rewrites upstream Host
headers to localhost:<port> and preserves useful forwarding headers such as
X-Forwarded-Host.
Hosts File Integration
Hosts file modification is not required for normal Portman usage. Prefer
.localhost domains, which are intended for loopback local development and do
not require editing /etc/hosts or the Windows hosts file on modern systems.
The portman hosts commands remain available as an experimental, optional
escape hatch for custom domains. They are not part of the core workflow.
Benchmarking
Portman includes a small stdlib-only benchmark helper:
python scripts/benchmark.py --host api.localhost --port 8080 --requests 1000 --concurrency 50
Run it while Portman and the target upstream service are already running. The script reports request throughput plus mean, median, p95, and p99 latency.
Limitations
- Portman is a local development proxy, not a production edge proxy.
- TLS termination is not implemented in v0.1.0.
.localhostdomains should be preferred; custom domains may require manual DNS or hosts file setup.- Upstream services must already be running on local TCP ports.
- Route matching is based on the request
Hostheader, not path prefixes.
Release Status
See docs/release-readiness.md for the current v0.1.0 readiness audit.
Project details
Release history Release notifications | RSS feed
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 portman_proxy-0.1.1.tar.gz.
File metadata
- Download URL: portman_proxy-0.1.1.tar.gz
- Upload date:
- Size: 12.0 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d65c61dadd13e83403b1ab54fd9aa4bd711fdc6460a45d4c84d4f0990d20c4ba
|
|
| MD5 |
712c9f7083465ed1f3718a1ca7dcd0dd
|
|
| BLAKE2b-256 |
8cf9cf76f0d440219fa68840dc7129c92b028c6a5171445d13433651cced3e4f
|
File details
Details for the file portman_proxy-0.1.1-py3-none-any.whl.
File metadata
- Download URL: portman_proxy-0.1.1-py3-none-any.whl
- Upload date:
- Size: 18.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4b79876943632b4be74d2ac6ebeb4faa1dc25e0208809083aa39852376799f4d
|
|
| MD5 |
1a6941e30e372772340d514996041fdb
|
|
| BLAKE2b-256 |
cc0a7e0a4d0e39971e803262a1964acc52d186f93388b4ba60c4589f46c0f856
|