Tutorial

How To Deploy a Local Django App to a VPS

Published on September 20, 2013
author

Stephen Tippets

How To Deploy a Local Django App to a VPS

Prerequisites


This tutorial assumes that you have already set up your virtual private server with your operating system of choice (Debian 7 was used for this tutorial; Ubuntu will also work). If you have not already done so, you can follow this tutorial. Before you begin, make sure your cloud server is properly configured to host Django applications with a database server, web server, and virtualenv already installed. If you have not already done this, please follow steps 1 - 6 about setting up a server for Django.

Step One: Update Packages


Before doing anything, it is always good practice to ensure all of your packages managed through apt, or whatever your package manager of choice is, are up to date. You can do this by connecting to your VPS via SSH and running the following commands:

sudo apt-get update
sudo apt-get upgrade

The first command downloads any updates for packages managed through apt-get. The second command installs the updates that were downloaded. After running the above commands, if there are updates to install you will likely be prompted to indicate whether or not you want to install these updates. If this happens, just type “y” and then hit “enter” when prompted.

Step Two: Set Up Your Virtualenv


If you completed the prerequisites, this should already be set up and you can skip this step.

Now we need to set up our virtualenv where our project files and Python packages will live. If you don’t use virtualenv, then simply create the directory where your Django project will live and move to step three.

To create your virtualenv run the following command. Remember to replace the path with the desired path of your project project on the virtual private server:

virtualenv /opt/myproject

Now that you have your virtualenv set up, you may activate your virtualenv and install Django and any other Python packages you may need using pip. Below is an example of how to activate your virtualenv and use pip to install Django:

source /opt/myproject/bin/activate
pip install django

Now we’re ready to create a database for our project!

Step Three: Create a Database


This tutorial assumes you use PostgreSQL as your database server. If not, you will need to check out documentation on how to create a database for your database server of choice.

To create a database with PostgreSQL start by running the following command:

sudo su - postgres

Your terminal prompt should now say “postgres@yourserver”. If so, run this command to create your database, making sure to replace “mydb” with your desired database name:

createdb mydb

Now create your database user with the following command:

createuser -P

You will now be met with a series of six prompts. The first will ask you for the name of the new user (use whatever name you would like). The next two prompts are for your password and confirmation of password for the new user. For the last three prompts, simply enter “n” and hit “enter.” This ensures your new user only has access to what you give it access to and nothing else. Now activate the PostgreSQL command line interface like so:

psql

Finally, grant this new user access to your new database with the following command:

GRANT ALL PRIVILEGES ON DATABASE mydb TO myuser;

You are now set with a database and a user to access that database. Next, we can work on configuring our web server to serve up our static files!

Step Four: Configure Your VPS

We need to create a new configuration file for our site. This tutorial assumes you are using NGINX as your cloud server. If this is not the case, you will need to check the documentation for your web server of choice in order to complete this step.

For NGINX, run the following command to create and edit your site’s web server configuration file, making sure to replace “myproject” at the end of the command with the name of your project:

sudo nano /etc/nginx/sites-available/myproject

Now enter the following lines of code into the open editor:

server {
    server_name yourdomainorip.com;

    access_log off;

    location /static/ {
        alias /opt/myenv/static/;
    }

    location / {
        proxy_pass http://127.0.0.1:8001;
        proxy_set_header X-Forwarded-Host $server_name;
        proxy_set_header X-Real-IP $remote_addr;
        add_header P3P 'CP="ALL DSP COR PSAa PSDa OUR NOR ONL UNI COM NAV"';
    }
}

Save and exit the file. The above configuration has set NGINX to serve anything requested at yourdomainorip.com/static/ from the static directory we set for our Django project. Anything requested at yourdomainorip.com will proxy to localhost on port 8001, which is where we will tell Gunicorn (or your app server of choice) to run. The other lines ensure that the hostname and IP address of the request get passed on to Gunicorn. Without this, the IP address of every request becomes 127.0.0.1 and the hostname is just your VPS hostname.

Now we need to set up a symbolic link in the /etc/nginx/sites-enabled directory that points to this configuration file. That is how NGINX knows this site is active. Change directories to /etc/nginx/sites-enabled like this:

cd /etc/nginx/sites-enabled

Once there, run this command:

sudo ln -s ../sites-available/myproject

Now restart NGINX with the command below and you should be set:

sudo service nginx restart

You may see the following error upon restart:

server_names_hash, you should increase server_names_hash_bucket_size: 32

You can resolve this by editing ’ /etc/nginx/nginx.conf ’

Open the file and uncomment the following line:

server_names_hash_bucket_size 64;

Now let’s get our project files pushed up to our droplet!

Step Five: Move Local Django Project to Droplet


We have several options here: FTP, SFTP, SCP, Git, SVN, etc. We will go over using Git to transfer your local project files to your virtual private server.

Find the directory where you set up your virtualenv or where you want your project to live. Change into this directory with the following command:

cd /opt/myproject

Once there, create a new directory where your project files will live. You can do this with the following command:

mkdir myproject

It may seem redundant to have two directories with the same name; however, it makes it so that your virtualenv name and project name are the same.

Now change into the new directory with the following command:

cd myproject

If your project is already in a Git repo, simply make sure your code is all committed and pushed. You can check if this is the case by running the following command locally on your computer in a terminal (for Mac) or a command prompt (for PC):

git status

If you see no files in the output then you should be good to go. Now SSH to your droplet and install Git with the following command:

sudo apt-get install git

Make sure to answer yes to any prompts by entering “y” and hitting “enter.” Once Git is installed, use it to pull your project files into your project directory with the following command:

git clone https://webaddressforyourrepo.com/path/to/repo .

If you use Github or Bitbucket for Git hosting there is a clone button you can use to get this command. Be sure to add the “.” at the end. If we don’t do this, then Git will create a directory with the repo name inside your project directory, which you don’t want.

If you don’t use Git then use FTP or another transfer protocol to transfer your files to the project directory created in the steps above.

Now all that’s left is setting up your app server!

Step Six: Install and Configure App Server


If you completed the prerequisites, this should already be set up and you can skip this step.

Now we need to install our app server and make sure it listens on port 8001 for requests to our Django app. We will use Gunicorn in this example. To install Gunicorn, first activate your virtualenv:

source /opt/myproject/bin/activate

Once your virtualenv is active, run the following command to install Gunicorn:

pip install gunicorn

Now that Gunicorn is installed, bind requests for your domain or ip to port 8001:

gunicorn_django --bind yourdomainorip.com:8001

Now you can hit “ctrl + z” and then type “bg” to background the process (if you would like). More advanced configuration and setup of Gunicorn can be found in step nine of this tutorial.

Now you’re ready for the final step!

Step Seven: Configure Your App


The final step is to configure your app for production. All of the changes we need to make are in your “settings.py” file for your Django project. Open this file with the following command:

sudo nano /opt/myproject/myproject/settings.py

The path to your settings file may differ depending on how your project is set up. Modify the path in the command above accordingly.

With your settings file open, change the DEBUG settings to False:

DEBUG = False

This will make it so that errors will show up to users as 404 or 500 error pages, rather than giving them a stack trace with debug information.

Now edit your database settings to look like the following, using your database name, user, and password instead of the ones shown below:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.psycopg2', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': 'mydb',                      # Or path to database file if using sqlite3.
        # The following settings are not used with sqlite3:
        'USER': 'myuser',
        'PASSWORD': 'password',
        'HOST': '',                      # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
        'PORT': '',                      # Set to empty string for default.
    }
}

Now edit your static files settings:

STATIC_ROOT = '/opt/myproject/static/'

STATIC_URL = '/static/'

Save and exit the file. Now all we need to do is collect our static files. Change into the directory where your “manage.py” script is and run the following command:

python manage.py collectstatic

This command will collect all the static files into the directory we set in our settings.py file above.

And that’s it! You’ve now got your app deployed to production and ready to go.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the author(s)

Category:
Tutorial

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
36 Comments
Leave a comment...

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Thank you so much. Greda tutorial :)

A couple of typos here:

With your settings file open, change the DEBUG settings to **False:

DEBUT = False

The False should end with double asterisks as well, making it bold (if this is Markdown) and the DEBUT should be DEBUG.

Don’t forget to set your ALLOWED_HOSTS in django. Great tuto, cheers =)

to?

Kamal Nasser
DigitalOcean Employee
DigitalOcean Employee badge
October 24, 2013

@Markus: Thanks, we’ve corrected the article. :]

Statics not work :( 403 Forbidden help me please

Hello,

You will have to change permissions of your project directory with the chown command. I’d recommend the following permission set to you project folder chown 777 ./projectdirecotory.

Basit

Kamal Nasser
DigitalOcean Employee
DigitalOcean Employee badge
October 29, 2013

@rajiv.rivero: What’s the output of <pre>sudo tail /var/log/nginx/error.log</pre>?

I sugest to update gunicorn usage for Django1.4+ gunicorn myproject:application

You should think about referencing this article about setting up ssh with git.

https://confluence.atlassian.com/display/BITBUCKET/Set+up+SSH+for+Git

When trying to bind unicorn using the following line:

gunicorn_django --bind yourdomainorip.com:8001 (of course changing to my IP)

I’m getting an error saying:

!!! WARNING: This command is deprecated. !!! !!! You should now run your application with the WSGI interface !!! installed with your project. Ex.: !!! !!! gunicorn myproject.wsgi:application !!! !!! See https://docs.djangoproject.com/en/1.4/howto/deployment/wsgi/gunicorn/ !!! for more info.

2014-04-08 15:39:05 [24343] [INFO] Worker exiting (pid: 24343) 2014-04-08 15:39:05 [24338] [INFO] Shutting down: Master 2014-04-08 15:39:05 [24338] [INFO] Reason: Worker failed to boot.

Is there something wrong?

Andrew SB
DigitalOcean Employee
DigitalOcean Employee badge
April 8, 2014

@ekonstantinidis

With more recent versions of gunicorn (greater than version 18.0), you should run your application with the wsgi.py file that should be apart of your project. The equivalent version on the command run in this article would be:

gunicorn --bind yourdomainorip:8001 myproject.wsgi:application

For further reading, see:

http://docs.gunicorn.org/en/18.0/news.html#id1 https://docs.djangoproject.com/en/1.4/howto/deployment/wsgi/gunicorn/

Let me know if you don’t figure it out!

@astarr Yes you’re right!! I did that and it worked! The issue I do have now(trying to figure it out for hours) is that when i’m typing:

‘python manage.py collectstatic’

I’m getting lots of errors which conclude to

’ File “/opt/upenv/local/lib/python2.7/site-packages/django/db/backends/mysql/base.py”, line 17, in <module> raise ImproperlyConfigured(“Error loading MySQLdb module: %s” % e) django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module: No module named MySQLdb ’

I checked with stack overflow and everyone with this error was told to check if ‘python-mysqldb’ was installed so I installed it using

‘sudo apt-get install python-mysqldb’.

But still getting this error. Any ideas?

Andrew SB
DigitalOcean Employee
DigitalOcean Employee badge
April 9, 2014

@ekonstantinidis

When you created the virtualenv you probably used the ‘–no-site-packages’ option as it is the default. This means system-wide python modules are not included in the virtual environment. So you should install python-mysqldb with pip:

pip install mysql-python

You’ll probably need to install these development libraries first so that it complies correctly:

sudo apt-get install libmysqlclient-dev sudo apt-get install python-dev

@astarr Once again you’re right! I managed to get mysql working. The only issue left is that static files won’t show up.

If I access them directly (http://188.xxx.xxx.93/static/css/bootstrap.css) they show up. But when running my application using gunicorn, I can see in the source code that it tried to find them using the port (http://188.xxx.xxx.93:8001)/static/css/bootstrap.css) so they won’t show up.

I guess it has to do with settings.py?

I followed these steps with an ubuntu server and when creating the user with “createuser -P” I get the following error:

createuser: creation of new role failed: ERROR:  role "postgres" already exists

Maybe since the tutorial the postgres default installation changed adding a new default user?

–brunoamaral

createuser --interactive -P

Andrew SB
DigitalOcean Employee
DigitalOcean Employee badge
June 30, 2014

@mail: Right. If you created a default postgres user while installing the package, you can skip that step.

droplet: ubuntu 14.4, django 1.7, python 2.7 nginx 1.4.6

step one-five: completed, fine.

I am getting error at step six…

I am inside virtualenv of my django project(cloned)

both commands failed:

1st. gunicorn_django --bind mydomain:8001

it gives the error.

  File "/usr/lib/python2.7/dist-packages/gunicorn/app/djangoapp.py", line 101, in load
    mod = util.import_module("gunicorn.app.django_wsgi")
  File "/usr/lib/python2.7/importlib/__init__.py", line 37, in import_module
    __import__(name)
  File "/usr/lib/python2.7/dist-packages/gunicorn/app/django_wsgi.py", line 20, in <module>
    from django.core.management.validation import get_validation_errors
ImportError: No module named validation
2014-11-13 14:24:46 [6752] [INFO] Worker exiting (pid: 6752)
2014-11-13 14:24:46 [6747] [INFO] Shutting down: Master
2014-11-13 14:24:46 [6747] [INFO] Reason: Worker failed to boot.

2nd: gunicorn --bind yourdomainorip:8001 project.wsgi

i’ve omitted “application” from above command it also struck (gunicorn --bind yourdomainorip:8001 project.wsgi:application)

directory structure:

/home/user/project/...
  /home/user/project/project->wsgi.py
  /home/user/project/app1
  /home/user/project/app2
  /home/user/project/app3
  /home/user/project/manage.py
  /home/user/project/virtualenv

(i am issuing both commands from my manage.py directory)

incase of command 2:

i am struck at…

2014-11-13 14:40:52 [6925] [INFO] Listening at: http://127.0.1.1:8001 (6925)
2014-11-13 14:40:52 [6925] [INFO] Using worker: sync
2014-11-13 14:40:52 [6930] [INFO] Booting worker with pid: 6930

Hi,

Great tutorial. Is this considered a secure application, or are there other measures that need to be taken for security. I ask because I read a similar tutorial for deploying django to AWS and the writer of the tutorial said “extra security measures must be taken” - but didnt qualify of explain the statement!

Thanks,

Andreas

Andrew SB
DigitalOcean Employee
DigitalOcean Employee badge
December 17, 2014

There’s nothing inherently insecure in this. Though, this doesn’t deal with anything on the application level. You might want to take a look at this overview from the official Django docs:

Of course, there are many best practices for administering your server securely that are outside of the scope of this tutorial like: locking down Postgres, setting up a firewll, and disabling password-based log-ins.

Is it OK in Django 1.7?

A couple of issues in step 3. Firstly like @brunoamaral, createuser -P doesn’t ask me for a username, just a password. Secondly, at the end of step 3 I can’t connect to the database :( Thirdly, at the end of step 3 I’m still the postgres Unix user, which isn’t ideal for continuing with the rest of the tutorial.

I’m confused by these instructions. How does gunicorn actually know where to find the Django app? I can’t see anywhere where we’re actually pointing gunicorn at the Django app.

@astarr Yes you’re right!! I did that and it worked! The issue I do have now(trying to figure it out for hours) is that when i’m typing:

‘python manage.py collectstatic’

I’m getting lots of errors which conclude to

’ File “/opt/upenv/local/lib/python2.7/site-packages/django/db/backends/mysql/base.py”, line 17, in <module> raise ImproperlyConfigured(“Error loading MySQLdb module: %s” % e) django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module: No module named MySQLdb ’

I checked with stack overflow and everyone with this error was told to check if ‘python-mysqldb’ was installed so I installed it using

‘sudo apt-get install python-mysqldb’.

But still getting this error. Any ideas?

Andrew SB
DigitalOcean Employee
DigitalOcean Employee badge
April 9, 2014

@ekonstantinidis

When you created the virtualenv you probably used the ‘–no-site-packages’ option as it is the default. This means system-wide python modules are not included in the virtual environment. So you should install python-mysqldb with pip:

pip install mysql-python

You’ll probably need to install these development libraries first so that it complies correctly:

sudo apt-get install libmysqlclient-dev sudo apt-get install python-dev

@astarr Once again you’re right! I managed to get mysql working. The only issue left is that static files won’t show up.

If I access them directly (http://188.xxx.xxx.93/static/css/bootstrap.css) they show up. But when running my application using gunicorn, I can see in the source code that it tried to find them using the port (http://188.xxx.xxx.93:8001)/static/css/bootstrap.css) so they won’t show up.

I guess it has to do with settings.py?

I followed these steps with an ubuntu server and when creating the user with “createuser -P” I get the following error:

createuser: creation of new role failed: ERROR:  role "postgres" already exists

Maybe since the tutorial the postgres default installation changed adding a new default user?

–brunoamaral

createuser --interactive -P

Andrew SB
DigitalOcean Employee
DigitalOcean Employee badge
June 30, 2014

@mail: Right. If you created a default postgres user while installing the package, you can skip that step.

droplet: ubuntu 14.4, django 1.7, python 2.7 nginx 1.4.6

step one-five: completed, fine.

I am getting error at step six…

I am inside virtualenv of my django project(cloned)

both commands failed:

1st. gunicorn_django --bind mydomain:8001

it gives the error.

  File "/usr/lib/python2.7/dist-packages/gunicorn/app/djangoapp.py", line 101, in load
    mod = util.import_module("gunicorn.app.django_wsgi")
  File "/usr/lib/python2.7/importlib/__init__.py", line 37, in import_module
    __import__(name)
  File "/usr/lib/python2.7/dist-packages/gunicorn/app/django_wsgi.py", line 20, in <module>
    from django.core.management.validation import get_validation_errors
ImportError: No module named validation
2014-11-13 14:24:46 [6752] [INFO] Worker exiting (pid: 6752)
2014-11-13 14:24:46 [6747] [INFO] Shutting down: Master
2014-11-13 14:24:46 [6747] [INFO] Reason: Worker failed to boot.

2nd: gunicorn --bind yourdomainorip:8001 project.wsgi

i’ve omitted “application” from above command it also struck (gunicorn --bind yourdomainorip:8001 project.wsgi:application)

directory structure:

/home/user/project/...
  /home/user/project/project->wsgi.py
  /home/user/project/app1
  /home/user/project/app2
  /home/user/project/app3
  /home/user/project/manage.py
  /home/user/project/virtualenv

(i am issuing both commands from my manage.py directory)

incase of command 2:

i am struck at…

2014-11-13 14:40:52 [6925] [INFO] Listening at: http://127.0.1.1:8001 (6925)
2014-11-13 14:40:52 [6925] [INFO] Using worker: sync
2014-11-13 14:40:52 [6930] [INFO] Booting worker with pid: 6930

Hi,

Great tutorial. Is this considered a secure application, or are there other measures that need to be taken for security. I ask because I read a similar tutorial for deploying django to AWS and the writer of the tutorial said “extra security measures must be taken” - but didnt qualify of explain the statement!

Thanks,

Andreas

Andrew SB
DigitalOcean Employee
DigitalOcean Employee badge
December 17, 2014

There’s nothing inherently insecure in this. Though, this doesn’t deal with anything on the application level. You might want to take a look at this overview from the official Django docs:

Of course, there are many best practices for administering your server securely that are outside of the scope of this tutorial like: locking down Postgres, setting up a firewll, and disabling password-based log-ins.

Is it OK in Django 1.7?

A couple of issues in step 3. Firstly like @brunoamaral, createuser -P doesn’t ask me for a username, just a password. Secondly, at the end of step 3 I can’t connect to the database :( Thirdly, at the end of step 3 I’m still the postgres Unix user, which isn’t ideal for continuing with the rest of the tutorial.

I’m confused by these instructions. How does gunicorn actually know where to find the Django app? I can’t see anywhere where we’re actually pointing gunicorn at the Django app.

OK, I think you have to be in the Django directory when you run gunicorn_django etc - though the tutorial doesn’t specify that.

I used this command : gunicorn --bind campusballot.com:8001 campusballot.wsgi:application

i step 6, i got this error :

(myenv)root@campusballot:/# gunicorn --bind campusballot.com:8001 campusballot.wsgi:application [2015-03-26 11:09:32 +0000] [13444] [INFO] Starting gunicorn 19.3.0 [2015-03-26 11:09:32 +0000] [13444] [INFO] Listening at: http://127.0.1.1:8001 (13444) [2015-03-26 11:09:32 +0000] [13444] [INFO] Using worker: sync [2015-03-26 11:09:32 +0000] [13449] [INFO] Booting worker with pid: 13449 [2015-03-26 11:09:32 +0000] [13449] [ERROR] Exception in worker process: Traceback (most recent call last): File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/arbiter.py”, line 507, in spawn_worker worker.init_process() File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/workers/base.py”, line 118, in init_process self.wsgi = self.app.wsgi() File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/app/base.py”, line 67, in wsgi self.callable = self.load() File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/app/wsgiapp.py”, line 65, in load return self.load_wsgiapp() File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/app/wsgiapp.py”, line 52, in load_wsgiapp return util.import_app(self.app_uri) File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/util.py”, line 355, in import_app import(module) ImportError: No module named campusballot.wsgi Traceback (most recent call last): File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/arbiter.py”, line 507, in spawn_worker worker.init_process() File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/workers/base.py”, line 118, in init_process self.wsgi = self.app.wsgi() File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/app/base.py”, line 67, in wsgi self.callable = self.load() File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/app/wsgiapp.py”, line 65, in load return self.load_wsgiapp() File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/app/wsgiapp.py”, line 52, in load_wsgiapp return util.import_app(self.app_uri) File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/util.py”, line 355, in import_app import(module) ImportError: No module named campusballot.wsgi [2015-03-26 11:09:32 +0000] [13449] [INFO] Worker exiting (pid: 13449) Traceback (most recent call last): File “/opt/myenv/bin/gunicorn”, line 11, in <module> sys.exit(run()) File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/app/wsgiapp.py”, line 74, in run WSGIApplication(“%(prog)s [OPTIONS] [APP_MODULE]”).run() File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/app/base.py”, line 189, in run super(Application, self).run() File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/app/base.py”, line 72, in run Arbiter(self).run() File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/arbiter.py”, line 174, in run self.manage_workers() File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/arbiter.py”, line 477, in manage_workers self.spawn_workers() File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/arbiter.py”, line 541, in spawn_workers time.sleep(0.1 * random.random()) File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/arbiter.py”, line 214, in handle_chld self.reap_workers() File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/arbiter.py”, line 459, in reap_workers raise HaltServer(reason, self.WORKER_BOOT_ERROR) gunicorn.errors.HaltServer: <HaltServer ‘Worker failed to boot.’ 3> (myenv)root@campusballot:/# clear (myenv)root@campusballot:/# gunicorn --bind campusballot.com:8001 campusballot.wsgi:application [2015-03-26 11:11:07 +0000] [13452] [INFO] Starting gunicorn 19.3.0 [2015-03-26 11:11:07 +0000] [13452] [INFO] Listening at: http://127.0.1.1:8001 (13452) [2015-03-26 11:11:07 +0000] [13452] [INFO] Using worker: sync [2015-03-26 11:11:07 +0000] [13457] [INFO] Booting worker with pid: 13457 [2015-03-26 11:11:07 +0000] [13457] [ERROR] Exception in worker process: Traceback (most recent call last): File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/arbiter.py”, line 507, in spawn_worker worker.init_process() File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/workers/base.py”, line 118, in init_process self.wsgi = self.app.wsgi() File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/app/base.py”, line 67, in wsgi self.callable = self.load() File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/app/wsgiapp.py”, line 65, in load return self.load_wsgiapp() File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/app/wsgiapp.py”, line 52, in load_wsgiapp return util.import_app(self.app_uri) File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/util.py”, line 355, in import_app import(module) ImportError: No module named campusballot.wsgi Traceback (most recent call last): File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/arbiter.py”, line 507, in spawn_worker worker.init_process() File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/workers/base.py”, line 118, in init_process self.wsgi = self.app.wsgi() File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/app/base.py”, line 67, in wsgi self.callable = self.load() File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/app/wsgiapp.py”, line 65, in load return self.load_wsgiapp() File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/app/wsgiapp.py”, line 52, in load_wsgiapp return util.import_app(self.app_uri) File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/util.py”, line 355, in import_app import(module) ImportError: No module named campusballot.wsgi [2015-03-26 11:11:07 +0000] [13457] [INFO] Worker exiting (pid: 13457) Traceback (most recent call last): File “/opt/myenv/bin/gunicorn”, line 11, in <module> sys.exit(run()) File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/app/wsgiapp.py”, line 74, in run WSGIApplication(“%(prog)s [OPTIONS] [APP_MODULE]”).run() File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/app/base.py”, line 189, in run super(Application, self).run() File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/app/base.py”, line 72, in run Arbiter(self).run() File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/arbiter.py”, line 174, in run self.manage_workers() File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/arbiter.py”, line 477, in manage_workers self.spawn_workers() File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/arbiter.py”, line 541, in spawn_workers time.sleep(0.1 * random.random()) File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/arbiter.py”, line 214, in handle_chld self.reap_workers() File “/opt/myenv/local/lib/python2.7/site-packages/gunicorn/arbiter.py”, line 459, in reap_workers raise HaltServer(reason, self.WORKER_BOOT_ERROR) gunicorn.errors.HaltServer: <HaltServer ‘Worker failed to boot.’ 3> (myenv)root@campusballot:/#

in step six i gave this command : $ gunicorn --bind campusballot.com:8001 campusballot.wsgi:application

I got this error:

(myenv)root@campusballot:/# gunicorn --bind campusballot.com:8001 campusballot.wsgi:application
[2015-03-26 11:11:07 +0000] [13452] [INFO] Starting gunicorn 19.3.0
[2015-03-26 11:11:07 +0000] [13452] [INFO] Listening at: http://127.0.1.1:8001 (13452)
[2015-03-26 11:11:07 +0000] [13452] [INFO] Using worker: sync
[2015-03-26 11:11:07 +0000] [13457] [INFO] Booting worker with pid: 13457
[2015-03-26 11:11:07 +0000] [13457] [ERROR] Exception in worker process:
Traceback (most recent call last):
  File "/opt/myenv/local/lib/python2.7/site-packages/gunicorn/arbiter.py", line 507, in spawn_worker
    worker.init_process()
  File "/opt/myenv/local/lib/python2.7/site-packages/gunicorn/workers/base.py", line 118, in init_process
    self.wsgi = self.app.wsgi()
  File "/opt/myenv/local/lib/python2.7/site-packages/gunicorn/app/base.py", line 67, in wsgi
    self.callable = self.load()
  File "/opt/myenv/local/lib/python2.7/site-packages/gunicorn/app/wsgiapp.py", line 65, in load
    return self.load_wsgiapp()
  File "/opt/myenv/local/lib/python2.7/site-packages/gunicorn/app/wsgiapp.py", line 52, in load_wsgiapp
    return util.import_app(self.app_uri)
  File "/opt/myenv/local/lib/python2.7/site-packages/gunicorn/util.py", line 355, in import_app
    __import__(module)
ImportError: No module named campusballot.wsgi
Traceback (most recent call last):
  File "/opt/myenv/local/lib/python2.7/site-packages/gunicorn/arbiter.py", line 507, in spawn_worker
    worker.init_process()
  File "/opt/myenv/local/lib/python2.7/site-packages/gunicorn/workers/base.py", line 118, in init_process
    self.wsgi = self.app.wsgi()
  File "/opt/myenv/local/lib/python2.7/site-packages/gunicorn/app/base.py", line 67, in wsgi
    self.callable = self.load()
  File "/opt/myenv/local/lib/python2.7/site-packages/gunicorn/app/wsgiapp.py", line 65, in load
    return self.load_wsgiapp()
  File "/opt/myenv/local/lib/python2.7/site-packages/gunicorn/app/wsgiapp.py", line 52, in load_wsgiapp
    return util.import_app(self.app_uri)
  File "/opt/myenv/local/lib/python2.7/site-packages/gunicorn/util.py", line 355, in import_app
    __import__(module)
ImportError: No module named campusballot.wsgi
[2015-03-26 11:11:07 +0000] [13457] [INFO] Worker exiting (pid: 13457)
Traceback (most recent call last):
  File "/opt/myenv/bin/gunicorn", line 11, in <module>
    sys.exit(run())
  File "/opt/myenv/local/lib/python2.7/site-packages/gunicorn/app/wsgiapp.py", line 74, in run
    WSGIApplication("%(prog)s [OPTIONS] [APP_MODULE]").run()
  File "/opt/myenv/local/lib/python2.7/site-packages/gunicorn/app/base.py", line 189, in run
    super(Application, self).run()
  File "/opt/myenv/local/lib/python2.7/site-packages/gunicorn/app/base.py", line 72, in run
    Arbiter(self).run()
  File "/opt/myenv/local/lib/python2.7/site-packages/gunicorn/arbiter.py", line 174, in run
    self.manage_workers()
  File "/opt/myenv/local/lib/python2.7/site-packages/gunicorn/arbiter.py", line 477, in manage_workers
    self.spawn_workers()
  File "/opt/myenv/local/lib/python2.7/site-packages/gunicorn/arbiter.py", line 541, in spawn_workers
    time.sleep(0.1 * random.random())
  File "/opt/myenv/local/lib/python2.7/site-packages/gunicorn/arbiter.py", line 214, in handle_chld
    self.reap_workers()
  File "/opt/myenv/local/lib/python2.7/site-packages/gunicorn/arbiter.py", line 459, in reap_workers
    raise HaltServer(reason, self.WORKER_BOOT_ERROR)

I have followed the tutorial properly and am able to host my Django app. However, I have two issues:

  1. My static files are in /opt/app/appname/website/app_main/static, but the static files are not loading. tail /var/log/nginx/error.log show file is loaded from somewhere else entirely! /home/django/django_project/django_project/static/js/authorizedCap.js I’ve used collectstatic but to no avail.

  2. Website is being made available on www.mydomain.com:8001 I want it to be available on www.mydomain.com. How do I change that?

did you ever find out how to do 2.?

Como configuro supervisor?? Ayuda !!

Thanks for the tutorial! It was mostly very easy to follow.

I’ve followed all the steps but when I visit my domain the website is not live. When I try to visit the IP address of my Digital Ocean droplet from within my web browser it says ‘This site can’t be reached. xxx.xxx.xxx.xxx took too long to respond.’

Does anyone know why this is?

Thanks!

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.