Serving multiple Django applications with Nginx and Gunicorn
OCT 29TH, 2013
Nginx makes a great server for your Gunicorn-powered Django applications. In this article I will demonstrate how you can run multiple Django applications on the same Nginx server, hosting sites on two different domains. Each application will be set up in its own Virtualenv and each will be owned by and run as a different user to limit consequences of a potential security breach.
Prerequisites
This artcle is a continuation of a previous article on setting up Django with Nginx and Gunicorn. You should start by following instructions in that article and prepare a server with the following components:
Nginx
PostgreSQL
Virtualenv
Supervisor
Our goal in this article will be to create two applications, one called Hello and one called Goodbye. The former will be served under the address http://hello.test and the latter http://goodbye.test
Create a virtual environment for each app
In order to keep your apps independent, each will run in its own virtual environment. Create an environment for each application using the virtualenv command. In each environment install Django, Gunicorn, the application itself and its other dependencies. Follow steps described in my previous article for each app.
Let’s say that for our hello and goodbye applications we would create environments in /webapps/hello_django and /webapps/goodbye_django respectively. We would get a directory structure containing the following entries:
/webapps/
├── hello_django <= virtualenv for the application Hello
│ ├── bin
│ │ ├── activate
│ │ ├── gunicorn <= Hello app's gunicorn
│ │ ├── gunicorn_start <= Hello app's gunicorn start script
│ │ └── python
│ ├── hello <= Hello app's Django project directory
│ │ └── hello
│ │ ├── settings.py <= hello.settings
│ │ └── wsgi.py <= hello.wsgi
│ ├── logs <= Hello app's logs will be saved here
│ ├── media
│ ├── run <= Gunicorn's socket file will be placed here
│ └── static
└── goodbye_django <= analogous virtualenv for the application Goodbye
├── bin
│ ├── activate
│ ├── gunicorn
│ ├── gunicorn_start
│ └── python
├── goodbye
│ └── goodbye
│ ├── settings.py
│ └── wsgi.py
├── logs
├── media
├── run
└── static
Create system accounts for the webapps
Even though Django has a pretty good security track record, web applications can become compromised. In order to make running multiple applications safer we’ll create a separate system user account for each application. The apps will run on our system with the privileges of those special users. Even if one application became compromised, an attacker would only be able to take over the part of your system available to the hacked application.
Create system users named hello and goodbye and assign them to a system group called webapps.
Now change the owner of files in each application’s folder. I like to assign the group users as the owner, because that allows regular users of the server to access and modify parts of the application which are group-writable. This is optional.
For each application create a simple shell script based on my gunicorn_start template. The scripts differ only in the values of variables which they set.
For the Hello app, set the following values in /webapps/hello_django/bin/gunicorn_start:
/webapps/hello_django/bin/gunicorn_start
NAME="hello_app" # Name of the application
DJANGODIR=/webapps/hello_django/hello # Django project directory
SOCKFILE=/webapps/hello_django/run/gunicorn.sock # we will communicte using this unix socket
USER=hello # the user to run as
GROUP=webapps # the group to run as
NUM_WORKERS=3 # how many worker processes should Gunicorn spawn
DJANGO_SETTINGS_MODULE=hello.settings # which settings file should Django use
DJANGO_WSGI_MODULE=hello.wsgi # WSGI module name
(...)
And for the Goodbye app by analogy:
/webapps/goodbye_django/bin/gunicorn_start
NAME="goodbye_app" # Name of the application
DJANGODIR=/webapps/goodbye_django/goodbye # Django project directory
SOCKFILE=/webapps/goodbye_django/run/gunicorn.sock # we will communicte using this unix socket
USER=goodbye # the user to run as
GROUP=webapps # the group to run as
NUM_WORKERS=3 # how many worker processes should Gunicorn spawn
DJANGO_SETTINGS_MODULE=goodbye.settings # which settings file should Django use
DJANGO_WSGI_MODULE=goodbye.wsgi # WSGI module name
Create Supervisor configuration files and start the apps
Next, create a Supervisor configuration for each application. Add a file for each app to the /etc/supervisor/conf.d directory.
One for Hello:
/etc/supervisor/conf.d/hello.conf
[program:hello]
command = /webapps/hello_django/bin/gunicorn_start ; Command to start app
user = hello ; User to run as
stdout_logfile = /webapps/hello_django/logs/gunicorn_supervisor.log ; Where to write log messages
redirect_stderr = true ; Save stderr in the same log
And one for Goodbye:
/etc/supervisor/conf.d/goodbye.conf
[program:goodbye]
command = /webapps/goodbye_django/bin/gunicorn_start ; Command to start app
user = goodbye ; User to run as
stdout_logfile = /webapps/goodbye_django/logs/gunicorn_supervisor.log ; Where to write log messages
redirect_stderr = true ; Save stderr in the same log
Reread the configuration files and update Supervisor to start the apps:
Finally we can create virtual server configurations for each app based on this template. These will be stored in /etc/nginx/sites-available and then activated by links in /etc/nginx/sites-enabled.
Now let’s point each domain to our server for testing purposes. Making actual changes to the Domain Name System is usually among the final steps when working in production, performed after all tests are completed. For testing you can simulate the DNS changes by adding an entry to the /etc/hosts file of a computer from which you will be connecting to your server (your laptop for example).
Say you want to serve Django applications under the domains hello.test and goodbye.test from a server with the IP address of 10.10.10.200. You can simulate the appropriate DNS entries locally on your PC by putting the following line into your /etc/hosts file. On Windows the file is conveniently hidden in %SystemRoot%\system32\drivers\etc\hosts.
/etc/hosts
10.10.10.200 hello.test goodbye.test
You can now navigate to each domain from your PC to test that each app on the server is working correctly:
原始链接:http://michal.karzynski.pl/blog/2013/10/29/serving-multiple-django-applications-with-nginx-gunicorn-supervisor/
Serving multiple Django applications with Nginx and Gunicorn
OCT 29TH, 2013
Nginx makes a great server for your Gunicorn-powered Django applications. In this article I will demonstrate how you can run multiple Django applications on the same Nginx server, hosting sites on two different domains. Each application will be set up in its own Virtualenv and each will be owned by and run as a different user to limit consequences of a potential security breach.Prerequisites
This artcle is a continuation of a previous article on setting up Django with Nginx and Gunicorn. You should start by following instructions in that article and prepare a server with the following components:
Our goal in this article will be to create two applications, one called Hello and one called Goodbye. The former will be served under the address http://hello.test and the latter http://goodbye.test
Create a virtual environment for each app
In order to keep your apps independent, each will run in its own virtual environment. Create an environment for each application using the virtualenv command. In each environment install Django, Gunicorn, the application itself and its other dependencies. Follow steps described in my previous article for each app.
Let’s say that for our hello and goodbye applications we would create environments in /webapps/hello_django and /webapps/goodbye_django respectively. We would get a directory structure containing the following entries:
Create system accounts for the webapps
Even though Django has a pretty good security track record, web applications can become compromised. In order to make running multiple applications safer we’ll create a separate system user account for each application. The apps will run on our system with the privileges of those special users. Even if one application became compromised, an attacker would only be able to take over the part of your system available to the hacked application.
Create system users named hello and goodbye and assign them to a system group called webapps.
Now change the owner of files in each application’s folder. I like to assign the group users as the owner, because that allows regular users of the server to access and modify parts of the application which are group-writable. This is optional.
Create Gunicorn start scripts
For each application create a simple shell script based on my gunicorn_start template. The scripts differ only in the values of variables which they set.
For the Hello app, set the following values in /webapps/hello_django/bin/gunicorn_start:
And for the Goodbye app by analogy:
Create Supervisor configuration files and start the apps
Next, create a Supervisor configuration for each application. Add a file for each app to the /etc/supervisor/conf.d directory.
One for Hello:
And one for Goodbye:
Reread the configuration files and update Supervisor to start the apps:
You can also start them manually, if you prefer:
Create Nginx virtual servers
Finally we can create virtual server configurations for each app based on this template. These will be stored in /etc/nginx/sites-available and then activated by links in /etc/nginx/sites-enabled.
Enable the virtual servers and restart Nginx:
Test the virtual servers
Now let’s point each domain to our server for testing purposes. Making actual changes to the Domain Name System is usually among the final steps when working in production, performed after all tests are completed. For testing you can simulate the DNS changes by adding an entry to the /etc/hosts file of a computer from which you will be connecting to your server (your laptop for example).
Say you want to serve Django applications under the domains hello.test and goodbye.test from a server with the IP address of 10.10.10.200. You can simulate the appropriate DNS entries locally on your PC by putting the following line into your /etc/hosts file. On Windows the file is conveniently hidden in %SystemRoot%\system32\drivers\etc\hosts.
You can now navigate to each domain from your PC to test that each app on the server is working correctly:
Good luck!
Posted by Michał Karzyński Oct 29th, 2013 tech