mirror of
https://github.com/thecyberlearn/hostinger-django-demo.git
synced 2026-08-18 07:52:56 +00:00
- Complete deployment documentation (PRODUCTION_DEPLOYMENT.md) - Automated deployment script (production-deploy.sh) - Systemd service templates (socket + service) - Production settings template with security best practices - Nginx configuration template with performance optimizations - Comprehensive troubleshooting guide - Quick start guide for fast deployment Fixes all issues encountered in initial deployment: - Uses non-root django user for security - Proper /var/www directory structure - Unix socket instead of TCP for better performance - Socket activation with systemd - Correct virtual environment handling - Production security headers and settings 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
7.6 KiB
7.6 KiB
Production Django Deployment Guide
A comprehensive, battle-tested guide for deploying Django applications on VPS with proper security and performance.
🎯 Overview
This guide follows Django best practices and avoids common pitfalls we encountered:
- ❌ Avoid: Running as root, wrong directories, TCP sockets, hardcoded paths
- ✅ Use: Non-root user,
/var/www/, Unix sockets, proper systemd configuration
📋 Prerequisites
- Ubuntu 20.04+ VPS with root access
- Domain name (optional, can use IP address)
- Git repository with Django project
🚀 Step 1: VPS Initial Setup
Connect and Update System
ssh root@YOUR_VPS_IP
apt update && apt upgrade -y
Install Required Packages
apt install -y python3 python3-pip python3-venv python3-dev \
nginx postgresql postgresql-contrib libpq-dev \
build-essential curl git ufw
Create Non-Root User
adduser django --disabled-password --gecos ''
usermod -aG sudo django
Configure SSH for New User (Optional)
mkdir -p /home/django/.ssh
cp /root/.ssh/authorized_keys /home/django/.ssh/
chown -R django:django /home/django/.ssh
chmod 700 /home/django/.ssh
chmod 600 /home/django/.ssh/authorized_keys
🗂️ Step 2: Project Setup
Create Project Directory
mkdir -p /var/www
chown django:www-data /var/www
Clone Project (as django user)
sudo -u django bash -c "
cd /var/www
git clone YOUR_REPO_URL django-app
cd django-app
"
Create Virtual Environment
sudo -u django bash -c "
cd /var/www/django-app
python3 -m venv venv
source venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
"
⚙️ Step 3: Django Configuration
Environment Variables
sudo -u django bash -c "
cd /var/www/django-app
cp .env.example .env
# Edit .env with production settings
"
Required .env settings:
SECRET_KEY=your-super-secret-key-generate-new-one
DEBUG=False
ALLOWED_HOSTS=yourdomain.com,www.yourdomain.com,YOUR_VPS_IP
DATABASE_URL=postgresql://dbuser:dbpassword@localhost/dbname
SECURE_SSL_REDIRECT=False # Set True after SSL setup
Run Django Setup
sudo -u django bash -c "
cd /var/www/django-app
source venv/bin/activate
python manage.py collectstatic --noinput
python manage.py migrate
python manage.py createsuperuser
"
🔧 Step 4: Gunicorn with systemd
Create Gunicorn Socket
cat > /etc/systemd/system/gunicorn.socket << 'EOF'
[Unit]
Description=gunicorn socket
[Socket]
ListenStream=/run/gunicorn.sock
[Install]
WantedBy=sockets.target
EOF
Create Gunicorn Service
cat > /etc/systemd/system/gunicorn.service << 'EOF'
[Unit]
Description=Gunicorn daemon for Django app
Requires=gunicorn.socket
After=network.target
[Service]
User=django
Group=www-data
WorkingDirectory=/var/www/django-app
Environment=DJANGO_SETTINGS_MODULE=PROJECT_NAME.settings
EnvironmentFile=/var/www/django-app/.env
ExecStart=/var/www/django-app/venv/bin/gunicorn \
--workers 3 \
--bind unix:/run/gunicorn.sock \
PROJECT_NAME.wsgi:application
Restart=always
[Install]
WantedBy=multi-user.target
EOF
⚠️ Replace PROJECT_NAME with your actual Django project name!
Start Services
systemctl daemon-reload
systemctl start gunicorn.socket
systemctl enable gunicorn.socket
systemctl status gunicorn.socket
🌐 Step 5: Nginx Configuration
Create Nginx Site Config
cat > /etc/nginx/sites-available/django-app << 'EOF'
server {
listen 80;
server_name YOUR_DOMAIN.com www.YOUR_DOMAIN.com YOUR_VPS_IP;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
# Gzip compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
location / {
include proxy_params;
proxy_pass http://unix:/run/gunicorn.sock;
}
location /static/ {
alias /var/www/django-app/staticfiles/;
expires 1y;
add_header Cache-Control "public, immutable";
}
location /media/ {
alias /var/www/django-app/media/;
expires 1y;
add_header Cache-Control "public";
}
# Block access to sensitive files
location ~* /\.(?!well-known\/) {
deny all;
}
location ~* /(requirements\.txt|\.env|deploy/|\.git/) {
deny all;
}
}
EOF
Enable Site
ln -s /etc/nginx/sites-available/django-app /etc/nginx/sites-enabled/
rm -f /etc/nginx/sites-enabled/default
nginx -t
systemctl restart nginx
🔒 Step 6: Security & Firewall
Configure UFW Firewall
ufw default deny incoming
ufw default allow outgoing
ufw allow ssh
ufw allow 'Nginx Full'
ufw --force enable
ufw status
🔐 Step 7: SSL Certificate (Optional)
Install Certbot
apt install certbot python3-certbot-nginx -y
Get SSL Certificate
certbot --nginx -d yourdomain.com -d www.yourdomain.com
Update Environment for HTTPS
# In /var/www/django-app/.env
SECURE_SSL_REDIRECT=True
✅ Step 8: Verification
Test Application
curl -I http://YOUR_VPS_IP # Should return 200 OK
Check Services
systemctl status gunicorn.socket
systemctl status gunicorn.service
systemctl status nginx
View Logs
journalctl -u gunicorn.service -f # Django logs
tail -f /var/log/nginx/error.log # Nginx logs
🔄 Deployment Updates
Update Code
sudo -u django bash -c "
cd /var/www/django-app
git pull origin main
source venv/bin/activate
pip install -r requirements.txt
python manage.py migrate
python manage.py collectstatic --noinput
"
systemctl restart gunicorn.service
🚨 Common Issues & Solutions
Issue: 502 Bad Gateway
Cause: Gunicorn not running or socket issues Solution:
systemctl status gunicorn.service
systemctl restart gunicorn.socket
Issue: Static files not loading
Cause: Nginx can't access staticfiles directory Solution:
sudo -u django bash -c "cd /var/www/django-app && source venv/bin/activate && python manage.py collectstatic --noinput"
Issue: Permission denied
Cause: Wrong file ownership Solution:
chown -R django:www-data /var/www/django-app
Issue: ModuleNotFoundError
Cause: Virtual environment not recreated after moving files Solution:
sudo -u django bash -c "cd /var/www/django-app && rm -rf venv && python3 -m venv venv && source venv/bin/activate && pip install -r requirements.txt"
📝 Quick Commands Reference
# Service management
systemctl restart gunicorn.service
systemctl restart nginx
systemctl status gunicorn.service
# View logs
journalctl -u gunicorn.service -f
tail -f /var/log/nginx/access.log
# Django management
sudo -u django bash -c "cd /var/www/django-app && source venv/bin/activate && python manage.py COMMAND"
🎯 Key Differences from Our Initial Approach
- User: Use
djangouser instead ofroot - Location: Use
/var/www/django-appinstead of/root/django-demo - Socket: Use Unix socket instead of TCP
- Virtual Environment: Always recreate in target location
- Systemd: Use socket activation with proper service file
- Security: Proper file permissions and firewall rules
This configuration is production-ready, secure, and follows Django best practices.