Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practice for setting up Flask+uWSGI+nginx [closed]

I'm trying to set up my first web server using the combination of Flask, uWSGI, and nginx. I've had some success getting the Flask & uWSGI components running. I've also gotten many tips from various blogs on how to set this up. However, there is no consistency and the articles suggest many different ways of setting this up especially where folder structures, nginx configurations and users/permissions are concerned (I've tried some of these suggestions and many do work, but I am not sure which is best). So is there one basic "best practice" way of setting up this stack?

like image 320
RedRaven Avatar asked Mar 16 '14 04:03

RedRaven


2 Answers

nginx + uwsgi + flask make for a potent stack! I add supervisor to the mix and configure it as follows.

  1. Run both uwsgi and nginx out of supervisor for better process control. You can then start supervisor at boot and it will run uwsgi and nginx in the right order. It will also intelligently try to keep them alive if they die. See a sample supervisor configuration below.
  2. If you are running nginx and uwsgi on the same host, use unix sockets rather than HTTP.
  3. The nginx master process must run as root if your web server is listening on port 80. I usually run my web server on some other port (like 8080) and use a load balancer in front to listen on port 80 and proxy to nginx.
  4. Make sure your uwsgi server has access to read/write to the socket file you choose as well as proper permissions to any app code and data directories.

Don't worry too much about your folder structure, especially if you're using a Linux distro like Ubuntu that has sensible defaults. The main supervisor config file can include files from a subdirectory like /etc/supervisor/conf.d/ to separate your app-specific configuration from the supervisor core config. Same goes for nginx, only /etc/nginx/sites-enabled.

Sample supervisor config for uwsgi and nginx:

$ cat /etc/supervisor/conf.d/app.conf
[program:app]
command=/usr/local/bin/uwsgi
  --enable-threads
  --single-interpreter
  --vacuum
  --chdir /path/to/app
  --uid www-data
  --log-syslog
  --processes 4
  --socket /tmp/app.sock
  -w mypython:app
  --master
directory=/path/to/app
autostart=true
autorestart=true
priority=999
stopsignal=INT
environment=SOMEVAR=somevalue

[program:nginx]
command=/usr/sbin/nginx

autostart=true
autorestart=true

priority=999

Sample nginx.conf:

$ cat /etc/nginx/sites-enabled/myapp.conf
server {
  listen 8080;
  client_max_body_size 4G;
  server_name localhost;
  keepalive_timeout 5;
  location / {
      include uwsgi_params;
      uwsgi_pass unix:///tmp/app.sock;
  }
}
like image 180
Ben Whaley Avatar answered Oct 21 '22 23:10

Ben Whaley


There are two parts to this, one is setting up the system itself (by this I mean, the operating system and its various path/filesystems) and the second part is installing and configuring the components.

I will concentrate on the second part, which I believe is the crux of your question:

  1. nginx should be installed by your operating system's native package management utilities. This will make sure that all permissions are set correctly, and the configuration files are where you (or anyone else) would expect them. For example this means on debian-like systems (such as ubuntu and its various cousins), the configurations are in /etc/nginx/, sites are configured by adding files in /etc/nginx/sites-available/ and so on. It also means that if and when updates are pushed by your OS vendor, they will automatically be installed by your packaging software.

  2. uWSGI you should install by source; because it has a very fast development cycle and improvements in uwsgi are going to have a positive affect on your application. The installation process is simple, and there are no special permissions required; other than the normal root/superuser permissions you would need to install applications system-wide.

  3. Your application's source files. For this, I would strongly advise creating separate user roles for each application and isolate all permissions and all related files (for example, log files generated by uwsgi) so that they are all owned by the same user. This makes sure that other applications/users cannot read error messages/log files, and that one user has all the permissions to read/debug everything related to that application without using tools such as sudo.

Other than the three points mentioned above, actually getting all these components to work together is a standard process:

  1. Create your wsgi process/handler in your application. For flask, the default flask application already provides this interface.

  2. Run this file using your wsgi engine. This is uwsgi or gunicorn or similar. Make sure you are using the binary protocol.

  3. Map your static files to a location that is serviced by your web proxy (this is nginx); and create a upstream server that points to the location that the wsgi process is expecting connections. This could be a port or a pipe (depending on how you have setup the components).

  4. Optional use a process manager like supervisor to control the wsgi processes so that they are restarted upon system reboot and are easier to manage.

Everything else is subject to personal preferences (especially when it comes to file system layouts). For large applications, the creators of flask provide blueprints but again note that they do not extol any file system/directory layout.

As a general rule for any Python package, I would refer you to this link.

like image 30
Burhan Khalid Avatar answered Oct 22 '22 01:10

Burhan Khalid