Table of Contents
- Introduction: What are Nginx and Gunicorn?
- Step 1: Create a Simple Django App
- Step 2: Setting Up the Production Environment
- Step 3: Install and Configure Gunicorn
- Step 4: Use Systemd for Process Management
- Step 5: Configure Nginx as a Reverse Proxy
- Step 6: Secure the App with SSL (Optional)
- Step 7: Troubleshooting Common Issues
Introduction: What are Nginx and Gunicorn?
When you decide to deploy your Django app in production, you want it to be fast, secure, and scalable. Two of the most powerful tools for this are Nginx and Gunicorn.
Gunicorn is a WSGI server that runs your Django application. It listens for incoming requests and passes them to Django, which processes and responds. On the other hand, Nginx is a high-performance web server that acts as a reverse proxy, handling HTTP requests and serving static files, while forwarding dynamic requests to Gunicorn.
This tutorial will take you through the entire process of setting up your Django app with Nginx, Gunicorn, and Systemd—starting from creating a simple app to configuring a production-ready environment. Let’s dive in!
Step 1: Create a Simple Django App
Before we get into the deployment, we need a simple Django app. If you already have one, you can skip this step. But for new users, here's how you can create a simple Django project and app.
# Install Django in your environment pip install django # Create a new Django project django-admin startproject myproject # Create an app inside the project cd myproject python manage.py startapp myapp # Create a simple view in your app # myapp/views.py from django.http import HttpResponse def home(request): return HttpResponse("Hello, World!")
In your urls.py
, make sure to wire up this view:
# myproject/urls.py from django.contrib import admin from django.urls import path from myapp import views urlpatterns = [ path('', views.home), path('admin/', admin.site.urls), ]
Test it by running the Django development server:
python manage.py runserver
Now, visit http://localhost:8000
, and you should see "Hello, World!"
Step 2: Setting Up the Production Environment
Now that we have a working Django app, let’s configure the production environment. This step ensures that everything runs securely and efficiently in production.
First, create a virtual environment to isolate your project dependencies:
# Install virtualenv if you haven’t already pip install virtualenv # Create a virtual environment virtualenv venv # Activate the virtual environment source venv/bin/activate # On Windows, use venv\Scripts\activate # Install Django and Gunicorn pip install django gunicorn
Update your settings.py
to configure Django for production:
# myproject/settings.py DEBUG = False ALLOWED_HOSTS = ['your_domain_or_ip'] # Add your domain or server IP here # Configure your database (e.g., PostgreSQL) DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'your_db_name', 'USER': 'your_db_user', 'PASSWORD': 'your_db_password', 'HOST': 'localhost', 'PORT': '5432', } }
Make sure to apply database migrations:
python manage.py migrate
Your Django app is now ready for production. But before you can serve it, we need Gunicorn to run the app and Nginx to reverse proxy requests.
Step 3: Install and Configure Gunicorn
Gunicorn is the WSGI server that will serve your Django app. Let’s install Gunicorn and test it.
pip install gunicorn
To run Gunicorn on your app, use this command:
gunicorn --workers 3 --bind 0.0.0.0:8000 myproject.wsgi:application
This binds Gunicorn to all available network interfaces on port 8000. Now your app should be accessible at http://your_server_ip:8000
. You can check this by opening a browser and visiting the server’s IP address on port 8000.
For production, however, you should use Nginx as a reverse proxy (discussed in the next section).
Step 4: Use Systemd for Process Management
Gunicorn should be managed by systemd, which will ensure it runs as a background process and starts on boot.
First, create a systemd service file:
# /etc/systemd/system/myproject_gunicorn.service [Unit] Description=gunicorn daemon for Django project After=network.target [Service] User=your_user Group=your_group WorkingDirectory=/path/to/your/project ExecStart=/path/to/your/venv/bin/gunicorn --workers 3 --bind unix:/path/to/your/project/myproject.sock myproject.wsgi:application [Install] WantedBy=multi-user.target
Enable and start Gunicorn with these commands:
# Enable Gunicorn to start on boot sudo systemctl enable myproject_gunicorn # Start Gunicorn sudo systemctl start myproject_gunicorn # Check the status of the service sudo systemctl status myproject_gunicorn
Gunicorn will now run as a service and automatically restart if it crashes.
Step 5: Configure Nginx as a Reverse Proxy
Now, let’s configure Nginx as a reverse proxy. Nginx will accept incoming HTTP requests on port 80 and forward them to Gunicorn running on port 8000 (or using a Unix socket for better performance).
Create an Nginx configuration file for your app:
# /etc/nginx/sites-available/myproject server { listen 80; server_name your_domain_or_ip; # Replace with your domain or public IP location / { proxy_pass http://unix:/path/to/your/project/myproject.sock; # Unix socket for performance proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }
Enable this site and restart Nginx:
# Enable the Nginx site sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled # Test the Nginx configuration sudo nginx -t # Restart Nginx to apply the changes sudo systemctl restart nginx
Now, users can access your app at http://your_domain_or_ip
, and Nginx will forward requests to Gunicorn.
Step 6: Secure the App with SSL (Optional)
It’s a good idea to secure your app with SSL. We recommend using Let’s Encrypt for free SSL certificates.
Here’s how to set up SSL in Nginx:
# /etc/nginx/sites-available/myproject server { listen 443 ssl; server_name your_domain_or_ip; ssl_certificate /etc/letsencrypt/live/your_domain/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/your_domain/privkey.pem; location / { proxy_pass http://unix:/path/to/your/project/myproject.sock; } }
Don’t forget to add a redirect from HTTP to HTTPS:
server { listen 80; server_name your_domain_or_ip; return 301 https://$host$request_uri; }
Step 7: Troubleshooting Common Issues
As you deploy your Django app, you may run into some common errors. Here’s how to handle them:
- Gunicorn Not Starting: If Gunicorn fails to start, check the logs with
sudo journalctl -u myproject_gunicorn
for error details. - 403 Forbidden Error: If you’re seeing a 403 error, ensure that Nginx has permission to access the Gunicorn socket file. Use
ls -l /path/to/your/project/myproject.sock
to check its ownership and permissions. - 500 Internal Server Error: This is usually a Django configuration issue. Check the logs in
/var/log/nginx/error.log
or usesudo journalctl -u myproject_gunicorn
.
With these fixes, your app should be running smoothly in production!