Is it really OK to ignore the Flask production warning?

When you start a Flask project, you see this message: WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.

Several people have asked, what should I do about this? They get the reply: just ignore the warning, it’s fine.

But the Flask documentation says:

When running publicly rather than in development, you should not use the built-in development server (flask run). The development server is provided by Werkzeug for convenience, but is not designed to be particularly efficient, stable, or secure.

Instead, use a production WSGI server.

Is there something different about Replit that means this advice doesn’t apply?

2 Likes

Welcome to the forums, @ciphergoth!
It’s true, you can ignore it. The Flask docs say this because WSGI servers often have slightly more security.

1 Like

Help me understand why? Are the Flask team just wrong?

Hello @ciphergoth!

A production WSGI server uses proxy managers like nginx and is usually more secure.
I usually ignore the warning, but you can do whatever you want.

1 Like

:arrow_up:
You could of course ignore it, but I can also assist you if you want to migrate to a BaseWSGIServer.

1 Like

When I search for BaseWSGIServer I find this file:

A WSGI and HTTP server for use during development only. This
server is convenient to use, but is not designed to be particularly
stable, secure, or efficient. Use a dedicate WSGI server and HTTP
server when deploying to production.

It doesn’t seem like setting that up would address the issue.

No, but I can also assist to migrating to more WSGI servers. Really, Flask is very secure and you should be just fine using it.

If it’s a security thing, surely I shouldn’t be ignoring it?

Because WSGI is used to build the web server part of Flask, but Flask has some of the best security for a simple web server out there, so you will be perfectly fine without a WSGI server.

The developers of the Flask server themselves say that they don’t think their server is secure - we’re saying that their own documentation is mistaken, and actually their server is secure enough for production use?

It’s simply a precaution – if you really want a WSGI server, I can help.

Gunicorn is easy to set up with Flask. Here’s the guide to set up Flask with Gunicorn.

2 Likes

Before I want to make a change, I want to understand the current situation. I see a couple of possibilities:

  • The warnings in the Flask documentation that the built-in server are insecure should not be taken seriously, the developers are underestimating the security of their own code and it’s actually fine to use it in production.
  • The warnings in the Flask documentation that the built-in server are insecure should be taken seriously, and no-one should be using this in production.

Do you have a sense of which of these is true? Everyone is insisting that it’s fine to use this in production, but they shy away from explicitly saying that the Flask developers are mistaken about the security of their own code. Of course I can do what I want but I want to understand what the right thing is.

1 Like

The tricky thing about gunicorn is that it isn’t just a question of modifying my Python file to call gunicorn in the main function - gunicorn wants to be called instead of Python. I couldn’t figure out how to make that work correctly with replit’s declarative nix/poetry based dependency support - poetry run gunicorn ... worked locally, but failed mysteriously in deployment. pip install gunicorn works but that’s not declarative.

Bjoern doesn’t have this issue, and everyone says it’s faster. I was able to make this work by adding it to my pyproject.toml and updating replit.nix to include pkgs.libev. See https://replit.com/@ciphergoth/AwesomeDirtyKeygenerator

Seems like this would be a good default for new Flask projects?

Make two files: app.py (for your Flask), and server.py (for the Gunicorn). server.py should look like this:

import sys
from gunicorn.app.wsgiapp import run
if __name__ == '__main__':
    sys.argv = "gunicorn --bind 0.0.0.0:5151 app:app".split()
    sys.exit(run())

Then your app.py can be whatever Flask.

Make sure to install all necessary modules.

2 Likes

Hey @ciphergoth, I am responsible for the support team at Replit (who you can get in touch with using the ? button in the Replit Workspace). I wanted to drop in quick and mention a few things.

First, I agree this is super confusing and am thankful you took it upon yourself to raise it up again :pray:

  1. It’s not a great idea to ignore a warning unless you understand the cost/benefit of doing so
  2. I’m not a Flask expert but I wouldn’t consider flask run for any sort of production deployment
  3. This thread made the rounds internally. Deploying a simple app following best practices should be quick and easy. Not confusing and hard. Your experience is confusing and hard :frowning_face:
  4. We are planning to produce an officially supported Template to follow the best practices for both dev and deploy servers
5 Likes

Thank you, this is great to read.

You put this exactly right, thank you. It’s not “never ignore a warning”, it’s “don’t ignore a warning until you understand why it’s there”. Chesterton’s warning :slight_smile:

Hah, glad to have made the rounds, I know what that’s like :slight_smile: waves to all the lovely smart and hard-working people at Replit

Yes, I was surprised that the template didn’t handle this for me automatically. It makes Flask feel unloved, and yet this is what replit guided me towards when I wanted to write a webapp in Python which has to be one of the more popular choices.

Looking forward to seeing the official Template for this - thanks again!

3 Likes

I’ve added a README to my sample app, describing all the changes I made to the default Flask app to get something well rounded:

https://replit.com/@ciphergoth/ciphergoths-sample-Flask-app#README.md

In particular I think ProxyFix is also important.

Hope this is useful to the team creating the improved Flask Template!

3 Likes

@ciphergoth I appreciate you raising this concern! I’ve update the Flask template to use gunicorn in Development and in Deployments.

Edit: We’ll look into using ProxyFix.

9 Likes

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.