ABS guide draft · setup · fix-pass applied after NEEDS_FIXES review

Hugging Face Spaces — Quick Deploy for an AI Demo or Agent Backend

Setup guide for shipping a Gradio, Streamlit, or Docker Space on huggingface.co with secrets, hardware tiers, and a working Dockerfile.

Review copy · Updated July 22, 2026

Hugging Face Spaces — Quick Deploy for an AI Demo or Agent Backend

A Hugging Face Space is a git-backed app host. Push code, let Hugging Face build it, and the app gets an hf.space URL. This guide leads with the shortest useful path—a small Gradio demo—then gives a compact Docker alternative for custom backends or Streamlit.

By the end, you will have created a Space, pushed an app, configured a secret, and checked the deployed URL. One pricing distinction matters before you begin: CPU Basic costs $0 per hour, but creating a Gradio or Docker compute Space requires PRO for a personal account or Team/Enterprise for an organization. Static Spaces are free for everyone. Qualifying free personal accounts may host up to two Gradio ZeroGPU Spaces.

What a Hugging Face Space actually is

A Space combines a Hub git repository, an automated build, a hosted runtime, and an app URL. Each pushed commit triggers a rebuild and restart. A public Space exposes both its code and app; a protected Space keeps code private while the app remains public; a private Space limits both to owners and collaborators.

The current SDK choices are Gradio, Docker, and static HTML. Use Gradio for a small interactive demo. Use Docker for FastAPI, Flask, Go, a custom runtime, or a new Streamlit deployment. Hugging Face’s built-in Streamlit SDK is deprecated; its docs direct new Streamlit Spaces to Docker plus the Streamlit template.

🤖 Let your agent do it: ask your installed agent:

I want to deploy a Hugging Face Space. Ask what the app does, whether it
is a quick demo or a backend another service will call, and whether it is
Streamlit. Recommend Gradio, Docker, or static HTML under the current
Hugging Face account-plan rules, then explain the choice in one paragraph.

Before you start

You need:

  • A Hugging Face account at huggingface.co/join. Account plan determines what you can build:
    • Free personal accounts can use CPU Basic Spaces for static or graded demos and may host up to 2 Gradio ZeroGPU Spaces if their account is in good standing.
    • Gradio / Docker Spaces that compute on Hugging Face infrastructure require a paid plan (PRO, Team, or Enterprise). Static Spaces remain free.
    • Visibility (Public / Protected / Private) is a separate choice from plan. Private Spaces restrict both the app and source; they are plan-gated only insofar as Private requires the same plan tier the Space type already needs.
  • A Personal Access Token with write scope, at huggingface.co/settings/tokens. You’ll use it once to push; you can revoke it after.
  • git and a working terminal. The Spaces build pipeline runs git push on whatever you have locally; no huggingface-cli required.
  • Time budget: ~15 minutes for a Gradio or Streamlit Space; ~30–45 minutes for a Docker Space the first time (the Docker build itself usually takes 2–10 minutes).

Two things you do not need: a credit card for Static-only or CPU Basic Gradio usage, or inbound port forwarding on your machine. Spaces run on Hugging Face’s infrastructure; you push and walk away.

Install

1. Create the Space

Open huggingface.co/new-space, choose a name, and select Gradio for the fast path. Choose Docker for a custom backend or Streamlit. CPU Basic has no hourly charge, although the compute-Space account-plan requirement above still applies.

Choose visibility deliberately:

  • Public: source and running app are public.
  • Protected: source is private but the app URL is public; Hugging Face documents this as PRO/Team/Enterprise-only.
  • Private: source and app are available only to owners and collaborators. Hugging Face does not document private visibility as PRO-gated.

🤖 Let your agent do it: if it has browser automation, say:

Open https://huggingface.co/new-space. Create <name> as a public
<Gradio|Docker> Space on CPU Basic. Do not select legacy Streamlit:
use Docker if this is a Streamlit app. Report the repository URL.

2. Clone and write the app

Use hf auth login if you have the current hf CLI installed. Otherwise, HTTPS Git accepts a write token as the password.

git clone https://huggingface.co/spaces/<username>/<space-name>
cd <space-name>
git config user.email "[email protected]"
git config user.name "Your Name"

For Gradio, create app.py:

import gradio as gr

def greet(name):
    return f"Hello, {name}! Your Space is live."

demo = gr.Interface(fn=greet, inputs="text", outputs="text",
                    title="Quick Smoke Test")
demo.launch()

And requirements.txt:

gradio>=4.40,<5

Gradio Spaces install requirements.txt and run the application. No Dockerfile is needed.

For Docker, keep the same small app.py but add a Dockerfile. This pattern follows Hugging Face’s UID 1000 guidance:

FROM python:3.11-slim
RUN useradd -m -u 1000 user
ENV HOME=/home/user PATH=/home/user/.local/bin:$PATH
WORKDIR $HOME/app
USER user
COPY --chown=user requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY --chown=user . .
EXPOSE 7860
CMD ["python", "app.py"]

Set Docker metadata at the top of README.md:

---
title: My Docker Space
emoji: 🐳
colorFrom: blue
colorTo: green
sdk: docker
app_port: 7860
---

Docker exposes the single port named by app_port; its default is 7860. For a new Streamlit Space, select Docker and start from Hugging Face’s Streamlit Docker template. Port 8501 is the usual Streamlit template default, but a Docker Space exposes whichever single port its app_port declares and the app actually binds.

🤖 Let your agent do it: say:

Clone https://huggingface.co/spaces/<user>/<name>. If the chosen path is
Gradio, write app.py and requirements.txt for <app description>. If it is
Docker+Streamlit, use the official Streamlit Docker-template structure. If
it is generic Docker, create a UID-1000 Dockerfile and matching README
app_port. Commit the files, but ask before pushing.

Configure

Add secrets

In the Space’s Settings → Variables and secrets, create a secret such as OPENAI_API_KEY. At runtime, Spaces exposes it as an environment variable:

import os
api_key = os.environ["OPENAI_API_KEY"]

Official docs say secret values cannot be reread from Settings after they are set and are not copied when someone duplicates the Space. Do not commit credentials. If one enters git history, rotate it immediately and then clean the history.

🤖 Let your agent do it: ask it to open the Space Settings page and navigate to the secret form, but paste the value into the browser yourself. Do not send credentials through chat or ask the agent to echo them.

Push and watch the build

git add app.py requirements.txt
git add Dockerfile README.md  # Docker path only
git commit -m "first deploy"
git push

A push triggers a rebuild and restart. Watch the Space page change from Building to Running, or open its runtime logs for the exact error. The docs do not guarantee that a failed deployment leaves the prior version running, so treat every push as a deployment.

Persistent data

The default disk is ephemeral: its contents may be lost when the Space restarts or stops. For durable data, create a Storage Bucket, then attach it as a volume while creating the Space, from Space Settings, or through huggingface_hub. Choose the mount path you want and select read-write or read-only. Storage attachment is not configured through README metadata, and /data is not the required mount path.

Buckets are mutable and non-versioned, so deletions are immediate. Use them for working data, logs, or agent state that does not need Git history; use a repository when versioning matters.

Verify

For a public or protected Space, test the app URL:

curl -fsS -o /dev/null -w '%{http_code}\n' \
  https://<space-subdomain>.hf.space

Expect a 2xx. Do not require HTTP/2 or rely on HEAD behavior. A private Space is different: an anonymous request may return 404; verify it while signed in as an owner or collaborator instead.

Then use the UI once. Submit a Gradio input or call the Docker endpoint. If the request needs a secret, trigger it and check runtime logs without printing the secret itself.

Command map

Command / actionJobSuccess stateIf it fails
git clone https://huggingface.co/spaces/<u>/<s>Downloads the Space repo.Directory exists and git remote -v shows Hugging Face.Authenticate with hf auth login, SSH, or a write token as the HTTPS password.
Write Gradio filesDefines the quick-path app.app.py and requirements.txt exist.Read the build traceback for the exact import or syntax error.
Write Docker filesDefines the custom runtime and public port.README has sdk: docker; app binds the same app_port.Compare README, Dockerfile, application bind address, and runtime logs.
Add a Settings secretInjects sensitive runtime configuration.Secret name appears in Settings.Match the case-sensitive environment-variable name in code.
git pushStarts a build and restart.Space reaches Running.Open build/runtime logs; do not assume rollback.
curl -fsS ...Checks public routing.Public/protected Space returns 2xx.Confirm visibility and inspect runtime status/logs.

Common failures and fixes

Treat the runtime log as authoritative for your deployment. Forum reports may reveal possibilities, but they do not establish universal causes.

SymptomEvidence-based first checkConservative next step
Build or startup timeoutOpen logs and identify whether time was spent building or starting. The official startup_duration_timeout README setting controls startup health-check time and defaults to 30 minutes.Fix the slow startup first. Increase the timeout only when the app legitimately needs longer.
App is unhealthy after the container startsFor Docker, confirm the app listens on 0.0.0.0 and the same port declared by app_port; Docker’s documented default is 7860.Correct the bind/port mismatch, push, and reread runtime logs.
DNS or download failureNote whether the failure occurred during build or runtime and copy the exact hostname and exception from logs.It may be transient infrastructure or DNS trouble; retry once, then report the exact log and commit if it persists.
Build remains queuedCheck Space status and logs rather than inferring a code failure.It may be transient infrastructure congestion. Wait and retry; if persistent, post the Space URL and logs in the Spaces forum.
Secret is missingCompare the case-sensitive Settings name with os.environ.Recreate the secret if necessary; never print its value.
Process is killed or restartsInspect runtime logs and compare memory use with CPU Basic’s 16 GB RAM.Reduce memory use or select suitable hardware. T4 small currently lists 16 GB VRAM at $0.40/hour; upgraded hardware is billed while Starting or Running.

When not to use it

Spaces are best for demos and lightweight hosted apps, not every production backend. Free hardware sleeps after inactivity. The cited docs do not promise an availability SLA or rollback after a failed deploy. For no-cold-start, dedicated production inference, evaluate Hugging Face Inference Endpoints or a conventional application host.

Do not use ephemeral disk for durable state. Attach a bucket volume or use an external database. For sensitive workloads, review visibility, authentication, data residency, and compliance requirements rather than assuming a private toggle is sufficient.

Security, updates, and embedding

Keep credentials in Settings secrets and avoid printing them. Public Spaces expose source and app; protected Spaces expose the app; private Spaces restrict both. After dependency or platform changes, rerun the smoke test and review logs before automating deployments.

Public and protected Spaces can be embedded with the official plain iframe form; no extra query parameter is required:

<iframe src="https://<space-subdomain>.hf.space"
        frameborder="0" width="850" height="450"></iframe>

For help, use the Spaces docs index or Spaces forum. Include the Space URL, commit SHA, SDK, hardware tier, exact status, and relevant redacted logs.

Sources

Last verified: 2026-07-22 by Hermes. The draft was independently reviewed in a fresh MiniMax M3 context, and this revision applies the review’s five priority fixes.