Django is a web framework for developing mobile applications and websites using Python. It includes a built-in server for local testing and simple solutions, but you'll typically need a more robust setup for production. This guide will walk you through installing Django on Ubuntu and configuring it for production.
sudo
privilegesDo not perform this setup as the
root
user; use a user withsudo
privileges instead.
First, let's update the apt
packages to ensure we use the latest releases. Then, install Python 3 and other necessary packages:
sudo apt update
sudo apt install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx curl
This command will install pip
(Python's package manager), Python-related files, Gunicorn (a Python WSGI HTTP server), PostgreSQL (a relational database system), and Nginx (a web server).
PostgreSQL uses "peer authentication" by default, allowing users to connect without entering a password if the OS user matches the database user. You can switch to the postgres system user using the following command:
sudo -u postgres psql
In the PostgreSQL interface, create a new database for your project:
CREATE DATABASE myproject;
Then, create a user with a secure password:
CREATE USER myprojectuser WITH PASSWORD 'password';
To optimize settings, configure the user with UTF-8 encoding, "read committed" transaction isolation, and the UTC timezone:
ALTER ROLE myprojectuser SET client_encoding TO 'utf8';
ALTER ROLE myprojectuser SET default_transaction_isolation TO 'read committed';
ALTER ROLE myprojectuser SET timezone TO 'UTC';
Now, grant all privileges on the database to this user:
GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;
Exit the PostgreSQL prompt:
\q
Your PostgreSQL database setup is now complete.
You'll need to install virtualenv to create an isolated environment for your project:
sudo -H pip3 install --upgrade pip
sudo -H pip3 install virtualenv
Create a new directory for your project and navigate to it:
mkdir ~/myprojectdir
cd ~/myprojectdir
Now, create a virtual Python environment:
virtualenv myprojectenv
Activate the virtual environment:
source myprojectenv/bin/activate
You’ll see the prompt change, indicating that you're now working inside the virtual environment:
(myprojectenv)user@host:~/myprojectdir$
Install Django, Gunicorn, and the PostgreSQL adapter psycopg2
:
pip install django gunicorn psycopg2-binary
Now, create a new Django project inside the directory:
django-admin startproject myproject ~/myprojectdir
Modify Django settings. Open the settings file to configure it:
nano ~/myprojectdir/myproject/settings.py
At the top of the file, add the following:
import os
Next, find the ALLOWED_HOSTS
directive. This determines which addresses can connect to your Django instance. Add the necessary IP addresses or domains within square brackets:
ALLOWED_HOSTS = ['your_server_domain_or_IP', 'second_domain_or_IP', 'localhost']
Then, scroll to the DATABASES
section. Replace the default configuration with the PostgreSQL settings:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'myproject',
'USER': 'myprojectuser',
'PASSWORD': 'password',
'HOST': 'localhost',
'PORT': '',
}
}
At the end of the file, define where Django should store static files. This will be needed when setting up Nginx:
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
Save and exit the file.
Now, apply database migrations and create a superuser to manage the project:
~/myprojectdir/manage.py makemigrations
~/myprojectdir/manage.py migrate
~/myprojectdir/manage.py createsuperuser
Set a username, password, and email. After this, if you plan to collect all static content in one place, run the following command:
~/myprojectdir/manage.py collectstatic
This will require confirmation before moving files to the static folder. Allow access to port 8000 through the firewall using UFW:
sudo ufw allow 8000
Start the Django development server:
~/myprojectdir/manage.py runserver 0.0.0.0:8000
Visit http://server_domain_or_IP:8000
in your browser to verify that everything is working. If the Django index page appears, your setup is successful! You can also access the admin panel at http://server_domain_or_IP:8000/admin
using the superuser credentials you created.
To stop the development server, press <Ctrl+C> in the terminal.
Gunicorn creates a socket at startup via systemd, which listens for incoming connections. First, create a new file:
sudo nano /etc/systemd/system/gunicorn.socket
In this file, create a new [Unit]
section to describe the socket, a [Socket]
section to define where the socket is located, and an [Install]
section for enabling the socket at startup:
[Unit]
Description=gunicorn socket
[Socket]
ListenStream=/run/gunicorn.sock
[Install]
WantedBy=sockets.target
Save and close the file. Next, create the systemd
service file:
sudo nano /etc/systemd/system/gunicorn.service
Start with the [Unit]
section to define metadata and dependencies, specifying that the service should start after the network is up:
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target
In the [Service]
section, define the user, group, working directory, and command to start Gunicorn. Replace user with your username. In this example, we use 3 worker processes:
[Service]
User=user
Group=www-data
WorkingDirectory=/home/user/myprojectdir
ExecStart=/home/user/myprojectdir/myprojectenv/bin/gunicorn \
--access-logfile - \
--workers 3 \
--bind unix:/run/gunicorn.sock \
myproject.wsgi:application
Finally, in the [Install]
section, define where the services should be linked upon activation:
[Install]
WantedBy=multi-user.target
Close the file and save the changes.
Now, start the Gunicorn socket and enable it to run at boot:
sudo systemctl start gunicorn.socket
sudo systemctl enable gunicorn.socket
To verify that the Gunicorn socket is running, check its status:
sudo systemctl status gunicorn.socket
Make sure the gunicorn.sock file exists in the /run
directory:
file /run/gunicorn.sock
The output should confirm that the socket exists:
/run/gunicorn.sock: socket
If the socket fails to start, use the following command to diagnose the issue:
sudo journalctl -u gunicorn.socket
Check for any errors in the file, and correct them if necessary.
It's important to note that when gunicorn.socket
is running, gunicorn.service
will be inactive. You can confirm this with:
sudo systemctl status gunicorn
The output should show the service is inactive.
Now, test the socket connection with curl
:
curl --unix-socket /run/gunicorn.sock localhost
If you see HTML data, Gunicorn has successfully started. Recheck the status of the service:
sudo systemctl status gunicorn
The status should be Running
. If you encounter errors, check the Gunicorn log for details:
sudo journalctl -u gunicorn
Reload and restart the systemd
daemon if needed:
sudo systemctl daemon-reload
sudo systemctl restart gunicorn
Now, set up Nginx as a reverse proxy. Create a new Nginx configuration file:
sudo nano /etc/nginx/sites-available/myproject
In this file, configure Nginx to listen on port 80 and respond to your domain or server IP address:
server {
listen 80;
server_name server_domain_or_IP;
}
Next, define the location of static files and instruct Nginx to ignore issues related to favicon.ico
:
server {
listen 80;
server_name server_domain_or_IP;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/user/myprojectdir;
}
}
Finally, create a block that passes all other requests to the Gunicorn socket:
server {
listen 80;
server_name server_domain_or_IP;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/user/myprojectdir;
}
location / {
include proxy_params;
proxy_pass http://unix:/run/gunicorn.sock;
}
}
Save and close the file. Link this configuration to the sites-enabled
directory:
sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled
Add the www-data
user to your group:
sudo usermod -a -G ${USER} www-data
Check for syntax errors in the Nginx configuration:
sudo nginx -t
If no errors are found, restart Nginx:
sudo systemctl restart nginx
Now, delete the rule allowing access through port 8000, and open port 80 for Nginx:
sudo ufw delete allow 8000
sudo ufw allow 'Nginx Full'
Finally, visit your server's domain or IP address to confirm everything works.
Before going live, make sure to secure your site with SSL/TLS using a certificate from Let’s Encrypt.
This guide has walked you through installing and configuring Django with PostgreSQL, Gunicorn, and Nginx on Ubuntu. Once configured, you can start building your Django application in this environment.