Deploy a Flask app (Python)
Deploy a Flask or FastAPI app on OneBit Deploy from a GitHub repository — requirements.txt, gunicorn on port 8000, no Dockerfile. Python is in early access.
Python is in early access on OneBit Deploy: add a GitHub repository as an app, we
recognise it as A Python app, and we build a python:3.12-slim image, install requirements.txt and
start gunicorn on port 8000. No Dockerfile, no platform config file.
This page uses the exact files we run as our own canary — onebit-client/deploy-e2e-flask — so you can fork it or copy the two files below.
The two files
app.py must expose a WSGI callable named app:
import os
from flask import Flask, jsonify
app = Flask(__name__)
@app.get("/")
def index():
return jsonify(app="deploy-e2e-flask", framework="flask", runtime="python", port=os.environ.get("PORT", "8000"), ok=True)
@app.get("/health")
def health():
return "ok", 200
if __name__ == "__main__": # local dev only; on Deploy gunicorn serves app:app
app.run(host="0.0.0.0", port=int(os.environ.get("PORT", "8000")))requirements.txt lists Flask and gunicorn (we install gunicorn if it is
missing, but pin your own version so local and production match):
flask==3.1.*
gunicorn==23.*That is the whole repository. Push it to GitHub.
Deploy it
- In the console, on Apps, press Add app and open GitHub account (press Connect GitHub the first time).
- Pick the repository, choose the Branch and press Use this
project. We look for
requirements.txt(or an installablepyproject.toml) in the root directory, and the console says "A Python app." If it does not, open More settings and set Framework to Python; Port is8000. - Check the Name and press Deploy. The size is set for you from your plan.
- The Python version is
3.12(3.11 and 3.13 are available) and the start command is empty. Leave the start command empty unless you need a custom entry point; both are in the app's Settings → Build settings → Change how it is built (Runtime version, Start command) and apply on the next update.
The build takes about 30 seconds for a repo this size. When it finishes your app
answers on https://<name>-<id>.app.onebit.ng/ with automatic HTTPS.
What runs in the container
Without a start command the image runs:
gunicorn -b 0.0.0.0:8000 --workers 2 --threads 4 --timeout 60 --access-logfile - app:appThe module is picked at build time from the files in your root directory:
| Found | Module |
|---|---|
manage.py + <project>/wsgi.py | <project>.wsgi:application (Django — see Deploy a Django app) |
app.py | app:app |
main.py | main:app |
wsgi.py | wsgi:app |
The build log prints the line it chose as Start command: …. PORT is set to the
container port (8000 by default) and the process runs as a non-root user.
FastAPI
FastAPI is ASGI, so it needs an ASGI worker. If fastapi is in requirements.txt we
install uvicorn[standard] and run gunicorn with -k uvicorn.workers.UvicornWorker
against the detected module (main:app for the usual main.py). To be explicit, set
the start command instead:
uvicorn main:app --host 0.0.0.0 --port 8000Custom start command
The Start command field (app Settings → Build settings) becomes the container's CMD verbatim (run through
sh -c, as the same non-root user). Use it for a different callable, extra gunicorn
flags, or a migration step before the server starts:
gunicorn myapp.server:application -b 0.0.0.0:8000 --workers 4Environment variables
Add secrets and settings on the app's Environment tab (Add variable); they are injected into
the container at runtime (and written to a .env in the build context). Read them
with os.environ. PORT is always present. See
Environment variables.
Good to know
- Free plan apps sleep when idle and wake on the next request (the first visit after a quiet period waits for the container to start). Starter and above stay always-on — see Scaling & idle.
- Dependencies come from
requirements.txtfirst; without one we runpip install .when the repo has apyproject.toml. - Extra build steps (for example
pip install -r requirements-prod.txt) go in the Build command under the app's Settings → Build settings → Change how it is built (commands separated by commas); they run after the install asRUNlines. - Your own Dockerfile wins. If the repository carries a
Dockerfilewe build from it and none of the above applies.
Next steps
Builds & frameworks
How OneBit builds your app, which frameworks are supported, and how to configure the build.
Deploy a Django app (Python)
Deploy a Django project on OneBit Deploy from GitHub — gunicorn on port 8000, ALLOWED_HOSTS and SECRET_KEY from environment variables, migrations and static files. Python is in early access.