Configuration, deployment and authentication

Streamlit · Expert · 15 min

Shipping an app to real users raises questions of configuration, hosting, auth and capacity that the dev server hides.

Configuration lives in .streamlit/config.toml (project) or ~/.streamlit/config.toml, and every option can also be a CLI flag or an environment variable: [server] port = 8080 equals --server.port 8080 and STREAMLIT_SERVER_PORT=8080. streamlit config show lists all options. Common ones: server.port, server.address, server.headless = true (no browser), server.maxUploadSize (MB), server.baseUrlPath behind a proxy, client.toolbarMode, and a [theme] section (primaryColor, base, fonts).

Hosting options:

  • Streamlit Community Cloud: connect a GitHub repo, set secrets in the UI.
  • Containers: a Docker image running streamlit run app.py --server.port=8501 --server.address=0.0.0.0, with a health check on /_stcore/health.
  • Snowflake, cloud platforms and Kubernetes. Recent versions also provide st.App, an ASGI application you can run with uvicorn or mount inside FastAPI or Starlette.

Authentication: st.login() starts an OpenID Connect flow (Google, Microsoft, Okta, Auth0 ...) configured under [auth] in secrets (redirect URI, cookie secret, client id and secret, metadata URL). Afterwards st.user.is_logged_in and st.user attributes such as email are available, and st.logout() ends the session.

Scaling: each user session holds a WebSocket and its session state in the server process, and runs reruns in threads. A single process serves many light users, but CPU-heavy reruns contend for the GIL. Scale out with several replicas behind a load balancer with sticky sessions (WebSocket affinity), share caches through external stores, and keep heavy computation in cached functions or background services.

Example

# .streamlit/config.toml
[server]
headless = true
port = 8501
maxUploadSize = 50          # MB
enableXsrfProtection = true

[theme]
base = "light"
primaryColor = "#E8383D"

# .streamlit/secrets.toml (excerpt) for st.login() with an OIDC provider
[auth]
redirect_uri = "https://app.example.com/oauth2callback"
cookie_secret = "a-long-random-string"
client_id = "..."
client_secret = "..."
server_metadata_url = "https://accounts.google.com/.well-known/openid-configuration"

# Dockerfile essentials:
#   CMD ["streamlit", "run", "app.py", "--server.address=0.0.0.0"]
#   HEALTHCHECK CMD curl -f http://localhost:8501/_stcore/health

Remember

  • Options come from config.toml, CLI flags or STREAMLIT_* environment variables
  • Deploy via Community Cloud, containers with /_stcore/health, or st.App under ASGI
  • st.login adds OIDC auth; scale out with sticky sessions and shared caches

Watch out for

  • Load balancing replicas without sticky sessions, which breaks the WebSocket connection to a user's session.

Check yourself

  1. You run three Streamlit replicas behind a load balancer and users randomly lose their state. What is the likely cause?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.streamlit.io/develop/api-reference/configuration/config.toml