I am currently setting up a FastAPI application to run on an AWS RockyLinux 8 instance with a gunicorn deployment. Most of the documentation that I have read recommends NGINX as a proxy server.
I currently have an Apache sever running on this instance and would rather not install another HTTP daemon if I can help it.
My question is: Why is a proxy HTTP server needed at all? gunicorn seems to run just fine without a proxy HTTP server simply by specifying a port other than 80. Is this a security recommendation or am I missing something?
Related
I have a Flask application currently using http being hosted on an ec2 instance. I want to host my application using https. Currently with http, I am able to access my application (running on 0.0.0.0 port 80) by just accessing the ec2 public IP address (displays Running on http://0.0.0.0:80/, and I am able to use my app at http://IP).
I am following this tutorial to test https support: https://blog.miguelgrinberg.com/post/running-your-flask-application-over-https.
When I add the most basic app.run(ssl_context='adhoc') to my program, the app is now Running on https://0.0.0.0:80/, but I am unable to access my app at https://IP. I opened up my port 403 in my EC2 settings however I am still unable to communicate with my app using https...no response whenever I make a request.
The same no response occurs when I run the application with gunicorn. Am I missing something? I think my requests are well formed, however I am never able to communicate with my app when using https.
Simple way is put your instance behind ALB. ALB is not only load balancer, but also integrate ACM for free.
I've got a web app developed in Flask. The setup is simple. The app is running on Gunicorn. All requests are proxied through the nginx. The Flask app itself makes HTTP requests to external API. The HTTP requests from the flask app to the external API are initiated by AJAX calls from the javascript code in the frontend. The external API returns data in JSON format to the Flask app and the back to the frontend.
The problem is that when I run this app in development mode with the option multithreaded = True I can see that the JSON data get returned asynchronously to the server and I can see the result on the frontend page very quickly.
However, when I try to run the app in production mode with nginx and gunicorn I see that the JSON data get returned sequentially - quit slowly, one by one. It seems that due to some reason the HTTP requests to the external API get blocked.
I use supervisor on linux Ubuntu Server 16.04. This is how I start gunicorn through supervisor:
command = /path/to/project/env/bin/gunicorn -k gevent --worker-connections 1000 wsgi:app -b localhost:8500
It seems that gunicorn does not handle the requests asynchronously, although it should.
As experiment I ran the Flask app using it's built in wsgi server (NOT gunicorn) in development mode, with debug=True and multithreaded=True. All requests were still proxied through the nginx. The JSON data returned much quicker, i.e. asynchronously (seems the calls did not block).
I read gunicorn's documentation. It says if I need to make calls to external API, then I should use async workers. I use them but it doesn't work.
All the caching stuff was taken into account. I may assume that I don't use any cache. I cleared it all when I checked the server setups.
What am I missing? How can I make gunicorn run as expected?
Thanks.
I actually solved this problem quite quickly and forgot to post the answer right away. The reason why the gunicorn server did not process the requests acynchronously as I would expect was very simple and stupid. Since I was managing gunicorn through the supervisor after I had changed the config to:
command = /path/to/project/env/bin/gunicorn -k gevent --worker-connections 1000 wsgi:app -b localhost:8500
I forgot to run:
sudo supervisorctl reread
sudo supervisorctl update
It's simple but not obvious though. My mistake was that I expected the config to update automatically after I restart my app on gunicorn using this command:
sudo supervisorctl restart my_app
Yes it restart the app, but not the config of gunicorn.
Intend
I want to be able to tell which server is running my Flask app.(Either Werkzeug or Gunicorn) And additionally if it is being proxied by NGINX or Apache.
Problem
I think I can get the response with JavaScript and get the server header, but In the case of it being proxy by NGINX or Apache, I won't be able to tell whatever is gunicorn or werkzeug that I is running under hood.
Is there a way to tell the server within the flask app?
Some servers will add SERVER_SOFTWARE into the os environment. Gunicorn will do this.
#app.route('/server')
def server():
return os.environ.get('SERVER_SOFTWARE')
Result:
I downloaded the SSL vulnerability tester SSlyze and ran it against my gunicorn port. One of the results was:
* Session Renegotiation:
Client-initiated Renegotiations: VULNERABLE - Server honors client-initiated renegotiations
Is there a Gunicorn setting I can use to prevent it from honoring client initiated renegotiations?
Don't use Gunicorn as a web server. Proxy it with Nginx. Nginx is good at being a web server, Gunicorn is good at being a WSGI server. Nginx disabled renegotiation in 2009.
A recent flask application I wrote needed to be on an apache2 server. I successfully completed connecting apache and flask but I still wonder why using apache and wsgi is better than just saying "python main.py" and just running the server on port 8080 with port 80 forwarding to 8080?
If you run your sever directly with python on a port, using Flask, then the server will be single threaded with your requests. Your performance will suffer.
How many concurrent requests does a single Flask process receive?