<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Guguweb - nginx</title><link href="https://www.guguweb.com/" rel="alternate"></link><link href="https://www.guguweb.com/feeds/nginx.atom.xml" rel="self"></link><id>https://www.guguweb.com/</id><updated>2022-03-30T14:50:56+02:00</updated><subtitle>Freelance developer and sysadmin</subtitle><entry><title>Django NGINX: deploy your Django project on a production server</title><link href="https://www.guguweb.com/2019/11/13/django-nginx-deploy-your-django-project-on-a-production-server/" rel="alternate"></link><published>2019-11-13T09:46:56+00:00</published><updated>2022-03-30T14:50:56+02:00</updated><author><name>Augusto Destrero</name></author><id>tag:www.guguweb.com,2019-11-13:/2019/11/13/django-nginx-deploy-your-django-project-on-a-production-server/</id><summary type="html">&lt;p&gt;&lt;a href="https://www.djangoproject.com/"&gt;Django&lt;/a&gt; &lt;a href="https://www.nginx.com/"&gt;NGINX&lt;/a&gt; is a popular and well tested combination used to deploy web applications in production. In this post I will explain the steps needed to have your Django project deployed on a production server using Ubuntu 18.04.&lt;/p&gt;
&lt;p&gt;To have Django NGINX deployed on your production server follow these …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="https://www.djangoproject.com/"&gt;Django&lt;/a&gt; &lt;a href="https://www.nginx.com/"&gt;NGINX&lt;/a&gt; is a popular and well tested combination used to deploy web applications in production. In this post I will explain the steps needed to have your Django project deployed on a production server using Ubuntu 18.04.&lt;/p&gt;
&lt;p&gt;To have Django NGINX deployed on your production server follow these simple steps.&lt;/p&gt;
&lt;div class="toc"&gt;&lt;span class="toctitle"&gt;Table of Contents&lt;/span&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#django-nginx-its-better-together"&gt;Django Nginx: it's better together!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#install-required-packages-using-apt"&gt;Install required packages using apt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#create-directories-for-your-static-and-media-files"&gt;Create directories for your static and media files&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#setup-your-django-project-and-install-requirements"&gt;Setup your Django project and install requirements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#collect-static-files"&gt;Collect static files&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#configure-uwsgi-to-host-your-django-project"&gt;Configure uWSGI to host your Django project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#configure-nginx-to-serve-your-application"&gt;Configure NGINX to serve your application&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#enjoy-your-django-nginx-application"&gt;Enjoy your Django NGINX application&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#extra-step-automate-all-these-steps-with-ansible"&gt;Extra step: automate all these steps with Ansible!&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h2 id="django-nginx-its-better-together"&gt;Django Nginx: it's better together!&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.djangoproject.com/"&gt;Django&lt;/a&gt; is a web framework written in Python. It lets you develop and prototype web applications with little effort. It comes with many built-in features that are often useful in a web application, such as: session management, user authentication, an object relational mapper, a template language.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.nginx.com/"&gt;NGINX&lt;/a&gt; is a very fast and configurable web server that is very well suited to serve static files and act as a reverse proxy for other applications. In this tutorial I'll explain how to configure NGINX to serve static files (images, javascript, css, ...) and to proxy requests to your Django application.&lt;/p&gt;
&lt;h2 id="install-required-packages-using-apt"&gt;Install required packages using apt&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo apt install nginx uwsgi uwsgi-plugin-python3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Why do you need &lt;a href="https://uwsgi-docs.readthedocs.io/en/latest/"&gt;uWSGI&lt;/a&gt;? In very simple terms NGINX on its own cannot run a Python process to host your application, for this you&amp;#8217;ll need a so called &lt;em&gt;application server&lt;/em&gt; that will host a Python process running your Django project. NGINX and uWSGI will &amp;#8220;talk&amp;#8221; each other using the uwsgi protocol.&lt;/p&gt;
&lt;h2 id="create-directories-for-your-static-and-media-files"&gt;Create directories for your static and media files&lt;/h2&gt;
&lt;p&gt;Static files are &amp;#8220;not-python&amp;#8221; files needed by your Django project, for example Javascript, CSS and images. Media files will be the files uploaded by the users of your application. Not every application will let users upload files, but it&amp;#8217;s a very common scenario. Django will not serve static and media files by itself. We&amp;#8217;ll leverage NGINX to serve them.&lt;/p&gt;
&lt;p&gt;First of all you have to create the directories. Here I assume that you are currently using the user &lt;strong&gt;ubuntu&lt;/strong&gt; with the default home directory &lt;strong&gt;/home/ubuntu&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir -p /home/ubuntu/static /home/ubuntu/media
sudo chown www-data.www-data /home/ubuntu/media
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The second command will make the user named &lt;strong&gt;www-data&lt;/strong&gt; the owner of the &lt;strong&gt;/home/ubuntu/media&lt;/strong&gt; directory. &lt;strong&gt;www-data&lt;/strong&gt; will be the user running your Python process in uWSGI, and that user should be able to write in the media directory to correctly save user uploaded files.&lt;/p&gt;
&lt;h2 id="setup-your-django-project-and-install-requirements"&gt;Setup your Django project and install requirements&lt;/h2&gt;
&lt;p&gt;This step really depends on your particular Django application, for the purpose of this tutorial I will assume that your Django project is installed in the directory &lt;code&gt;/home/ubuntu/django_project/&lt;/code&gt; with the following structure:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;/home/ubuntu/django_project/
├── app1
│   ├── admin.py
│   ├── __init__.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   ├── views.py
├── manage.py
└── project
   ├── __init__.py
   ├── settings
  │   └── __init__.py
  │   └── base.py
  │   └── production.py
   ├── urls.py
   ├── wsgi.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Also I will assume that you installed all your Python requirements, for example using apt or pip.&lt;/p&gt;
&lt;p&gt;I always follow a best practice when starting a new Django project, by splitting the monolithic &lt;strong&gt;settings.py&lt;/strong&gt; file in different files, one for each deploy environment (local, test, production, &amp;#8230;). You can read a more &lt;a href="https://www.coderedcorp.com/blog/django-settings-for-multiple-environments/"&gt;in depth explanation&lt;/a&gt; of this approach if you aren&amp;#8217;t used to it.&lt;/p&gt;
&lt;p&gt;In our case Django will use the module &lt;strong&gt;project/settings/production.py&lt;/strong&gt; for his settings. Here we set the &lt;strong&gt;STATIC_ROOT&lt;/strong&gt; and &lt;strong&gt;MEDIA_ROOT&lt;/strong&gt; variables to the directories we created at step 2:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;.base&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;

&lt;span class="n"&gt;ALLOWED_HOSTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;www.example.com&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# customize with your domain name&lt;/span&gt;

&lt;span class="n"&gt;DATABASES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;default&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# here the configuration for your database&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;STATIC_ROOT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/home/ubuntu/static&amp;#39;&lt;/span&gt;
&lt;span class="n"&gt;MEDIA_ROOT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/home/ubuntu/media&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="collect-static-files"&gt;Collect static files&lt;/h2&gt;
&lt;p&gt;Run the following command to collect all static files for your Django project:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;./manage.py collectstatic
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This command will copy all static files (Javascript, CSS, images) for all your Django apps in the &lt;strong&gt;STATIC_ROOT&lt;/strong&gt; directory configured in &lt;strong&gt;production.py&lt;/strong&gt;. For instance &lt;strong&gt;/home/ubuntu/static&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id="configure-uwsgi-to-host-your-django-project"&gt;Configure uWSGI to host your Django project&lt;/h2&gt;
&lt;p&gt;Create a file named &lt;strong&gt;django.ini&lt;/strong&gt; in the &lt;strong&gt;/etc/uwsgi/apps-enabled/&lt;/strong&gt; directory. The content of the file should be something like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;[uwsgi]&lt;/span&gt;
&lt;span class="na"&gt;chdir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/home/ubuntu/django_project # customize with your django installation directory&lt;/span&gt;
&lt;span class="na"&gt;env&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;DJANGO_SETTINGS_MODULE=project.settings.production # customize with your settings module&lt;/span&gt;
&lt;span class="na"&gt;wsgi-file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;project/wsgi.py # customize with the relative path to your wsgi.py file&lt;/span&gt;
&lt;span class="na"&gt;workers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Restart uWSGI with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;service uwsgi restart
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You should find the uWSGI logs in &lt;strong&gt;/var/log/uwsgi/apps/django.log&lt;/strong&gt;. Therefore you can check them to see if the Python process started correctly or there are issues.&lt;/p&gt;
&lt;h2 id="configure-nginx-to-serve-your-application"&gt;Configure NGINX to serve your application&lt;/h2&gt;
&lt;p&gt;Create a file named &lt;strong&gt;django&lt;/strong&gt; in the &lt;strong&gt;/etc/nginx/sites-enabled/&lt;/strong&gt; directory. The content of the file should be something like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;www.example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# customize with your domain name&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;# django running in uWSGI&lt;/span&gt;
        &lt;span class="kn"&gt;uwsgi_pass&lt;/span&gt; &lt;span class="s"&gt;unix:///run/uwsgi/app/django/socket&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;include&lt;/span&gt; &lt;span class="s"&gt;uwsgi_params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;uwsgi_read_timeout&lt;/span&gt; &lt;span class="s"&gt;300s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;client_max_body_size&lt;/span&gt; &lt;span class="mi"&gt;32m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/static/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="c1"&gt;# static files&lt;/span&gt;
       &lt;span class="kn"&gt;alias&lt;/span&gt; &lt;span class="s"&gt;/home/ubuntu/static/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# ending slash is required&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="s"&gt;/media/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;# media files, uploaded by users&lt;/span&gt;
        &lt;span class="kn"&gt;alias&lt;/span&gt; &lt;span class="s"&gt;/home/ubuntu/media/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# ending slash is required&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Restart NGINX with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;service nginx restart
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id="enjoy-your-django-nginx-application"&gt;Enjoy your Django NGINX application&lt;/h2&gt;
&lt;p&gt;Point the browser to your domain, and you should see your Django application in all of its glory!&lt;/p&gt;
&lt;h2 id="extra-step-automate-all-these-steps-with-ansible"&gt;Extra step: automate all these steps with Ansible!&lt;/h2&gt;
&lt;p&gt;If you have to manage many different Django projects on many different servers, certainly you&amp;#8217;ll find that automating stuff is always a good idea.&lt;/p&gt;
&lt;p&gt;Read my post on &lt;a href="https://www.guguweb.com/2017/05/02/how-to-deploy-a-django-project-in-15-minutes-with-ansible/"&gt;How to deploy a Django project in 15 minutes with Ansible&lt;/a&gt; to automate all the steps described here.&lt;/p&gt;
&lt;p&gt;In conclusion, I hope that this post helped you with configuring Django NGINX to deploy your Django project on a production server. Please let me know if you have questions leaving a comment in the area below or contacting me by email or social account.&lt;/p&gt;</content><category term="web"></category><category term="django"></category><category term="nginx"></category><category term="python"></category><category term="uwsgi"></category></entry></feed>