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!

Top comments (0)