NiceGUI Configuration And Deployment¶
Use this reference when a NiceGUI task concerns ui.run(...) settings, runtime URLs, native windows, environment variables, server hosting, executable packaging, or NiceGUI On Air. For startup ownership, app factories, ui.run_with(...), lifespan, reload, and workers, load FastAPI and Uvicorn startup.
The public surfaces below follow NiceGUI's current configuration and deployment documentation. Inspect the target project's pinned NiceGUI version before relying on a recently added option or native-mode behavior.
Configure The Owning Runtime¶
Choose the process owner before setting runtime options:
| Deployment shape | Owning surface | Where configuration belongs |
|---|---|---|
| NiceGUI is the application and starts its server | ui.run(...) |
NiceGUI arguments plus additional Uvicorn keyword arguments |
| A parent FastAPI app owns startup | ui.run_with(parent_app, ...) and the external ASGI server |
NiceGUI composition options in ui.run_with; socket, TLS, reload, and worker options in Uvicorn or the process manager |
| Desktop application | ui.run(native=True, ...) |
NiceGUI runtime options and app.native configuration |
| Packaged browser or desktop executable | ui.run(reload=False, ...) |
import-safe page registration, packaging flags, and multiprocessing setup |
Do not split ownership by calling ui.run() and a separate server launcher for the same app. The exact composition patterns and worker constraints are in FastAPI and Uvicorn startup.
Select ui.run Options Deliberately¶
ui.run(...) accepts several groups of settings:
| Concern | Representative options | Decision rule |
|---|---|---|
| route and metadata | root, title, viewport, favicon, language, dark, markdown |
Use a root callable or decorated pages; override metadata per page when it is route-specific. |
| network and launch | host, port, show, on_air |
Bind and expose only the interfaces required by the deployment; treat On Air as a separate remote-access choice. |
| client recovery | reconnect_timeout, message_history_length |
Tune together from observed disconnect duration and replay volume; replay is not durable job delivery. |
| binding work | binding_refresh_interval |
Reduce active links before lowering the interval; use None only when no polling-based links need updates. |
| static delivery | cache_control_directives, gzip_middleware_factory |
Preserve deliberate cache lifetimes and compression behavior; disabling gzip or changing immutable caching is an operational decision. |
| development | reload, uvicorn_reload_dirs, uvicorn_reload_includes, uvicorn_reload_excludes, uvicorn_logging_level |
Keep reload local to development and restart fully when changing options that the reloader process owns. |
| frontend runtime | tailwind, unocss, prod_js |
Verify class compatibility before switching CSS engines; use production Vue and Quasar assets in deployed apps. |
| API visibility | fastapi_docs, endpoint_documentation |
Expose only the OpenAPI surfaces the application intends to publish. |
| browser storage | storage_secret, session_middleware_kwargs |
A secret is required for ui.storage.user and ui.storage.browser; load it from a secret source and configure cookie policy for the deployment. |
| native window | native, window_size, fullscreen, frameless |
Use only for a desktop app with a supported browser engine. |
Additional keyword arguments are forwarded to uvicorn.run. Most ui.run option changes require stopping and fully restarting the process; do not assume development auto-reload applies them.
Read Runtime URLs After Binding¶
app.urls contains the URLs on which the running app is available. The server has not bound its sockets during app.on_startup, so the collection is not available there. Read it in a page function or subscribe to app.urls.on_change when another application component needs the final addresses.
from nicegui import app, ui
@ui.page('/')
def home() -> None:
for url in app.urls:
ui.link(url, target=url)
ui.run()
Do not derive a public URL solely from the listening host and port when a reverse proxy, container port mapping, or tunnel owns the external address.
Configure Environment-Controlled Facilities¶
NiceGUI recognizes these framework environment variables:
| Variable | Default | Effect |
|---|---|---|
MATPLOTLIB |
enabled | Set to false to skip the potentially costly Matplotlib import; ui.pyplot and ui.line_plot then remain unavailable. |
NICEGUI_STORAGE_PATH |
.nicegui in the working directory |
Changes the local storage-file directory. |
NICEGUI_REDIS_URL |
no Redis backend | Selects Redis for shared persistent storage. |
NICEGUI_REDIS_KEY_PREFIX |
nicegui: |
Namespaces NiceGUI keys in Redis. |
MARKDOWN_CONTENT_CACHE_SIZE |
1000 |
Bounds cached Markdown snippets. |
RST_CONTENT_CACHE_SIZE |
1000 |
Bounds cached reStructuredText snippets. |
Treat these as process-start configuration. For application-owned host, port, credentials, feature flags, and service settings, use one validated settings model rather than scattering direct environment reads. When multiple processes or executables share local storage, do not let them independently rewrite the same files; give each instance a distinct NICEGUI_STORAGE_PATH or configure Redis where state must be shared.
Deploy A Browser-Hosted App¶
Run the production entry point under a service manager or container restart policy. NiceGUI's multi-architecture Docker image runs an application mounted at /app; its default internal port is 8080, so publish that port explicitly. The image supports non-root execution through PUID and PGID and passes process signals through to the app.
docker run --detach --restart always \
--publish 80:8080 \
--env PUID="$(id -u)" \
--env PGID="$(id -g)" \
--volume "$PWD:/app" \
zauberzeug/nicegui:latest
For HTTPS, either pass Uvicorn's ssl_certfile and ssl_keyfile options to ui.run(...) or terminate TLS at a reverse proxy such as NGINX or Traefik. A reverse-proxy deployment must preserve NiceGUI's HTTP and Socket.IO traffic, forwarding scheme and host information, route prefixes, timeouts, and upload limits consistently. Verify the rendered page, static assets, websocket connection, reconnect behavior, and upload path through the public URL rather than only against the container port.
Use one worker by default. NiceGUI clients, element trees, tasks, and ordinary Python state are process-local; a multi-worker deployment needs compatible session affinity and externalized shared state. See FastAPI and Uvicorn startup before adding workers or combining them with reload.
Build A Native Desktop App¶
ui.run(native=True) launches a pywebview window. window_size, fullscreen, and frameless cover common presentation settings. Configure lower-level pywebview behavior before startup through:
app.native.window_argsforwebview.create_windowargumentsapp.native.start_argsforwebview.startargumentsapp.native.settingsfor pywebview settingsapp.native.main_windowfor asynchronous access to the running window
Values in window_args and start_args take precedence over overlapping ui.run arguments. The browser engine must support ES modules and import maps; use Chrome 89 or newer, a current WebKitGTK or Qt backend on Linux, and the EdgeChromium prerequisites used by pywebview on Windows. A local Windows favicon used as the native icon must be an .ico file.
Native mode chooses an available port automatically when port is omitted. Browser mode defaults to 8080; use native.find_open_port() explicitly when multiple browser-mode executable instances must coexist.
Native Events And Process Placement¶
Register sync or async handlers with app.native.on(...). Supported lifecycle and window events are shown, loaded, minimized, maximized, restored, resized, moved, closed, and drop. Resized and moved events expose dimensions or coordinates in event.args; drop events expose filesystem paths under event.args['files'].
The native UI runs in a separate process. Define app.native.window_args, start_args, settings, and event registrations outside the if __name__ == '__main__': guard so the child process sees them.
from nicegui import app, ui
app.native.window_args['resizable'] = False
app.native.on('drop', lambda event: print(event.args['files']))
if __name__ == '__main__':
ui.run(native=True, reload=False)
Native storage follows the same scopes as browser mode. Multiple executable instances started from one working directory can collide on the default .nicegui files; isolate NICEGUI_STORAGE_PATH per instance or use Redis for intentionally shared state.
Package An Executable¶
Both nicegui-pack/PyInstaller and Nuitka require an import-safe application:
- Disable auto-reload with
ui.run(reload=False, ...). - Supply a
rootpage callable toui.runor register at least one@ui.page. - Decide whether the executable opens a browser or uses
native=True. - Use an available port when simultaneous instances are valid.
- Exercise the built artifact on every target operating system; a successful build on the development host does not establish runtime compatibility.
With nicegui-pack, --onefile is convenient but starts more slowly because PyInstaller extracts it on each run. A directory build starts faster and can be archived for distribution. Use --windowed only with native=True; a browser-mode application without a console has no normal Ctrl-C exit surface.
Nuitka must include both NiceGUI modules and package data because NiceGUI uses lazy imports and ships frontend assets:
Add equivalent package and package-data flags for optional libraries that ship templates or frontend assets. Prefer --standalone when startup speed matters more than producing one file.
Multiprocessing In Packaged Native Apps¶
Packaged native apps must call multiprocessing.freeze_support() as the first statement inside the main guard to prevent recursive process creation. Keep native settings outside the guard so the spawned native process applies them.
from multiprocessing import freeze_support
from nicegui import app, ui
app.native.window_args['transparent'] = True
def root() -> None:
ui.label('Packaged app')
if __name__ == '__main__':
freeze_support()
ui.run(root, native=True, reload=False)
Use On Air Only For Deliberate Remote Access¶
ui.run(on_air=True) creates a temporary public URL, currently valid for one hour. A private device token can select a stable organization/device URL. Treat that token as a secret, and do not log or commit it.
NiceGUI On Air is a tech preview, not a substitute for selecting an authentication, authorization, availability, and data-governance model. Before exposing an application, review what data and actions become reachable, add application authentication where needed, and verify the service's current operational and privacy terms. Use ordinary hosted deployment when the application requires controlled networking, durable availability, or organization-owned TLS and access policy.
Deployment Verification¶
Validate the built deployment through its real entry point and public boundary:
- process starts with reload disabled and shuts down cleanly under the service manager or container runtime
- health route, root page, static assets, Socket.IO connection, and reconnect flow work through the proxy or published port
app.urlsis consumed only after server binding and is not mistaken for canonical proxy configuration- storage survives and isolates users, tabs, workers, and executable instances as designed
- TLS, forwarded headers, cookie flags, upload limits, cache policy, and logs match the public deployment
- a native build opens, handles window events, closes cleanly, and can run alongside another instance when supported
- packaged artifacts include NiceGUI and optional-library data files and are tested on each target platform
- normal background tasks cancel on shutdown, while only explicitly bounded finalization work uses
@background_tasks.await_on_shutdown; see interaction mechanics