In this article, we'll talk about how to deploy a Django project manually on a Linux server using uWSGI and Nginx. Assume you are using Ubuntu 22.4 LTS.
First of all, you must prepare your server like we discussed in this article, so that it is secure and safe to use. And also make sure your software is up to date by running the following commands.
1sudo apt update
1sudo apt upgrade
Clone your project using Git
After you've set up the server, you'll need to upload the Django project to the server. Git is an ideal tool for this purpose. Git is an open-source version control software that can track the changes in the source code. It is designed for coordinating work among programmers.
Git should be preinstalled on your system by default, but just in case it is not there, you can install it using the following command:
1sudo apt install git
And then, go to the home
directory, and clone our project from GitHub to the server.
1cd ~
1git clone https://github.com/ericsdevblog/django-tutorial.git
This command will create a django-tutorial
directory and put our project in it. Here is a small Linux trick, you can check the content of a directory using the following command:
1ls
If you need to list the hidden items as well:
1ls -a
Next time, when you make changes to our project, instead of uploading the entire project again, you only need to run the git pull
command.
Create virtual environment & install requirements
Now that you have cloned your Django project, you need to create an isolated virtual Python environment for it. However, on Debian based systems, the venv
package, which you'll need to create a virtual environment, is not included by default, but you can install it using the following command:
1sudo apt install python3.10-venv
Go to the application's root directory:
1cd <path_to_root_directory>
Create a virtual environment:
1python3 -m venv env
Run the ls
command again, and you should see an env
directory. The virtual environment is created inside. Now, all you need to do is activate the environment and install all the necessary requirements for this project.
Activate the virtual environment:
1source env/bin/activate
Remember, if you install required packages without activating the virtual environment, the packages will be installed globally, instead of in the virtual environment we just created.
If the activation is successful, your terminal prompt should look like this.
1(env) eric@djangoDeployDemo:~/django-tutorial/djangoTutorial$
(env)
means you are currently working inside a virtual environment called env
.
You can also deactivate virtual environment using the following command:
1deactivate
Install requirements:
1pip install -r requirements.txt
Install uWSGI
uWSGI is a software application that "aims at developing a full stack for building hosting services". It is named after the Web Server Gateway Interface (WSGI), which was the first plugin supported by the project.
uWSGI is often used for serving Python web applications in conjunction with web servers such as Cherokee and Nginx, which offer direct support for uWSGI's native uWSGI protocol.
Before you can install uWSGI, you need to install the Python development package first.
1sudo yum groupinstall "Development Tools"
2sudo yum install python-devel
Next, install the latest stable version of uWSGI:
1pip install uwsgi
Test Your Django Project
Now, we can test our Django project with uWSGI. First, make sure our site actually works:
1python manage.py runserver 0.0.0.0:8000
And if that works, run it with uWSGI:
1uwsgi --http :8000 --module django_blog.wsgi
module mysite.wsgi
: load the specified wsgi
module.
Visit the server IP from your browser, if the site appears, it means uWSGI is able to serve your Django application from your virtualenv
, and this stack operates correctly:
1the web client <-> uWSGI <-> Django
Now, normally we won’t have the browser speaking directly to uWSGI. That’s a job for the web server, which will act as a go-between.
Install Nginx
Nginx is an open-source high-performance web server. Compared to Apache, it is much more flexible and lightweight.
First, we need to add the Nginx repository:
1sudo yum install epel-release
Install Nginx using yum
command:
1sudo yum install nginx
After this, we can start the Nginx server by typing:
1sudo systemctl start nginx
Now we need to check if the Nginx server is working properly by visiting it in a web browser on port 80. You should get a message from Nginx: “Welcome to Nginx!”. If not, it is probably because something else is running on port 80, and you need to reconfigure Nginx to serve on a different port. For this tutorial, we'll use port 8000.
Configure Nginx for Your Site
To configure Nginx so that it works for our Django site, we need to edit the uwsgi_params
file, which is available in the nginx
directory of the uWSGI distribution, or from GitHub.
We need to copy this file to the Django project directory, and later we'll need to tell Nginx to use this file.
Now create a file called django_blog_nginx.conf
in the /etc/nginx/sites-available/
directory, and add the following configurations:
1# django_blog_nginx.conf
2
3# the upstream component nginx needs to connect to
4
5upstream django {
6 # server unix:///<path_to_your_site>/mysite.sock; # for a file socket
7 server 127.0.0.1:8001; # for a web port socket (we'll use this first)
8}
9
10# configuration of the server
11
12server {
13 # the port your site will be served on
14 listen 8000;
15 # the domain name it will serve for
16 server_name example.com; # substitute your machine's IP address or FQDN
17 charset utf-8;
18
19 # max upload size
20 client_max_body_size 75M; # adjust to taste
21
22 # Django media
23 location /media {
24 alias <path_to_your_site>/media; # your Django project's media files - amend as required
25 }
26
27 location /static {
28 alias <path_to_your_site>/static; # your Django project's static files - amend as required
29 }
30
31 # Finally, send all non-media requests to the Django server.
32 location / {
33 uwsgi_pass django;
34 include <path_to_your_site>/uwsgi_params; # the uwsgi_params file you installed
35 }
36
37}
This configuration file tells Nginx to serve the site on port 8000. Nginx will handle the static file and media files, as well as requests that require Django's intervention. For a large project, it is always better to let one server handel static/media files, and another handle Django applications. But for now, this is all we need to do.
Symlink to this file from /etc/nginx/sites-enabled
so Nginx can use it:
1sudo ln -s /etc/nginx/sites-available/django_blog_nginx.conf /etc/nginx/sites-enabled/
Deploy Static Files
Before running Nginx, we have to collect all Django static files in the static folder. First of all, we have to edit settings.py
adding:
1STATIC_ROOT = os.path.join(BASE_DIR, "static/")
and then run
1python manage.py collectstatic
Test Nginx Server
Since we made changes to the Nginx server configuration, we need to restart the server so that these changes can take effect:
1sudo systemctl restart nginx
Upload a new image (media.png
) to the /media
directory, can then visit http://<your_domain>:8000/media/media.png
in the browser to see if Nginx is serving the media files correctly. If it doesn't work, try stopping and starting the Nginx server again. This will inform you if there is a problem and where it is.
Run the Django Application with Nginx and uWSGI
Now that we have uWSGI and Nginx properly installed and configured, we can start our Django application:
1uwsgi --socket django_blog.sock --module django_blog.wsgi --chmod-socket=664
Configuring uWSGI to run with a .ini
file
We can put relevant uWSGI configurations into a file, and then ask uWSGI to parse the configurations on start up.
Create a file called django_blog_uwsgi.ini
:
1# django_blog_uwsgi.ini file
2
3[uwsgi]
4
5# Django-related settings
6
7# the base directory (full path)
8
9chdir = /path/to/your/project
10
11# Django's wsgi file
12
13module = project.wsgi
14
15# the virtualenv (full path)
16
17home = /path/to/virtualenv
18
19# process-related settings
20
21# master
22
23master = true
24
25# maximum number of worker processes
26
27processes = 10
28
29# the socket (use the full path to be safe
30
31socket = /path/to/your/project/mysite.sock
32
33# ... with appropriate permissions - may be needed
34
35# chmod-socket = 664
36
37# clear environment on exit
38
39vacuum = true
And run uwsgi
using this file:
1uwsgi --ini mysite_uwsgi.ini # the --ini option is used to specify a file
Install uWSGI System-Wide
So far, uWSGI is only installed in our virtual environment, and we’ll need it installed system-wide for deployment purposes.
Deactivate your virtual environment:
1deactivate
and install uWSGI system-wide:
1sudo pip3 install uwsgi
The uWSGI wiki describes several installation procedures. Before installing uWSGI system-wide, it’s worth considering which version to choose and the most appropriate way of installing it.
Check again that we can still run uWSGI just like we did before:
1uwsgi --ini mysite_uwsgi.ini # the --ini option is used to specify a file