# Streamlit data-app host

Source: https://docs.quake.ai/resources/iac-templates/streamlit
Markdown: https://docs.quake.ai/resources/iac-templates/streamlit.md

---

# Streamlit data-app host

This pattern composes Compute, Network, and Block Storage into a self-hosted data-app host you run on infrastructure you control.

## What this template does

Provisions a single instance running [Streamlit](https://streamlit.io), a Python framework for data apps and interactive demos (a self-hosted alternative to Streamlit Cloud or Hugging Face Spaces). You write Python, Streamlit renders widgets and charts in the browser, and your code reads datasets from the attached volume:

- Compute instance that runs Streamlit in Docker, sized for a single CPU-bound app (2 vCPU and 2 GiB RAM)
- Private network, subnet, router, port, and security group; a floating IP for public access
- A block volume mounted at `/opt/streamlit`, so your Python app code and data files live on a volume you can grow rather than on the boot disk
- cloud-init installs Docker Engine and starts Streamlit from a compose file on first boot

[Gradio](https://gradio.app) fits the same host shape if your team prefers Gradio widgets: swap the container image and entrypoint while keeping the volume layout.

Streamlit hosts internal dashboards, model demos, and analyst-facing tools on a VM you own. Quake AI flavors are CPU-only; GPU training belongs on an external backend.

No credential ships with this template. Add authentication at the reverse proxy or in your app if the dashboard should not be public.

## Parameters

| Parameter | Description | Default |
| --- | --- | --- |
| `key_name` | SSH keypair name (must already exist) | No default |
| `flavor_name` | Instance size (single Streamlit app on 2 vCPU / 2 GiB) | `s1a.small` |
| `image_name` | Operating system image | `Ubuntu-24.04` |
| `app_name` | Display name prefix for resources | `streamlit` |
| `volume_size` | Block volume size in GiB, mounted at `/opt/streamlit` | `20` |
| `external_network` | External network for floating IP allocation | `PublicStatic` |
| `private_cidr` | CIDR for the private subnet | `10.43.0.0/24` |
| `app_allowed_cidr` | CIDR allowed to reach the app on port 8501 | `10.43.0.0/24` |

## App access and security

The app listens on port 8501 over plain HTTP. The security group restricts 8501 to `app_allowed_cidr`, which defaults to the private network only, so the raw port stays off the public internet. Reach the app one of three ways:

- Put a reverse proxy (Caddy or Nginx) in front of Streamlit and serve the app over HTTPS on 443. Point the domain's DNS A record at the floating IP. This is the recommended path for routine access.
- Tunnel over SSH: `ssh -L 8501:localhost:8501 user@FLOATING_IP`, then open `http://localhost:8501`.
- Set `app_allowed_cidr` to `YOUR_IP/32` to reach port 8501 directly from one address.

Ports 80 and 443 stay open for the reverse proxy you put in front; they carry no traffic until you add one.


Streamlit does not ship authentication. Treat the app like any internal dashboard until you add auth at the reverse proxy or in your Python code.


## Deploying your own app

Replace the sample files under `/opt/streamlit/app` on the instance with your own Python modules and list dependencies in `requirements.txt`. Store datasets and artifacts under `/opt/streamlit/data`. Restart the container with `docker compose up -d` from `/opt/streamlit`.

## When to use this pattern

Host a Python data app or demo with charts, filters, and file uploads on a VM you operate. Streamlit suits analyst dashboards, lightweight model demos, and internal tools. For multi-user notebook servers, pair with the JupyterHub template in the data tooling catalog. For workflow automation around your data stack, see [n8n workflow automation](/resources/iac-templates/n8n-workflow).

## Estimated cost

<PricingCompanion
  components={[
    { kind: "template", slug: "streamlit", required: true },
  ]}
/>

## Template source

<TemplateSource slug="streamlit" />

<TemplateResourceMap template="streamlit" format="opentofu" />

## Customize this pattern

- [Customize a template's image and flavor](/docs/automation/how-to/customize-template-image-flavor)
- [Add a block volume to a template](/docs/automation/how-to/add-volume-to-template)
- [Parameterize a template with a tfvars file](/docs/automation/how-to/parameterize-template-tfvars)

## See also

- [self-managed PostgreSQL](/resources/iac-templates/self-managed-postgres)
- [Object Storage how-to guides](/docs/storage/object)
- [n8n workflow automation](/resources/iac-templates/n8n-workflow)
