This post explains setting up a Django app deployed by Gunicorn behind Nginx server in a Ubuntu 16.04 virtual machine set up via Vagrant.
These are broader steps that you would need to take:
- Setting up an Ubuntu 16.04 VM using Vagrant.
- Setting up python and virtual environment.
- Setting up Gunicorn systemd file.
- Setting up Nginx to proxy pass Gunicorn.
1. Creating an Ubuntu 16.04 VM using Vagrant
Installing Vagrant is pretty simple step.
But first you would need to install Virtual Box or any other VM provider. Virtual Box is popular choice and even easier option amongst the providers to install.
Just go to the Virtual Box's downloads page and select respective host depending on your system's operating system.
If you select OSX host, a .dmg package is downloaded, open it and follow steps. While installing in OSX if you get an error something like Your Instalation Failed, follow this blog to troubleshoot.
Once Virtual Box is installed you can move on to installing Vagrant.
Go to Vagrant's download page and download installation image as per your OS.
Check if vagrant is installed. Open terminal and type vargant
. The output should be something like this:
$ vagrant
Usage: vagrant [options] <command> [<args>]
-v, --version Print the version and exit.
-h, --help Print this help.
#...
Once installation is complete, open terminal shell and go to directory where you want to setup your virtual machine. For example, create directory called virtualmachines/,here you would have all the virtual machines you want to setup. So, for Ubuntu 16.04, create a directory ubuntu16_04/. Go inside the directory
mkdir ./virtualmachines && cd virtualmachines
mkdir ubuntu16_04 && cd ubuntu16_04
Now is the time create a VM box. You can create a VM from scratch using command:
$ vagrant init hashicorp/xenial64
or setup a base image of OS called a box by executing command:
$ vagrant box add hashicorp/xenial64
If you want to install any other flavour of Ubuntu replace xenial with the flavour's first name. 64 in xenial64 means the guest OS would be a 64-bit OS. You can find the list of available OS here.
If you execute ls
command, you would find a file called VagrantFile present in the directory. This is the source file that is used to configure the VM. Every time that you want to start the VM, the configurations would be set as per this file.
Make sure to un-comment line declaring forwarded_port
for guest and host OS.
The guest
is your virtual machine and the host
is your local machine.
Also, if it is commented, un-comment this block:
config.vm.provider "virtualbox" do |vb|
vb.gui = false
vb.memory = 2048
vb.cpus = 2
and specify vb.gui
, vb.memory
and vb.cpus
.
You can find sample VagrantFile in this gist.
Now to start the VM run :
$ vagrant up
This would boot your environment, and in less than a minute you would have Ubuntu running in a virtual machine. There would be no output visible, as Vagrant runs the VM without UI. To access Ubuntu you would require ssh. Run:
$ vagrant ssh
This would start a full-fledged SSH session.
2. Setting up python and virtual environment for Django app
Now that you are inside Ubuntu, it is time to install all necessary packages/modules.
Install python and pip using command
$ sudo apt install python python-pip
This would install python2.7. For python3 use:
$ sudo apt install pyhton3 python-pip3
Now install virtualenv:
$ pip install virtualenv
Create a directory called webapps/, this is going to contain all the Django projects created henceforth. You can directly clone your git repository here or start a project (remember to create a directory inside which you should start your project).
Such that your webapps/ directory tree looks like this :
* webapps/
|
---- * your_project_parent_directory
|
---- * your_project
|
---- * your_app
---- * your_project
|
---- * your_project.wsgi
Your project should have virtualenv set up and activated. Make sure you have a .wsgi file in it. Change directory and get inside your project.
3. Setting up Gunicorn systemd file
Now its time to install Gunicorn:
$ pip install gunicorn
Once gunicorn is installed, run command:
$ gunicorn <your_project_name>.wsgi:application --bind 0.0.0.0:8000
If the server starts, your gunicorn setup is working. Though there is a robust way of gunicorn interacting with django project.
Create and open a systemd service file for Gunicorn with sudo privileges in your text editor:
$ sudo nano /etc/systemd/system/gunicorn.service
Your gunicorn.service file should look something like this:
[Unit]
Description=gunicorn service
After=network.target
[Service]
WorkingDirectory=/home/vagrant/webapps/your_project_parent_dir/project_name
ExecStart=/home/vagrant/webapps/your_project_parent_dir/env/bin/gunicorn --access-logfile - --bind \
unix:/home/vagrant/webapps/your_project_parent_dir/your_project/your_project.sock \
your_project.wsgi:application
[Install]
WantedBy=multi-user.target
The [Unit]
and [Install]
remain as they are. In the WorkingDirectory
, you need to provide absolute path to your project. In ExecStart
, you specify command to run gunicorn, but instead using gunicorn
command directly, you need to specify which gunicorn
, hence, you provide the path to gunicorn, if it is installed globally, you would need to specify the absolute path to global command file, like /usr/local/bin/gunicorn
followed by parameters --access-logfile
and --bind
, after unix:
specify absolute path to your_project.sock
Now we would have to start this service.
Run command:
$ sudo systemctl start gunicorn
Check status of the service:
$ sudo systemctl status gunicorn
You can confirm that the operation was successful by checking for the socket file.
$ ls your_project_parent_dir/your_project/
You should find a file called your_project.sock here.
If not, check for the service configurations or status of it.
To check for errors look up in the journal:
$ sudo journalctl -u gunicorn
Other reasons could be :
- The owner is root and not sudo.
- The
WorkingDirectory
path does not point to the project directory. - The path given for configuration for gunicorn service in
ExceStart
directive is incorrect. Check these:- The path to the gunicorn binary points to the actual location of the binary within the virtual environment.
- The
--bind
directive defines a file to create within a directory that Gunicorn can access. - The your_project.wsgi should be immediate child to your_project directory.
Remember a reload of daemon service would be required if the file is edited :
$ sudo systemctl daemon-reload
$ sudo systemctl restart gunicorn
4. Setting up nginx
Install Nginx in your guest, type this command in terminal:
sudo apt-get install nginx
Check if nginx is successfully installed:
$ nginx
You should not see command not found
error.
Now we need to create and start a new server block in /etc/nginx/sites-available
.
$ sudo nano /etc/nginx/sites-available/you_project
Here specify something like this:
server {
listen 8000;
server_name 0.0.0.0;
location = /favicon.ico { access_log off; log_not_found off; }
location / {
include proxy_params;
proxy_pass http://unix:/home/vagrant/webapps/project-name/project-name.sock;
}
}
The argument to listen
is the port of guest that would be exposed, you should mention this port in forwarded_port
and map it to some host port in VagrantFile.
The server_name
is the IP location or DNS location of your server, here it is localhost so we provide server_name
as 0.0.0.0.
In proxy_pass
after unix:
specify absolute path to your_project.sock file.
If you have static files you would need to add these extra lines
location /static/ {
root /home/vagrant/webapps/your_project_parent_dir/your_project;
}
inside server
object.
Save and close the file when you are finished. Now, you can enable the file by linking it to the sites-enabled directory:
$ sudo ln -s /etc/nginx/sites-available/your_project /etc/nginx/sites-enabled/
Test your nginx for syntax errors:
$ sudo nginx -t
If the test is ok, you would require to restart the nginx now and check its status.
$ sudo systemctl restart nginx
$ sudo systemctl status nginx
You are all set. Hit 0.0.0.0:host_port on browser to view your Django projects app page.
Top comments (0)