Deploy a FastAPI app.
Add requirements.txt, a Procfile with $PORT and a run-zero.yaml. The buildpack installs the packages and starts Uvicorn, and Flask runs the same way with gunicorn.
Needs the Developer plan, the free plan only covers websites. Pricing · Check the limits first
- FastAPI and Flask tested
Procfilelike on Heroku- HTTPS from the first deploy
> Deploy the python-fastapi folder to run.zero.
runzero_create_appdoneexample-fastapi
runzero_push_filesdoneone commit
runzero_deploydoneservices created
runzero_wait_for_builddonelive
live at https://web-example-fastapi-84f30cf3.run-zero.de
- Live demoRunning on run.zero(opens in a new tab)
- Example codeMIT, on GitHub(opens in a new tab)
- BuildpacksNode, Python, Go, PHP, Java
- Hosted in GermanyHetzner, Nuremberg
Live in four steps.
Tested with the example that runs live.
- 01
Pin your dependencies
A
requirements.txtat the root lets the buildpack detect Python. According to the docs,Pipfileandpyproject.tomlare detected too. - 02
Write the Procfile
The
webprocess gets the address and must listen on0.0.0.0:$PORT.Procfile web: uvicorn main:app --host 0.0.0.0 --port $PORT - 03
Add run-zero.yaml
One service, port 8080.
run-zero.yaml version: "1"services: web: port: 8080 - 04
Create an account and deploy
Create an account, connect your agent with this command, then sign in from Claude Code with
/mcpand Authenticate.- Then tell your agent: deploy this repo to run.zero.
Without an agent
Create the app in the dashboard and connect your GitHub repo. Every push rebuilds.
Connect Claude Code claude mcp add --transport http \ -s user run-zero \ https://api.run-zero.de/mcp \ --client-id runzero-cli \ --callback-port 53761
After 1 to 3 minutes the app is live at https://web-<app>.run-zero.de. Check a route of your app, in the example /api/health. If the build is red, runzero_get_build_logs tells you why.
Three files plus the config.
Exactly as they sit in the example that runs live.
The app with / and /api/health, /docs comes from FastAPI.
# Minimal FastAPI app for run.zero. Uvicorn binds to $PORT, see Procfile.import platformfrom fastapi import FastAPIfrom fastapi.responses import HTMLResponseapp = FastAPI(title="FastAPI on run.zero")@app.get("/", response_class=HTMLResponse)def index() -> str: return """<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>FastAPI on run.zero</title></head><body style="font-family:system-ui,sans-serif;max-width:640px;margin:64px auto;padding:0 24px"><h1>FastAPI on run.zero</h1><p>This Python app was built by a Paketo buildpack and runs under Uvicorn.</p><p><a href="/api/health">/api/health</a> · <a href="/docs">/docs</a></p></body></html>"""@app.get("/api/health")def health() -> dict: return {"status": "ok", "runtime": f"python {platform.python_version()}", "platform": "run.zero"}fastapi and uvicorn, pinned.
fastapi==0.115.6uvicorn==0.34.0Same line, different server.
Only the Procfile changes.
| Framework | Procfile |
|---|---|
| FastAPI | web: uvicorn main:app --host 0.0.0.0 --port $PORT |
| Flask | web: gunicorn app:app --bind 0.0.0.0:$PORT |
| Django, not tested | web: gunicorn project.wsgi --bind 0.0.0.0:$PORT |
What does not work today.
So the first build goes through.
Needs the Developer plan
Free has no server apps and no Postgres, a deploy stops with an error.
See pricingPython version
The live demo runs the buildpack’s default version, 3.11 at the time of testing.
Files need a volume
Without
volumes:, SQLite files and uploads do not survive a restart. Volumes start at the Developer plan, and we tested them with the PocketBase image.Django not tested
FastAPI and Flask run live. For Django we only show the start command.
What you stop doing yourself.
Builds, HTTPS, the database and backups run on the platform.
Data stays in Germany
Servers and backups at Hetzner in Nuremberg. With a data processing agreement.
HTTPS by default
Every service gets an address on
run-zero.de, custom domains a Let’s Encrypt certificate.Postgres as an addon
One entry in
run-zero.yaml,DATABASE_URLarrives as an environment variable.No lock-in
Your code stays in your repo, the database is a dump you can download.
Questions.
About Python.
Does this work with Flask?
Yes. The Heroku example is a Flask app with gunicorn and Postgres, and it runs live.
How do I connect to Postgres from Python?
Attach the Postgres addon. psycopg accepts DATABASE_URL including sslmode=require as is.
Can I run a worker?
According to the docs, other process types in the Procfile run without an inbound address. We only tested the web process here.
Is /docs public?
Yes, FastAPI serves /docs by default. Turn it off with docs_url=None if you do not want it.