remote-local
Expose your local FastAPI, NiceGUI, or development servers remotely — easily, reliably, and for free.
remote-local is a simple and robust middleware that automatically creates a public tunnel for your local server using ngrok (and more in the future).
It handles session cleanup, hot reloads, and retries automatically — no manual setup required.
Features
- 🌍 Expose your local server remotely with one line of code.
- ⚡ Fully compatible with FastAPI, NiceGUI, or any ASGI app.
- 🔄 Handles hot reloads and session recovery automatically.
- 🔒 No external configuration required — works with free ngrok accounts.
- 🛠️ Designed for development, testing, and remote integrations.
Installation
pip install remote-local
Quick Usage
from nicegui import app, ui
from remote_local import NgrokMiddleware
NgrokMiddleware(app, port=8080)
@ui.page('/')
async def main_page():
ui.label('Hello World')
ui.run(port=8080, reload=True)
✅ That's it! Your local server is now publicly accessible through a secure URL.
By default, a /server-info endpoint is also created, showing the current public URL and server status.
Environment Variable: PUBLIC_URL
If your server is already running with a public URL (for example, in a production deployment), you can set the PUBLIC_URL environment variable. When PUBLIC_URL is set, the middleware will skip starting ngrok and use the provided URL as the public-facing address for your app.
- If
PUBLIC_URLis set, ngrok will not be started and the middleware will simply use this value. - If
PUBLIC_URLis not set, the middleware will start ngrok and set the public URL automatically.
Example:
export PUBLIC_URL=https://your-production-url.example.com
Configuration Options
You can customize the middleware:
NgrokMiddleware(
app,
port=8080,
max_wait_seconds=60, # how long to retry if ngrok fails initially
fallback_to_localhost=False, # fallback to localhost if ngrok fails
expose_server_info=True, # create a /server-info endpoint
)
Temporary Usage: temporal_url
If you need a temporary public URL during the execution of a specific task (instead of during the whole app lifecycle), you can use temporal_url as a simple context manager.
It will automatically reuse the same public URL if called multiple times in parallel, and will close the tunnel once all usages are finished.
Example:
from remote_local import temporal_url
@router.post("/external-access")
async def external_access():
with temporal_url(port=8080) as public_url:
print(f"My API is now accessible at {public_url}")
# Perform actions that need external access
# Tunnel is closed automatically after the block
Notes:
temporal_urlrequires specifying theportexplicitly.- It automatically kills existing ngrok sessions if needed.
- It's safe to nest multiple
with temporal_url(...)usages — they will share the same tunnel.
License
This project is licensed under the MIT License.
Future Plans
- Support for other tunnels (Cloudflared, Localhost.run, etc.)
- More flexible server info APIs
- Auto-detection of multiple servers
Author
Made with ❤️ by Pablo Schaffner
Metadata
Release files for remote-local 0.0.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| remote_local-0.0.3.tar.gz | 5.5 kB | Without provenance | Details for remote_local-0.0.3.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| remote_local-0.0.3-py3-none-any.whl | Python 3 | none | any | Details for remote_local-0.0.3-py3-none-any.whl |
Total release size: 11.5 kB
Release files / remote_local-0.0.3.tar.gz
| Download URL | remote_local-0.0.3.tar.gz |
|---|---|
| Size | 5.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5453508daa142aed14c21783e75f218afa5299a189b116aeb0cbe80a719702c9
|
|
BLAKE2b-256 checksum How to use checksums |
3756e4159ae80b142797d2e053a9a67585e348a44fc8a1720ba03aecf4a928b3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.2
|
Release files / remote_local-0.0.3-py3-none-any.whl
| Download URL | remote_local-0.0.3-py3-none-any.whl |
|---|---|
| Size | 6.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4bc853d53487b7b8f836a89bbf0633c7a8209eef3d080015153bdb32e40b1263
|
|
BLAKE2b-256 checksum How to use checksums |
e43746dcb5f6869bc17a89e4ead09a7b56957cbca97a1cec9e4c2484d1e0df35
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.2
|
Security for remote-local 0.0.3
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.