DEV Community

ngemuantony
ngemuantony

Posted on • Edited on

Building a Project Budget Manager with Django - Part 4: Deployment and Production Setup On Ubuntu Server

In this final part of our series, we'll prepare our Project Budget Manager for production deployment. We'll cover security configurations, performance optimizations, and deployment steps.

Production Settings

  1. Update config/settings/production.py with production-specific settings:
from .base import *

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False

# SECURITY WARNING: configure the secret key for production
SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY')

# Database configuration
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': os.environ.get('DB_NAME'),
        'USER': os.environ.get('DB_USER'),
        'PASSWORD': os.environ.get('DB_PASSWORD'),
        'HOST': os.environ.get('DB_HOST'),
        'PORT': os.environ.get('DB_PORT', '3306'),
        'OPTIONS': {
            'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
            'charset': 'utf8mb4',
        }
    }
}

# Email settings
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = os.environ.get('EMAIL_HOST', 'smtp.gmail.com')
EMAIL_PORT = int(os.environ.get('EMAIL_PORT', 587))
EMAIL_USE_TLS = True
EMAIL_HOST_USER = os.environ.get('EMAIL_HOST_USER')
EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_HOST_PASSWORD')
DEFAULT_FROM_EMAIL = os.environ.get('DEFAULT_FROM_EMAIL', EMAIL_HOST_USER)

# Security settings
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_BROWSER_XSS_FILTER = True
SECURE_CONTENT_TYPE_NOSNIFF = True

# Static files configuration
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),
]

# Enable WhiteNoise for static file serving
MIDDLEWARE.insert(1, 'whitenoise.middleware.WhiteNoiseMiddleware')
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

# Site settings
SITE_ID = 1
ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', '').split(',')
USE_X_FORWARDED_HOST = True
Enter fullscreen mode Exit fullscreen mode

Environment Variables

Create a production .env file template (.env.example):

# Django settings
DJANGO_SETTINGS_MODULE=config.settings.production
DJANGO_SECRET_KEY=your-secret-key-here
ALLOWED_HOSTS=your-domain.com,www.your-domain.com

# Database settings
DB_NAME=budget_db
DB_USER=budget_user
DB_PASSWORD=your-secure-password
DB_HOST=localhost
DB_PORT=3306

# Email settings
EMAIL_HOST=smtp.gmail.com
EMAIL_PORT=587
EMAIL_HOST_USER=your-email@gmail.com
EMAIL_HOST_PASSWORD=your-app-specific-password
DEFAULT_FROM_EMAIL=your-email@gmail.com

# Security settings
SECURE_SSL_REDIRECT=True
SESSION_COOKIE_SECURE=True
CSRF_COOKIE_SECURE=True
Enter fullscreen mode Exit fullscreen mode

Production Dependencies

Update requirements.txt with production dependencies:

Django==5.0.2
django-allauth==0.61.1
django-crispy-forms==2.3
mysqlclient==2.2.4
whitenoise==6.9.0
python-dotenv==1.0.1
gunicorn==21.2.0
Enter fullscreen mode Exit fullscreen mode

Setting Up MySQL Database

  1. Install MySQL server:
sudo apt update
sudo apt install mysql-server
Enter fullscreen mode Exit fullscreen mode
  1. Create database and user:
CREATE DATABASE budget_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'budget_user'@'localhost' IDENTIFIED BY 'your-secure-password';
GRANT ALL PRIVILEGES ON budget_db.* TO 'budget_user'@'localhost';
FLUSH PRIVILEGES;
Enter fullscreen mode Exit fullscreen mode

Nginx Configuration

  1. Install Nginx:
sudo apt install nginx
Enter fullscreen mode Exit fullscreen mode
  1. Create Nginx configuration (/etc/nginx/sites-available/project-budget):
server {
    listen 80;
    server_name your-domain.com www.your-domain.com;

    location = /favicon.ico { access_log off; log_not_found off; }

    location /static/ {
        root /path/to/your/project;
    }

    location /media/ {
        root /path/to/your/project;
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn.sock;
    }
}
Enter fullscreen mode Exit fullscreen mode
  1. Enable the site:
sudo ln -s /etc/nginx/sites-available/project-budget /etc/nginx/sites-enabled
sudo nginx -t
sudo systemctl restart nginx
Enter fullscreen mode Exit fullscreen mode

Gunicorn Service

  1. Create a systemd service file (/etc/systemd/system/gunicorn.service):
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target

[Service]
User=your-user
Group=www-data
WorkingDirectory=/path/to/your/project
ExecStart=/path/to/your/venv/bin/gunicorn \
    --access-logfile - \
    --workers 3 \
    --bind unix:/run/gunicorn.sock \
    config.wsgi:application

[Install]
WantedBy=multi-user.target
Enter fullscreen mode Exit fullscreen mode
  1. Create socket file (/etc/systemd/system/gunicorn.socket):
[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target
Enter fullscreen mode Exit fullscreen mode
  1. Start and enable the service:
sudo systemctl start gunicorn.socket
sudo systemctl enable gunicorn.socket
Enter fullscreen mode Exit fullscreen mode

SSL Certificate with Let's Encrypt

  1. Install Certbot:
sudo apt install certbot python3-certbot-nginx
Enter fullscreen mode Exit fullscreen mode
  1. Obtain SSL certificate:
sudo certbot --nginx -d your-domain.com -d www.your-domain.com
Enter fullscreen mode Exit fullscreen mode

Deployment Checklist

  1. Prepare the environment:
# Create and activate virtual environment
python -m venv venv
source venv/bin/activate

# Install dependencies
pip install -r requirements.txt
Enter fullscreen mode Exit fullscreen mode
  1. Set up the database:
python manage.py migrate
python manage.py createsuperuser
Enter fullscreen mode Exit fullscreen mode
  1. Collect static files:
python manage.py collectstatic --noinput
Enter fullscreen mode Exit fullscreen mode
  1. Set up environment variables:
cp .env.example .env
# Edit .env with your production values
Enter fullscreen mode Exit fullscreen mode
  1. Test the application:
python manage.py check --deploy
Enter fullscreen mode Exit fullscreen mode

Monitoring and Maintenance

  1. Set up logging in production settings:
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'file': {
            'level': 'ERROR',
            'class': 'logging.FileHandler',
            'filename': '/path/to/django-error.log',
        },
    },
    'loggers': {
        'django': {
            'handlers': ['file'],
            'level': 'ERROR',
            'propagate': True,
        },
    },
}
Enter fullscreen mode Exit fullscreen mode
  1. Regular maintenance tasks:
# Backup database
mysqldump -u budget_user -p budget_db > backup.sql

# Check for updates
pip list --outdated

# Monitor logs
tail -f /path/to/django-error.log
Enter fullscreen mode Exit fullscreen mode

Performance Optimization Tips

  1. Enable caching:
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.redis.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379/1',
    }
}
Enter fullscreen mode Exit fullscreen mode
  1. Use database connection pooling:
DATABASES = {
    'default': {
        # ... other settings ...
        'CONN_MAX_AGE': 60,
    }
}
Enter fullscreen mode Exit fullscreen mode

Resources


This article is part of the "Building a Project Budget Manager with Django" series. Check out Part 1, Part 2, and Part 3 if you haven't already!

Heroku

Built for developers, by developers.

Whether you're building a simple prototype or a business-critical product, Heroku's fully-managed platform gives you the simplest path to delivering apps quickly — using the tools and languages you already love!

Learn More

Top comments (0)

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More