This repo uses uv to install Python and dependencies, Ruff for linting and formatting, and ty for type checking.
# Runtime only
uv sync
# Tests + Ruff (matches CI)
uv sync --extra test --group dev
# Documentation (MkDocs)
uv sync --extra docs --group devuv run ruff check .
uv run ruff format .
uv run ty check proxbox_api/types proxbox_api/utils/retry.py
uv run pytest tests
uv run mkdocs serve # after syncing with --extra docsProject documentation is available under docs/ and built with MkDocs Material.
uv sync --extra docs --group dev
uv run mkdocs serve- English (default)
- Brazilian Portuguese (
pt-BR) as optional translation
All images are Alpine-based (smaller footprint), built from this repository with uv and uv.lock in a multi-stage Dockerfile. Three variants are published to Docker Hub:
| Variant | Tags | Description |
|---|---|---|
| Raw (default) | latest, <version> |
Pure uvicorn, HTTP only. Smallest image. |
| Nginx | latest-nginx, <version>-nginx |
nginx terminates HTTPS via mkcert; proxies to uvicorn. |
| Granian | latest-granian, <version>-granian |
Granian (Rust ASGI server) with native TLS via mkcert. No nginx. |
Upgrade note: before v0.0.7,
latestwas the nginx+HTTP image. It is now the raw uvicorn image. Pulllatest-nginxfor the previous behavior.
Plain uvicorn on HTTP — the simplest option for local dev or when you put your own proxy in front.
docker pull emersonfelipesp/proxbox-api:latest
docker run -d -p 8000:8000 --name proxbox-api emersonfelipesp/proxbox-api:latestBuild from source:
docker build -t proxbox-api:raw .
docker run -d -p 8000:8000 proxbox-api:rawnginx terminates HTTPS on PORT (default 8000) using certificates from mkcert and proxies to uvicorn on 127.0.0.1:8001. supervisord manages both processes. The nginx config disables proxy buffering so chunked / SSE responses flow through unmodified.
docker pull emersonfelipesp/proxbox-api:latest-nginx
docker run -d -p 8443:8000 --name proxbox-api-nginx \
emersonfelipesp/proxbox-api:latest-nginxBuild from source:
docker build --target nginx -t proxbox-api:nginx .
docker run -d -p 8443:8000 proxbox-api:nginxGranian is a Rust-based ASGI server with native HTTP/2, WebSocket, and TLS support. This variant eliminates nginx and supervisord — a single granian process handles everything.
docker pull emersonfelipesp/proxbox-api:latest-granian
docker run -d -p 8443:8000 --name proxbox-api-granian \
emersonfelipesp/proxbox-api:latest-granianBuild from source:
docker build --target granian -t proxbox-api:granian .
docker run -d -p 8443:8000 proxbox-api:granian| Variable | Default | Description |
|---|---|---|
PORT |
8000 |
Port the server listens on |
MKCERT_CERT_DIR |
/certs |
Directory where certs are stored |
MKCERT_EXTRA_NAMES |
— | Extra SANs (commas or spaces), e.g. proxbox.lan,10.0.0.5 |
CAROOT |
— | Mount a volume here to persist the local CA across container restarts |
docker run -d -p 8443:8000 --name proxbox-api-tls \
-e MKCERT_EXTRA_NAMES='myhost.local,192.168.1.10' \
emersonfelipesp/proxbox-api:latest-nginxTo run a shell instead of starting the server, pass a command (the entrypoint delegates to it):
docker run --rm emersonfelipesp/proxbox-api:latest-nginx shgit clone https://github.com/netdevopsbr/netbox-proxbox.git
cd proxbox_api
From the repository root (where pyproject.toml lives):
uv sync
From the repository root:
uv run fastapi run proxbox_api.main:app --host 0.0.0.0 --port 8000
-
--host 0.0.0.0will make the app available on all host network interfaces, which my not be recommended. Just pass your desired IP like--host <YOUR-IP>and it will also work. -
--port 8000is the default port, but you can change it if needed. Just to remember to update it on NetBox also, at FastAPI Endpoint model.
Control NetBox API request caching to optimize sync performance:
# 5-minute TTL (default is 60 seconds)
export PROXBOX_NETBOX_GET_CACHE_TTL=300
# Disable caching entirely
export PROXBOX_NETBOX_GET_CACHE_TTL=0
# Increase max entries (default 4096)
export PROXBOX_NETBOX_GET_CACHE_MAX_ENTRIES=8192
# Set max cache size in bytes (default 52428800 = 50MB)
export PROXBOX_NETBOX_GET_CACHE_MAX_BYTES=104857600 # 100MB
# Enable debug logging
export PROXBOX_DEBUG_CACHE=1
uv run fastapi run proxbox_api.main:app --host 0.0.0.0 --port 8000Cache metrics are available at GET /cache and GET /cache/metrics/prometheus.
Control backup synchronization batch size and delay to prevent overwhelming NetBox's PostgreSQL connection pool:
# Batch size for backup sync (default 5, was 10 before fix)
export PROXBOX_BACKUP_BATCH_SIZE=5
# Delay between batches in milliseconds (default 200ms)
export PROXBOX_BACKUP_BATCH_DELAY_MS=200
uv run fastapi run proxbox_api.main:app --host 0.0.0.0 --port 8000Why adjust these?
- Smaller batch size (3-5): Use when NetBox has limited PostgreSQL connections or many concurrent users
- Larger batch size (10-20): Safe if NetBox has a large PostgreSQL pool (50+ connections) and dedicated hardware
- Longer delay (500-1000ms): Helps when "database unavailable" errors appear during full sync
- Shorter delay (0-100ms): Faster sync when NetBox is lightly loaded
Symptoms of incorrect tuning:
- HTTP 500 "database unavailable" during backup/VM sync → decrease batch size, increase delay
- HTTP 502 "Response ended prematurely" → decrease batch size, increase delay
- Slow sync performance on powerful hardware → increase batch size, decrease delay
pip install -e .
fastapi run proxbox_api.main:app --host 0.0.0.0 --port 8000
Or with uvicorn:
uvicorn proxbox_api.main:app --host 0.0.0.0 --port 8000
Install the local CA in your system trust store, generate a cert, then point uvicorn at the PEM files:
mkcert -install
mkcert proxbox.backend.local localhost 127.0.0.1 ::1
From the repository root (adjust paths to the files mkcert printed):
uv run uvicorn proxbox_api.main:app --host 127.0.0.1 --port 8000 --reload \
--ssl-keyfile=./proxbox.backend.local+3-key.pem \
--ssl-certfile=./proxbox.backend.local+3.pem
NetBox plugin layout (paths differ): example with --app-dir and module path as in your install:
/opt/netbox/venv/bin/uvicorn netbox-proxbox.proxbox_api.proxbox_api.main:app \
--host 127.0.0.1 --port 8000 --app-dir /opt/netbox/netbox \
--ssl-keyfile=/path/to/localhost+2-key.pem \
--ssl-certfile=/path/to/localhost+2.pem
Optional nginx in front of that uvicorn: copy or adapt a site config that proxy_passes to http://127.0.0.1:8000 and terminates TLS on 443 (same idea as TLS with a real certificate below).
Use Let’s Encrypt, a corporate CA, or any PEM full chain + private key. Prefer terminating TLS in nginx or Caddy and keeping the app on plain HTTP on localhost; uvicorn TLS is fine for small setups if you accept Python as the TLS endpoint.
1. Certificate files
- Let’s Encrypt (Certbot): typically
/etc/letsencrypt/live/<your-domain>/fullchain.pemandprivkey.pem. Renew withcertbot renew; reload nginx (or your proxy) after renewal. - Corporate / manual: use the PEM the CA gave you: certificate file must include the full chain (leaf + intermediates) in one file, plus the unencrypted private key (or use
--ssl-keyfile-passwordwith uvicorn if the key is encrypted).
2. Recommended: reverse proxy on the same host
Run the API on HTTP bound to loopback only, proxy from 443:
uv run uvicorn proxbox_api.main:app --host 127.0.0.1 --port 8000
Example nginx server block (replace domain and paths):
server {
listen 443 ssl http2;
server_name api.example.com;
ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 86400;
proxy_send_timeout 86400;
proxy_buffering off;
}
}For Connection $connection_upgrade, add at http level:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}Reload nginx after editing. Point NetBox’s FastAPI endpoint at https://api.example.com (and port 443 or your chosen HTTPS port).
3. Alternative: uvicorn serves TLS directly
uv run uvicorn proxbox_api.main:app --host 0.0.0.0 --port 8443 \
--ssl-certfile=/etc/letsencrypt/live/api.example.com/fullchain.pem \
--ssl-keyfile=/etc/letsencrypt/live/api.example.com/privkey.pem
Ensure the user running uvicorn can read the key (often root owns /etc/letsencrypt; use group ACLs, a deploy user + copied certs, or hitch/proxy instead). Use fullchain.pem for --ssl-certfile so clients receive the full chain.