Episyche
Django/Deployments/
2022-10-17T07:21:11.687339Z
Published on
Pushing a Django Application from development to production is a demanding process, with multiple steps to configure.
In this tutorial, we are going to host a Django Application on a remote ubuntu server. And run the Gunicorn as a web server locally and set up a reverse proxy using the Nginx web server.
Ubuntu server
Django App
Domain name
Please connect to your Ubuntu server to proceed with the following steps.
To connect with the server using SSH, refer to the article on Connect to your server with SSH.
To connect with the server using vs code, refer to the article on Connect to your server using vs code.
Set up the Django project on your server and check if it is running.
Please refer to the article Getting started with Django on how to set up a Django project on a remote server.
By referring to the above article I've set up my Django project in the path /home/ubuntu/django_example_repo/
and my virtual environment in the path /home/ubuntu/.django_venv/
as shown in the following reference screenshot.
So my django_project_directory would be /home/ubuntu/django_example_repo/
and my virtual_environment would be .django_venv
.
When I refer to these folder structures please keep in mind to replace the commands with your respective Django project path.
When I refer to the Django core app, I’m referring to the app that you created when creating the project that has the files settings.py, wsgi.py, and asgi.py. My Django core app name is core.
We need to collect the static files used in our Django project into a single directory because from now on we are using external servers to serve the files.
Now navigate to the Django core app directory.
1cd <django_project_directory>/<core_app>
2# in my case
3cd /home/ubuntu/django_example_repo/core/
Open the settings.py file and change the variable STATIC_ROOT as follow snippet, if the variable was not found then add the following line.
1STATIC_ROOT = BASE_DIR / 'static'
Now navigate to the Django root directory and run the following command.
1python3 manage.py collectstatic
It’ll copy the static files to a folder named static under the Django project directory.
An example screenshot of the above command is shown below for reference.
Navigate to the Django core app directory.
1cd <django_project_directory>/<core>
2
3For example.
4cd cd /home/ubuntu/django_example_repo/core/
Open the settings.py and append the following code to the file.
1# import the staticfiles_urlpatterns
2from django.contrib.staticfiles.urls import staticfiles_urlpatterns
3
4# below line have to be the last line of the file
5urlpatterns += staticfiles_urlpatterns()
An example django project for your reference can be found in the following git repository.
Gunicorn can be installed by using either APT package manager or python-pip.
We are going to install gunicorn using python-pip, to do so run the following command in the terminal.
1python3 -m pip install gunicorn
Now the gunicorn package will be installed as shown in the below screenshot.
Now we run the Django application using gunicorn in port 8000 which can be accessed from the public internet.
Navigate to the django_project_directory.
1cd <django_project_directory>
2# in my case
3cd /home/ubuntu/django_example_repo/
Run the following command to run gunicorn.
1gunicorn --bind <ip_address>:<port> <core_app>.wsgi:application
2# in my case
3gunicorn --bind 0.0.0.0:8000 core.wsgi:application
ip_address
: tells gunicorn to run the application from which host. For the application to be accessed from the public internet give 0.0.0.0
port
: from which port, are we going to run the application? We'll give 8000.
core_app
: name of the Django core app. (My core app name is named core. Give the name of your django_core_app name)
The gunicorn will run the Django application as shown in the below screenshot.
Check the status by visiting the IP address with the port number. (<ip_address>:8000)
We need to create a systemd for gunicorn for running it as a service so that the gunicorn can be run automatically and independently without manual start.
Navigate to the systemd directory and create a file named gunicorn.service.
1cd /etc/systemd/system/
2sudo touch gunicorn.service
Now open the above-said file and add the following snippet.
1[Unit]
2Description=gunicorn daemon
3After=network.target
4
5[Service]
6User=ubuntu
7Group=ubuntu
8WorkingDirectory=/home/ubuntu/django_example_repo/
9ExecStart=/home/ubuntu/.django_venv/bin/gunicorn --workers 3 --bind 127.0.0.1:8000 core.wsgi:application
10ExecReload=/bin/kill -s HUP $MAINPID
11
12[Install]
13WantedBy=multi-user.target
WorkingDirectory
Director path of Django project (in my case /home/ubuntu/django_example_repo
)
ExecStart
The command for starting gunicorn, gunicorn --workers 3 --bind 0.0.0.0:8000 core.wsgi:application
, (full gunicorn path within the virtual environment, run the command, which gunicorn
and paste the output it returns). An example command execution is given below for reference.
Run the following command so that the gunicorn service is loaded into the system.
1sudo systemctl daemon-reload
To start the gunicorn service run the below command.
1sudo systemctl start gunicorn.service
We need to enable the gunicorn service so that it can be started automatically when the server reboots.
1sudo systemctl enable gunicorn.service
Again check the status by visiting the IP address with the port number. (<ip_address>:8000)
To stop the gunicorn service run the below command.
1sudo systemctl stop gunicorn.service
To restart the gunicorn service run the below command.
1sudo systemctl restart gunicorn.service
An example gunicorn service file can be found in the following git repository.
django_production_setup_example/gunicorn_files at master · episyche/django_production_setup_example
Install Nginx by referring to the following article How to install Nginx on an Ubuntu server?
Disable the default site by running the following command.
1sudo unlink /etc/nginx/sites-enabled/default
Now we need to create a new nginx configuration file for our (new endpoint/ domain/ site).
Navigate to the nginx (configuration/ sites-available) directory and create a file with the name of your convenience(usually domain_name is used, I’m using my domain name api.iternerays.com).
1cd /etc/nginx/sites-available/
2sudo touch iternerays.com
Now open the file api.iternerays.com
and add the following snippet.
1server {
2 listen 80;
3 server_name api.iternerays.com;
4
5location /static {
6 root /home/ubuntu/django_example_repo;
7}
8
9location / {
10 proxy_pass "http://127.0.0.1:8000";
11 }
12}
location /static
redirects the URL whose path starts with /static (like http://api.iternerays.com/static/) to the static file location.
or
to make nginx serve the static files.
location
proxy_pass
redirects the request coming to the server to the locally running gunicorn. We are redirecting the request to port 8000 at localhost in the above example.
An example site configuration file can be found in the following git repository.
Now link the file api.iternerays.com
to the sites-enabled directory.
1sudo ln -s /etc/nginx/sites-available/api.iternerays.com /etc/nginx/sites-enabled/api.itinerarys.com
Restart both nginx and gunicorn to load the configuration changes by running the following commands.
1sudo systemctl restart nginx
2sudo systemctl restart gunicorn
Now check the status by visiting the domain name (In my case api.iternerays.com)
To create SSL certificates we need a domain mapped to our server’s IP address.
Please refer to the article How to point an A record to IP address and point a domain to your server’s IP address.
Install the certbot and nginx plugin using APT manager by running the below command.
1sudo apt install certbot python3-certbot-nginx -y
Then create SSL certificates using certbot by running the following command.
1sudo certbot --nginx -d <domain_name>
2
3# For example
4sudo certbot --nginx -d api.itinerarys.com
Enter the details asked by the certbot with your relevant data respectively.
While creating certificates certbot asks whether or not to redirect HTTP traffic to HTTPS, removing HTTP access, please choose option 2 for redirecting HTTP traffic to HTTPS.
After installing the SSL certificates, the nginx configuration file we created will now look like the below snippet.
1server {
2 server_name api.itinerarys.com;
3
4location /static {
5 root /home/ubuntu/django_example_repo;
6}
7
8location / {
9 proxy_pass "http://127.0.0.1:8000";
10 }
11
12 listen 443 ssl; # managed by Certbot
13 ssl_certificate /etc/letsencrypt/live/api.itinerarys.com/fullchain.pem; # managed by Certbot
14 ssl_certificate_key /etc/letsencrypt/live/api.itinerarys.com/privkey.pem; # managed by Certbot
15 include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
16 ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
17
18}
19server {
20 if ($host = api.itinerarys.com) {
21 return 301 https://$host$request_uri;
22 } # managed by Certbot
23
24
25 listen 80;
26 server_name api.itinerarys.com;
27 return 404; # managed by Certbot
28
29
30}
A reference file can be found in the following git repository.
Now check the status by visiting the domain name. (In my case https://api.itinerarys.com/)
Comments