Skip to main content

Overview

Inventario is a Django 5.2 application designed for easy deployment on cloud platforms or traditional servers. This guide covers local development setup, environment configuration, and production deployment.

System Requirements

Python

Version: 3.11.9 or higherRequired for Django 5.2 compatibility

Database

Production: PostgreSQL 12+Development: SQLite (included)

Memory

Minimum: 512 MB RAMRecommended: 1 GB+ for production

Storage

Minimum: 500 MBIncludes dependencies, static files, and media uploads

Dependencies

The application requires the following key packages:
requirements.txt
Django==5.2.6
django-allauth==65.14.3          # Google OAuth & authentication
django-widget-tweaks==1.5.1      # Form rendering utilities
gunicorn==25.1.0                  # Production WSGI server
whitenoise==6.11.0                # Static file serving
psycopg2-binary==2.9.11           # PostgreSQL adapter
dj-database-url==3.1.2            # Database URL parsing
python-dotenv==1.2.1              # Environment variable management
openai==2.21.0                    # AI-powered insights
twilio==9.10.1                    # SMS notifications
Pillow==12.1.1                    # Image processing
reportlab==4.4.10                 # PDF generation
barcode==1.0.4                    # Barcode generation
pandas==3.0.0                     # Data analysis for reports
resend==2.0.0                     # Email service

Environment Variables

Create a .env file in the project root with the following configuration:
# Core Django Settings
DEBUG=False
SECRET_KEY=your-secret-key-here-min-50-characters
ALLOWED_HOSTS=yourdomain.com,www.yourdomain.com
CSRF_TRUSTED_ORIGINS=https://yourdomain.com,https://www.yourdomain.com

# Database (PostgreSQL)
DATABASE_URL=postgresql://user:password@host:5432/database_name

# Email Configuration (Resend)
RESEND_API_KEY=re_xxxxxxxxxxxxx
DEFAULT_FROM_EMAIL=[email protected]

# Google OAuth (Optional)
GOOGLE_CLIENT_ID=your-google-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your-google-client-secret

# AI Features (Optional)
OPENAI_API_KEY=sk-proj-xxxxxxxxxxxxxxxx

# SMS Notifications (Optional)
TWILIO_ACCOUNT_SID=ACxxxxxxxxxxxxxxxx
TWILIO_AUTH_TOKEN=your-twilio-auth-token
TWILIO_PHONE_NUMBER=+1234567890

# Security
SESSION_COOKIE_SECURE=True
CSRF_COOKIE_SECURE=True

Configuration Breakdown

Django’s cryptographic signing key. Generate a secure random string:
from django.core.management.utils import get_random_secret_key
print(get_random_secret_key())
Never commit this to version control!
Database connection string parsed by dj-database-url:
# From inventario/settings.py:79-84
DATABASES = {
    'default': dj_database_url.config(
        default=f'sqlite:///{BASE_DIR / "db.sqlite3"}',
        conn_max_age=600
    )
}
Format: postgresql://username:password@host:port/databaseIf not provided, defaults to SQLite (dev only).
Enable “Sign in with Google” functionality:
  1. Go to Google Cloud Console
  2. Create a new project or select existing
  3. Enable Google+ API
  4. Create OAuth 2.0 credentials
  5. Add authorized redirect URI: https://yourdomain.com/accounts/google/login/callback/
# Configuration from inventario/settings.py:130-141
SOCIALACCOUNT_PROVIDERS = {
    'google': {
        'SCOPE': ['profile', 'email'],
        'AUTH_PARAMS': {'access_type': 'online'},
        'VERIFIED_EMAIL': True,
        'APP': {
            'client_id': os.environ.get('GOOGLE_CLIENT_ID', ''),
            'secret': os.environ.get('GOOGLE_CLIENT_SECRET', ''),
            'key': ''
        }
    }
}
Powers AI-driven dashboard insights and recommendations:
  • Predictive analytics for sales trends
  • Stock replenishment suggestions
  • Customer behavior analysis
  • Automated report summaries
Get your API key from OpenAI Platform
Enable SMS notifications for:
  • Low stock alerts
  • Daily sales summaries
  • Order confirmations
Sign up at Twilio and get your credentials from the dashboard.

Local Development Setup

1

Clone Repository

git clone <repository-url>
cd inventario
2

Create Virtual Environment

python3.11 -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate
3

Install Dependencies

pip install -r requirements.txt
4

Configure Environment

Copy the development .env template:
cp _env .env
Edit .env and set minimum required variables:
  • DEBUG=True
  • SECRET_KEY=<generate-one>
5

Run Database Migrations

python manage.py migrate
This creates the SQLite database and all required tables.
6

Create Superuser

python manage.py createsuperuser
Enter username, email, and password. This account has full admin access.
7

Collect Static Files

python manage.py collectstatic --no-input
Gathers all static files (CSS, JS, images) into staticfiles/ directory.
8

Run Development Server

python manage.py runserver
Access the application at http://127.0.0.1:8000Admin panel: http://127.0.0.1:8000/admin/

Production Deployment

Option 1: Railway Deployment

1

Prepare Project

Ensure these files exist in your repository:Procfile:
web: gunicorn inventario.wsgi:application --log-file - --workers 2 --timeout 120
runtime.txt:
python-3.11.9
2

Create Railway Project

  1. Go to Railway.app
  2. Click New ProjectDeploy from GitHub repo
  3. Select your repository
  4. Railway auto-detects Django and Python version
3

Add PostgreSQL Database

  1. In your Railway project, click NewDatabaseAdd PostgreSQL
  2. Railway automatically creates DATABASE_URL environment variable
  3. The database is linked to your application
4

Configure Environment Variables

In Railway dashboard, add all production environment variables:
DEBUG=False
SECRET_KEY=<generate-secure-key>
ALLOWED_HOSTS=${{RAILWAY_PUBLIC_DOMAIN}}
CSRF_TRUSTED_ORIGINS=https://${{RAILWAY_PUBLIC_DOMAIN}}
DATABASE_URL=${{DATABASE_URL}}  # Auto-provided by Railway
RESEND_API_KEY=<your-resend-key>
DEFAULT_FROM_EMAIL=[email protected]
5

Deploy

Railway automatically deploys on every push to your main branch.Build process:
  1. Installs dependencies from requirements.txt
  2. Runs migrations automatically
  3. Collects static files
  4. Starts Gunicorn server
Monitor deployment in Railway dashboard logs.
6

Configure Custom Domain (Optional)

  1. In Railway project settings, go to Domains
  2. Add your custom domain
  3. Update DNS records as shown
  4. Update ALLOWED_HOSTS and CSRF_TRUSTED_ORIGINS with your domain

Option 2: Render Deployment

1

Prepare Build Script

Create build.sh in project root:
build.sh
#!/usr/bin/env bash
set -o errexit

echo "📦 Installing dependencies..."
pip install -r requirements.txt

echo "📁 Collecting static files..."
python manage.py collectstatic --no-input

echo "🗄️ Running migrations..."
python manage.py migrate

echo "🌐 Configuring Site domain..."
python manage.py shell -c "
from django.contrib.sites.models import Site
site, _ = Site.objects.get_or_create(id=1)
site.domain = 'yourdomain.com'
site.name = 'Inventario'
site.save()
"

echo "✅ Build completed successfully."
Make it executable:
chmod +x build.sh
2

Create Render Web Service

  1. Go to Render Dashboard
  2. Click NewWeb Service
  3. Connect your GitHub/GitLab repository
  4. Configure:
    • Name: inventario
    • Environment: Python 3
    • Build Command: ./build.sh
    • Start Command: gunicorn inventario.wsgi:application --workers 2 --timeout 120
3

Add PostgreSQL Database

  1. In Render dashboard, click NewPostgreSQL
  2. Create database
  3. Copy the Internal Database URL
  4. Add to your web service as DATABASE_URL environment variable
4

Configure Environment Variables

In web service Environment tab, add:
PYTHON_VERSION=3.11.9
DEBUG=False
SECRET_KEY=<generate-secure-key>
ALLOWED_HOSTS=.onrender.com,yourdomain.com
CSRF_TRUSTED_ORIGINS=https://your-service.onrender.com
DATABASE_URL=<internal-database-url>
5

Deploy

Render automatically builds and deploys:
  1. Runs build.sh
  2. Executes migrations
  3. Collects static files
  4. Starts Gunicorn
Monitor in Logs tab.

Option 3: Traditional Server (Ubuntu)

1

Prepare Server

# Update system
sudo apt update && sudo apt upgrade -y

# Install Python and dependencies
sudo apt install python3.11 python3.11-venv python3-pip postgresql nginx -y
2

Setup PostgreSQL

# Start PostgreSQL
sudo systemctl start postgresql
sudo systemctl enable postgresql

# Create database and user
sudo -u postgres psql
In PostgreSQL shell:
CREATE DATABASE inventario_db;
CREATE USER inventario_user WITH PASSWORD 'secure_password';
ALTER ROLE inventario_user SET client_encoding TO 'utf8';
ALTER ROLE inventario_user SET default_transaction_isolation TO 'read committed';
ALTER ROLE inventario_user SET timezone TO 'America/Bogota';
GRANT ALL PRIVILEGES ON DATABASE inventario_db TO inventario_user;
\q
3

Deploy Application

# Create application directory
sudo mkdir -p /var/www/inventario
cd /var/www/inventario

# Clone repository
sudo git clone <repository-url> .

# Create virtual environment
sudo python3.11 -m venv venv
sudo chown -R $USER:$USER /var/www/inventario
source venv/bin/activate

# Install dependencies
pip install -r requirements.txt
4

Configure Environment

# Create .env file
nano .env
Add production configuration:
DEBUG=False
SECRET_KEY=<generate-secure-key>
ALLOWED_HOSTS=yourdomain.com,www.yourdomain.com
DATABASE_URL=postgresql://inventario_user:secure_password@localhost:5432/inventario_db
CSRF_TRUSTED_ORIGINS=https://yourdomain.com,https://www.yourdomain.com
5

Initialize Database

# Run migrations
python manage.py migrate

# Collect static files
python manage.py collectstatic --no-input

# Create superuser
python manage.py createsuperuser
6

Configure Gunicorn

Create systemd service file:
sudo nano /etc/systemd/system/inventario.service
[Unit]
Description=Inventario Gunicorn Daemon
After=network.target

[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/inventario
EnvironmentFile=/var/www/inventario/.env
ExecStart=/var/www/inventario/venv/bin/gunicorn \
          --workers 3 \
          --bind unix:/var/www/inventario/inventario.sock \
          --timeout 120 \
          inventario.wsgi:application

[Install]
WantedBy=multi-user.target
Enable and start service:
sudo systemctl start inventario
sudo systemctl enable inventario
sudo systemctl status inventario
7

Configure Nginx

Create Nginx configuration:
sudo nano /etc/nginx/sites-available/inventario
server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;
    
    client_max_body_size 10M;
    
    location = /favicon.ico { access_log off; log_not_found off; }
    
    location /static/ {
        alias /var/www/inventario/staticfiles/;
    }
    
    location /media/ {
        alias /var/www/inventario/media/;
    }
    
    location / {
        include proxy_params;
        proxy_pass http://unix:/var/www/inventario/inventario.sock;
    }
}
Enable site:
sudo ln -s /etc/nginx/sites-available/inventario /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
8

Setup SSL with Certbot

# Install Certbot
sudo apt install certbot python3-certbot-nginx -y

# Obtain SSL certificate
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

# Test auto-renewal
sudo certbot renew --dry-run

Static Files Configuration

Inventario uses WhiteNoise for efficient static file serving in production:
# From inventario/settings.py:46,97-101
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware',  # Must be after SecurityMiddleware
    # ... other middleware
]

STATIC_URL = 'static/'
STATICFILES_DIRS = [BASE_DIR / 'static']
STATIC_ROOT = BASE_DIR / 'staticfiles'
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
Benefits:
  • Serves compressed static files (gzip/brotli)
  • Adds far-future cache headers
  • No CDN required for small to medium applications
  • Works seamlessly with Django’s collectstatic
Always run python manage.py collectstatic --no-input before deploying or after modifying static files.

Database Migrations

Inventario uses Django’s built-in migration system:
# Create new migrations after model changes
python manage.py makemigrations

# Apply migrations
python manage.py migrate

# Show migration status
python manage.py showmigrations

# Rollback to specific migration
python manage.py migrate app_name migration_name
Production Best Practices:
  1. Always backup database before running migrations
  2. Test migrations in staging environment first
  3. Migrations run automatically during Railway/Render deployments
  4. For manual deployments, run migrations before restarting application

Health Checks & Monitoring

Application Health

# Check if application is running
curl https://yourdomain.com/login/

# Check admin panel
curl https://yourdomain.com/admin/

Database Connection

# Test database connectivity
python manage.py dbshell

# Or check in Django shell
python manage.py shell
>>> from django.db import connection
>>> connection.ensure_connection()
>>> print("Database connected successfully!")

Common Issues

Symptoms: CSS/JS files return 404 in productionSolution:
# Ensure static files are collected
python manage.py collectstatic --no-input --clear

# Verify STATIC_ROOT directory exists
ls -la staticfiles/

# Check WhiteNoise is in MIDDLEWARE (must be after SecurityMiddleware)
Symptoms: django.db.utils.OperationalError: FATAL: password authentication failedSolution:
  1. Verify DATABASE_URL format is correct
  2. Check database credentials
  3. Ensure database server is running and accessible
  4. For PostgreSQL, verify pg_hba.conf allows connections
# Test PostgreSQL connection
psql $DATABASE_URL
Symptoms: 403 Forbidden on form submissionsSolution:
# Ensure CSRF_TRUSTED_ORIGINS includes your domain
CSRF_TRUSTED_ORIGINS = [
    'https://yourdomain.com',
    'https://www.yourdomain.com',
]

# For Railway: https://*.railway.app
# For Render: https://*.onrender.com
Symptoms: Google login fails with “redirect_uri_mismatch”Solution:
  1. Go to Google Cloud Console
  2. Navigate to APIs & Services → Credentials
  3. Edit your OAuth 2.0 Client
  4. Add authorized redirect URI: https://yourdomain.com/accounts/google/login/callback/
  5. Update Site domain in Django admin:
python manage.py shell
>>> from django.contrib.sites.models import Site
>>> site = Site.objects.get(id=1)
>>> site.domain = 'yourdomain.com'
>>> site.name = 'Inventario'
>>> site.save()
Symptoms: 502 Bad Gateway or worker restart logsSolution: Increase timeout in Procfile or systemd service:
# Procfile
web: gunicorn inventario.wsgi:application --timeout 300 --workers 2

# For long-running reports/exports, increase to 300-600 seconds

Security Checklist

Before going to production, verify:
  • DEBUG=False in production environment
  • Strong SECRET_KEY (min 50 characters)
  • ALLOWED_HOSTS configured correctly
  • CSRF_TRUSTED_ORIGINS includes all domains
  • Database uses strong password
  • SSL/HTTPS enabled (use Certbot for free certificates)
  • SESSION_COOKIE_SECURE=True
  • CSRF_COOKIE_SECURE=True
  • .env file not committed to version control
  • Regular database backups configured
  • Admin account uses strong password

Performance Optimization

Database Connection Pooling

# Already configured in settings.py:79-84
DATABASES = {
    'default': dj_database_url.config(
        default=f'sqlite:///{BASE_DIR / "db.sqlite3"}',
        conn_max_age=600  # Reuse connections for 10 minutes
    )
}

Gunicorn Workers

Calculate optimal worker count:
# Formula: (2 x CPU cores) + 1
# For 1 CPU: 3 workers
# For 2 CPU: 5 workers

gunicorn inventario.wsgi:application --workers 3 --threads 2

Static File Compression

WhiteNoise automatically compresses static files. Verify:
# After collectstatic, check for .gz files
ls -la staticfiles/ | grep \.gz

Backup & Recovery

Database Backup

# Backup PostgreSQL database
pg_dump $DATABASE_URL > backup_$(date +%Y%m%d).sql

# Restore from backup
psql $DATABASE_URL < backup_20260310.sql

Automated Backups (Ubuntu)

# Create backup script
sudo nano /usr/local/bin/backup-inventario.sh
#!/bin/bash
BACKUP_DIR="/var/backups/inventario"
DATE=$(date +%Y%m%d_%H%M%S)

mkdir -p $BACKUP_DIR
pg_dump inventario_db > $BACKUP_DIR/db_$DATE.sql

# Keep only last 7 days
find $BACKUP_DIR -name "db_*.sql" -mtime +7 -delete
# Make executable
sudo chmod +x /usr/local/bin/backup-inventario.sh

# Add to crontab (daily at 2 AM)
sudo crontab -e
0 2 * * * /usr/local/bin/backup-inventario.sh

Updating the Application

1

Pull Latest Changes

cd /var/www/inventario
git pull origin main
2

Activate Virtual Environment

source venv/bin/activate
3

Update Dependencies

pip install -r requirements.txt --upgrade
4

Run Migrations

python manage.py migrate
5

Collect Static Files

python manage.py collectstatic --no-input
6

Restart Application

# Systemd service
sudo systemctl restart inventario

# Or if using supervisor
sudo supervisorctl restart inventario

Support & Resources

Django Documentation

Official Django 5.2 documentation

Railway Docs

Railway deployment guides

Render Docs

Render deployment documentation

Gunicorn Docs

Gunicorn configuration reference

Build docs developers (and LLMs) love