Skip to main content
Version: 2.0.11

How to Deploy a Flask App (Python) with Gunicorn

This guide shows how to put a Flask application online with OpenPanel. The app runs in its own Python container, and OpenPanel's web server forwards your domain to it, with a free SSL certificate.

INFORMATION

Python applications are available in OpenPanel Enterprise. The feature must be enabled for your hosting plan.


How It Works​

  • Your code lives in the domain's folder, e.g. /var/www/html/example.com/.
  • OpenPanel starts an official python container with that folder as the working directory.
  • On every start, the container can run pip install -r requirements.txt and then your startup command.
  • The web server (Nginx, Apache, OpenResty or OpenLiteSpeed) proxies https://example.com to the port your app listens on.

Step 1: Prepare the App​

A minimal project:

example.com/
├── app.py
└── requirements.txt

app.py:

from flask import Flask

app = Flask(__name__)

@app.route("/")
def index():
return "Hello from Flask on OpenPanel!"

requirements.txt:

Flask==3.0.3
gunicorn==23.0.0

Flask's built-in server (app.run()) is for development only. In production, run the app with Gunicorn.


Step 2: Add the Domain and Upload the Code​

  1. Add the domain in OpenPanel → Domains (see Add a new domain) and point its DNS to the server.
  2. Upload your files to the domain's folder with the File Manager, FTP, or skip this step and deploy from Git in the next step.

Step 3: Create the Python Application​

Go to OpenPanel → Websites → Install App → Setup Python Application and fill in:

FieldValue
Namee.g. flaskapp
Domainexample.com (optionally with a subfolder)
Port8000
Startup Fileapp.py
Custom Startup Commandgunicorn --bind 0.0.0.0:8000 --workers 2 app:app
Versiona current Python version, e.g. 3.12
Run Install✅ Yes - runs pip install -r requirements.txt on start
Git repositoryoptional - an https:// URL of your repository
CPU / Memorye.g. 1 core and 0.5 GB

Install Python Application form with the application details, domain, startup file and advanced options Install Python Application form with the application details, domain, startup file and advanced options

Click Start Installation. When it's done, open https://example.com.

app:app means module app (the file app.py) and the Flask object named app. If your project uses an application factory, wrap it in single quotes: gunicorn --bind 0.0.0.0:8000 'app:create_app()'. Don't use double quotes in the startup command.

Deploy from Git

If you fill in a Git repository URL, the container fetches the latest commit of the default branch every time it starts. To deploy a new version, push to the repository and click Restart on the application's page. Only public https:// repositories are supported (no SSH keys).


Step 4: Connect a Database​

Create a database and user in OpenPanel → MySQL → Database Wizard (or PostgreSQL). Inside containers, databases are reached by service name, not localhost:

DatabaseHostPort
MySQLmysql3306
MariaDBmariadb3306
PostgreSQLpostgres5432

Example with SQLAlchemy:

import os
from flask_sqlalchemy import SQLAlchemy

app.config["SQLALCHEMY_DATABASE_URI"] = os.environ.get(
"DATABASE_URL", "mysql+pymysql://dbuser:dbpass@mysql:3306/dbname"
)
db = SQLAlchemy(app)

Add Flask-SQLAlchemy and PyMySQL (or psycopg2-binary for PostgreSQL) to requirements.txt. See connecting to MySQL from applications.


Step 5: Secrets and Environment Variables​

Keep secrets out of your code. Put them in a .env file in the app folder and load it with python-dotenv:

# /var/www/html/example.com/.env
SECRET_KEY=change-me
DATABASE_URL=mysql+pymysql://dbuser:dbpass@mysql:3306/dbname
from dotenv import load_dotenv
load_dotenv()

Don't commit the .env file to Git. Restart the app after changing it.


Managing the App​

Open OpenPanel → Websites → Sites and click Manage next to the app:

  • Restart after changing code or settings (Gunicorn doesn't reload automatically).
  • Install Packages to edit requirements.txt and run pip.
  • Logs to see Gunicorn output and Python tracebacks.
  • Overview to change the startup command, Python version and CPU/memory limits.

Python application page with its status, runtime version, CPU and memory limits, and Stop and Restart actions Python application page with its status, runtime version, CPU and memory limits, and Stop and Restart actions

More details: Python applications.


Troubleshooting​

ProblemFix
502 Bad GatewayThe app isn't listening on the configured port, or crashed on start. Check Logs, and make sure Gunicorn binds to 0.0.0.0:8000 - not 127.0.0.1. See 502 errors.
ModuleNotFoundErrorThe package is missing from requirements.txt, or Run Install is off.
Database connection refusedUse mysql / mariadb / postgres as the host, never localhost.
Container restarts in a loop / killedThe memory limit is too low. Increase it in Overview.