How to Deploy a Flask App in India (with gunicorn) | Replov
Skip to main content

Flask

Deploy a Flask app on Replov

A Flask app runs on Replov as a Web Service with a public HTTPS address. Replov builds the repository with Nixpacks, finds the Flask app in app.py or main.py, and starts it on gunicorn when gunicorn is in your dependencies.

Without gunicorn, Replov can only start Flask’s development server, which is not meant for real traffic; the build log then tells you to add gunicorn.

Last verified against the product on .

Before you start

  • A Flask app in a GitHub repository, with flask and gunicorn in requirements.txt (gunicorn listed in pyproject.toml or a Pipfile is also recognised).
  • The Flask object named app in app.py or main.py at the service’s root directory, or your own Start Command (see below).

How Replov builds it

  • Replov detects Python from requirements.txt and builds the image with Nixpacks, which installs the dependencies.
  • With no version declared, Python 3.12 is used. The build log shows the Python version and where it came from.
  • When Start Command is empty and gunicorn is a dependency, Replov uses gunicorn app:app --bind 0.0.0.0:${PORT:-3000} --workers ${WEB_CONCURRENCY:-2} --threads 4 --access-logfile - --forwarded-allow-ips='*' (or main:app for main.py) and prints it in the build log.
  • A Dockerfile in the service’s root directory replaces all of this.

Deploy it

  1. 1

    Sign in to Replov and connect GitHub (Connect GitHub / Import from GitHub). Replov asks for access to the repositories you choose.

  2. 2

    Create a project for the repository, then add a service to it.

  3. 3

    Choose Service Type: Web Service, select the repository and Branch, and set Root Directory if the app lives in a subfolder.

  4. 4

    Leave Build Command and Start Command empty. If your app is created elsewhere, for example in wsgi.py, set Start Command to gunicorn wsgi:app --bind 0.0.0.0:$PORT --workers 2 --threads 4.

  5. 5

    Add Environment Variables. Store SECRET_KEY, database URLs and API keys as secrets.

  6. 6

    Pick the Compute Tier for this Service and deploy. Check that the build log’s detected start command begins with gunicorn.

Example: app.py and requirements.txt

# app.py
import os
from flask import Flask
from werkzeug.middleware.proxy_fix import ProxyFix

app = Flask(__name__)
app.config["SECRET_KEY"] = os.environ["SECRET_KEY"]
# Optional: the visitor's IP in request.remote_addr
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1)

@app.get("/health")
def health():
    return {"status": "ok"}

# requirements.txt
flask
gunicorn

Environment variables and ports

  • Replov sets PORT (3000) and routes traffic to it. A custom Start Command must bind to 0.0.0.0:$PORT.
  • gunicorn runs 2 worker processes with 4 threads each, which fits a typical app on Nano (512 MB). Set WEB_CONCURRENCY to change the number of workers on a larger tier.
  • Each request is logged to the runtime logs. Those lines, and request.remote_addr, show Replov’s proxy address; wrap the app in Werkzeug’s ProxyFix if you need the visitor’s IP.
  • Secrets are encrypted at rest and injected at runtime only; read them with os.environ.

Domains and HTTPS

Every web service and static site gets an HTTPS address of the form <service-name>-<4 characters>.replov.com once it is live.

To use your own domain, open the service, choose Connect Domain and publish the CNAME and TXT records Replov shows at your DNS provider. After verification Replov routes the hostname and issues a Let’s Encrypt certificate automatically. More on HTTPS.

Logs and monitoring

The build log streams while the deployment runs; the first failing command and the lines just above it usually explain a failed build. Runtime logs (with live streaming) and CPU, memory and network metrics are on the service page. See service logs.

Troubleshooting

The build log warns that the app is running on its development server
gunicorn is not in requirements.txt. Add it and redeploy.
The build log shows `python app.py` as the start command
Replov did not find Flask in app.py or main.py. Set Start Command to gunicorn <module>:app --bind 0.0.0.0:$PORT.
The deployment fails its reachability check
A custom Start Command is listening on a fixed port (often 5000 or 8000) or on 127.0.0.1. Bind to 0.0.0.0:$PORT.
Workers are killed or the app runs out of memory
Lower WEB_CONCURRENCY, or move the service to a larger tier.

Deploy your repository on Replov

Connect GitHub, choose a service type and a compute tier, and watch the build log.