DocsFlask and FastAPI

Flask and FastAPI

Deploy a Flask or FastAPI app on Ruust: served by Gunicorn or Uvicorn, bound to $PORT on 0.0.0.0, on HTTPS.

Ruust runs your Python web app as an Egg: a long-running server, always on, with no cold starts. Nixpacks auto-detects a Python project from a requirements.txt (or pyproject.toml) at the repo root, installs your dependencies and lays the Egg. If your repo has a Dockerfile, Ruust builds that instead. This page covers Flask served by Gunicorn and FastAPI served by Uvicorn.

Deploy it

  1. Pin your dependencies in requirements.txt (include gunicorn for Flask, or uvicorn for FastAPI).
  2. Add a Procfile at the repo root with a web: line so Ruust knows how to start the server.
  3. Push your app to a Git repo.
  4. In the dashboard, choose New Egg, connect the repo and pick a Coop.
  5. Pick a size and a region (London, Virginia, or your own byo host), then lay the Egg.

Dependencies

Ruust installs from requirements.txt. Include your framework and its server: Gunicorn for Flask, Uvicorn for FastAPI.

text
flask
gunicorn

# or, for FastAPI:
fastapi
uvicorn[standard]
requirements.txt: pin your framework and its production server.

The port

Ruust sets a PORT env var. Your server must listen on it and bind to 0.0.0.0, not localhost (127.0.0.1). Binding to the wrong address is the top reason an Egg builds but never hatches: the process starts, but nothing outside the container can reach it. Do not use the built-in development server (flask run, or uvicorn with --reload) in production. Pin the start command with a web: line in a Procfile at the repo root.

text
web: gunicorn app:app -b 0.0.0.0:$PORT
Procfile for Flask: Gunicorn binds to 0.0.0.0 on $PORT. Here `app:app` is `module:variable`.
text
web: uvicorn main:app --host 0.0.0.0 --port $PORT
Procfile for FastAPI: Uvicorn binds to 0.0.0.0 on $PORT.

Environment variables

Set env vars on the Egg for secrets like SECRET_KEY and DATABASE_URL. They are available at both build and run time, encrypted at rest, and never printed in logs. Read them with os.environ in your app.

python
import os

DATABASE_URL = os.environ["DATABASE_URL"]
SECRET_KEY = os.environ["SECRET_KEY"]
Read configuration from the environment, never from committed files.

Custom domains and networking

Every Egg gets a <name>.<region>.ruust.run URL on HTTPS. To use your own domain, add it to the Egg, point the DNS record shown, and Ruust issues and renews TLS automatically. If your API talks to a database or another service Egg in the same Coop, turn on private networking and peer the two Eggs: connected Eggs reach each other by a private hostname. It is deny-by-default, so only Eggs you explicitly connect can talk.