How to Serve Django Admin and API on Separate Subdomains
‘Separating Django’s Admin panel and API on different subdomains can provide added security, cleaner organization, and more manageable scaling. In this guide, we’ll configure a Django project to run the Admin panel on one subdomain, such as
admin.example.com
, and the API on another, such asapi.example.com
. Using Django’s routing along with Nginx as a reverse proxy, this setup offers flexibility and security for your project.
Why Separate Admin and API?
- Enhanced Security: Isolating the Admin panel from the main API reduces exposure to potential security threats.
- Easier Scaling: Separating components allows for targeted scaling. For instance, you can prioritize scaling the API under high user demand while isolating the admin.
- Organized Management: With different domains, users can easily differentiate between API and admin endpoints, reducing the chance of accidental access.
Step 1: Set Up Django Settings
1.1 Add Subdomains to ALLOWED_HOSTS
In Django’s settings.py
, define the subdomains that will host the Admin panel and API. This allows Django to serve requests only from these specific domains.
# settings.py
ALLOWED_HOSTS = ['api.example.com', 'admin.example.com']
1.2 Configure Separate URL Patterns for Admin and API
Let’s create dedicated URL configuration files for both the Admin panel and API. This way, each subdomain will direct requests to a specific set of routes.
- Create Admin and API URL Files
- Admin URLs (
admin_urls.py
):
# admin_urls.py
from django.contrib import admin
from django.urls import path
urlpatterns = [
path('admin/', admin.site.urls), # Admin route
]
- API URLs (
api_urls.py
):
# api_urls.py
from django.urls import path, include
urlpatterns = [
path('v1/', include('your_app.api_urls')), # API routes
]
2. Main urls.py
Configuration
In the primary urls.py
file, conditionally include admin_urls
or api_urls
based on the subdomain in use. To do this, set a HOST
variable that captures the incoming request’s subdomain.
# urls.py
from django.conf import settings
from django.urls import include, path
urlpatterns = []
# Determine which URLs to serve based on HOST setting
if settings.HOST == 'admin':
urlpatterns += [
path('', include('project_name.admin_urls')),
]
elif settings.HOST == 'api':
urlpatterns += [
path('', include('project_name.api_urls')),
]
1.3 Dynamic HOST
Assignment
To capture and use the request’s subdomain, modify wsgi.py
(or asgi.py
for ASGI deployments). Here, we’ll set the HOST
environment variable based on the incoming request’s subdomain, which we’ll use in urls.py
for routing.
# wsgi.py (or asgi.py)
import os
from django.core.wsgi import get_wsgi_application
def application(environ, start_response):
os.environ['DJANGO_SETTINGS_MODULE'] = 'project_name.settings'
os.environ['HOST'] = environ['HTTP_HOST'].split('.')[0] # Set host based on subdomain
return get_wsgi_application()(environ, start_response)
Step 2: Configure Nginx for Subdomain Routing
To properly route requests to the correct Django views, use Nginx to set up reverse proxies that will direct requests from admin.example.com
to the Django admin interface and api.example.com
to the API.
2.1 Define Server Blocks for Each Subdomain
- Admin Subdomain Configuration
Create a new Nginx configuration file for the Admin panel:
# /etc/nginx/sites-available/admin.example.com
server {
listen 80;
server_name admin.example.com;
location / {
proxy_pass http://127.0.0.1:8000; # Local Django server
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;
}
}
- API Subdomain Configuration
Create another configuration file for the API:
# /etc/nginx/sites-available/api.example.com
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://127.0.0.1:8000; # Same Django app instance
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;
}
}
2.2 Enable Nginx Configuration
To activate these configurations, create symbolic links from sites-available
to sites-enabled
:
sudo ln -s /etc/nginx/sites-available/admin.example.com /etc/nginx/sites-enabled
sudo ln -s /etc/nginx/sites-available/api.example.com /etc/nginx/sites-enabled
Afterward, test the Nginx configuration to ensure no syntax errors, then reload Nginx.
sudo nginx -t
sudo systemctl reload nginx
Step 3: Verify the Setup
Once Django and Nginx are configured, you can test the setup by accessing each subdomain:
- Visit
admin.example.com/admin/
to check the Admin panel. - Test the API endpoints at
api.example.com/v1/
.
If both subdomains resolve to the correct routes, your setup is complete! This configuration enhances security, scalability, and manageability for your Django project.
Conclusion
Setting up Django to serve Admin and API on separate subdomains is a smart approach for applications that demand modularity and security. This guide provided step-by-step instructions for configuring Django and Nginx to achieve a seamless, subdomain-based routing structure. Now you can maintain clean, separated routes for your Admin and API, each of which can scale and secure independently.