Deploy Django on VPSGrid
You provision database, web server, TLS, backups, and security updates on VPSGrid Linux VPS. VPSGrid infrastructure is — application operations remain yours.
- Python venv + Django project
- PostgreSQL or MariaDB
- Gunicorn + systemd
- Nginx static/media + proxy
- collectstatic & migrate
- ALLOWED_HOSTS + HTTPS
Overview
This guide covers the steps and checks you need on an unmanaged VPSGrid VPS. Guest OS configuration remains your responsibility unless a separate managed product is documented on your account.
VPSGrid provides unmanaged KVM VPS hosting. You are responsible for backups, OS configuration, application data, and guest-level security. VPSGrid manages hypervisor infrastructure, network connectivity, power controls, and billing. Review What Is an Unmanaged VPS at VPSGrid? and Security Responsibilities on Unmanaged VPS before relying on support for guest OS tasks.
Hosted on US-Based KVM infrastructure using NVMe storage.
VPSGrid operates from its US-Based infrastructure datacenter while serving customers across the United States. Plans run on KVM virtual servers on Proxmox VE with NVMe storage. Plan sizes and current pricing appear at checkout on vpsgrid.net — knowledgebase articles do not publish fixed dollar amounts because promotions and tiers change.
Plan Django on VPSGrid
Django needs WSGI server (Gunicorn), database, static file serving, and secret key management. Size RAM for Gunicorn workers plus database buffers — compare plans at vpsgrid.net checkout.
System packages
sudo apt-get update\nsudo apt-get install -y python3-venv python3-pip nginx postgresql postgresql-contrib libpq-devProject setup
sudo mkdir -p /var/www/djangoapp\ncd /var/www/djangoapp\npython3 -m venv venv\nsource venv/bin/activate\npip install django gunicorn psycopg2-binary\ndjango-admin startproject myproject .Database configuration
sudo -u postgres createuser django_user
sudo -u postgres createdb django_db -O django_user
sudo -u postgres psql -c "ALTER USER django_user PASSWORD 'STRONG_PASSWORD';"Update settings.py or split settings module with DATABASES pointing at localhost PostgreSQL. Load SECRET_KEY from environment — never commit secrets.
Gunicorn systemd unit
[Unit]\nDescription=Gunicorn Django\nAfter=network.target\n\n[Service]\nUser=www-data\nGroup=www-data\nWorkingDirectory=/var/www/djangoapp\nEnvironmentFile=/var/www/djangoapp/.env\nExecStart=/var/www/djangoapp/venv/bin/gunicorn --workers 3 --bind 127.0.0.1:8000 myproject.wsgi:application\n\n[Install]\nWantedBy=multi-user.targetStatic and media files
python manage.py collectstatic --noinputNginx configuration
server {\n listen 80;\n server_name django.example.com;\n\n location /static/ {\n alias /var/www/djangoapp/static/;\n }\n\n location /media/ {\n alias /var/www/djangoapp/media/;\n }\n\n location / {\n proxy_pass http://127.0.0.1:8000;\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-Forwarded-Proto $scheme;\n }\n}Deploy workflow
git pull\nsource venv/bin/activate\npip install -r requirements.txt\npython manage.py migrate\npython manage.py collectstatic --noinput\nsudo systemctl restart gunicorn-djangoDatabase migrations can be irreversible — backup per Backup Best Practices for VPS Owners before major schema changes.
Production settings
DEBUG=FalseALLOWED_HOSTSlists your domainCSRF_TRUSTED_ORIGINSincludes https URL- Secure cookies behind HTTPS
Firewall and TLS
How to Configure UFW Firewall on Ubuntu/Debian then Let's Encrypt SSL with Certbot on VPSGrid.
Troubleshooting Django on VPS
| Issue | Cause | Fix |
|---|---|---|
| DisallowedHost | ALLOWED_HOSTS | Add domain to settings |
| Static 404 | collectstatic not run | Run collectstatic; check alias paths |
| 502 | Gunicorn crash | journalctl; see Fix 502 Bad Gateway on VPSGrid Nginx/Apache |
| Migration error | Schema drift | Restore backup; fix migration files |
| High memory | Too many workers | Reduce workers; upgrade VPS |
Monitoring and scale
Watch RAM/CPU with High CPU and RAM Usage on Your VPSGrid VPS. Upgrade at Linux VPS store. Flask alternative: Deploy Flask on VPSGrid with Gunicorn and Nginx.
Support scope
VPSGrid support assists with VPS infrastructure per Security Responsibilities on Unmanaged VPS — not Django application debugging on unmanaged plans. Open tickets with service ID for network or hypervisor issues.
MariaDB alternative to PostgreSQL
Some teams prefer MariaDB for Django using the mysqlclient driver. Install python3-mysqldb or pip package, create database and user mirroring PostgreSQL steps, and set ENGINE to django.db.backends.mysql with utf8mb4 charset. Test migrations on staging — MySQL-specific field types may differ from PostgreSQL JSON support.
Logging and observability
Configure Django LOGGING to write errors to stderr consumed by journald:
journalctl -u gunicorn-django -fCorrelate timestamps with Nginx access logs during incident response. External uptime monitors hitting HTTPS endpoints alert you before customers report outages.
Django admin hardening
Change default /admin/ URL via custom AdminSite if desired, enforce staff MFA through django-otp or similar, and restrict admin access by IP in Nginx location blocks during early production phases. Never expose DEBUG toolbar publicly.
Static CDN (optional)
Serve collected static files from Nginx on same VPS for simplicity. External CDN offloads bandwidth but adds DNS complexity — evaluate after baseline Nginx static serving performs adequately on VPSGrid US-Based connectivity.
Python WSGI/ASGI deployment patterns
Flask and Django on VPSGrid run behind Gunicorn (WSGI) or Uvicorn/Hypercorn (ASGI) with Nginx terminating TLS. You manage virtual environments, dependency pins (requirements.txt or Poetry lockfiles), static file collection, and database migrations — VPSGrid does not provide PaaS-style deploy buttons on unmanaged Linux VPS.
Virtual environments
Create per-app venv under /var/www/app/venv owned by the deploy user. Never install production packages globally with pip as root unless using distribution packages intentionally. Activate venv in systemd unit ExecStart paths.
Static and media files
Django requires collectstatic before serving via Nginx whitenoise or direct alias. User uploads belong in MEDIA_ROOT with backup plans — media is not recreated by git deploy. Flask static folders follow similar Nginx alias patterns.
Database migrations
Run python manage.py migrate (Django) or Alembic upgrades (Flask-SQLAlchemy) during deploy windows after backups. Failed migrations mid-transaction need DBA attention — test on staging VPS clones first.
systemd hardening
Run Gunicorn as non-root with ProtectSystem=strict, NoNewPrivileges=yes, and explicit WorkingDirectory. Cap LimitNOFILE for busy APIs. Restart policies Restart=always recover from memory leaks but mask application bugs — monitor restart counts.
Secrets and settings modules
Split settings: settings/base.py plus environment-specific overrides loaded from env vars. Never set DEBUG=True in production — exposes stack traces and enables dangerous management endpoints.
Scaling beyond one VPS
Single VPSGrid instances suit many small APIs. Horizontal scaling across multiple VPS nodes requires external load balancing and shared session storage — outside default unmanaged scope unless you architect it.
pip-audit and supply chain
Run pip-audit or similar on requirements.txt periodically — Python dependencies on public VPS need patch cadence like OS packages.
Celery workers (optional)
Background tasks may need separate Celery systemd units — ensure Redis/RabbitMQ persistence and backup if queues hold financial data.
WSGI vs ASGI
Django 4+ async views may benefit from ASGI (Uvicorn) — evaluate separately from this Gunicorn WSGI baseline.
Database connection pooling
Configure CONN_MAX_AGE in Django database settings for persistent connections under Gunicorn — balance against PostgreSQL max_connections on small VPS plans.
Logging to journald
Route Django LOGGING to stdout for systemd journal capture — simplifies correlation with Gunicorn and Nginx errors during 502 investigations.
requirements.txt pinning
Pin exact versions in production requirements — reproducible deploys on VPSGrid NVMe reduce surprise breakages after pip install -r.
pip-audit and supply chain
Run pip-audit or similar on requirements.txt periodically — Python dependencies on public VPS need patch cadence like OS packages.
Celery workers (optional)
Background tasks may need separate Celery systemd units — ensure Redis/RabbitMQ persistence and backup if queues hold financial data.
WSGI vs ASGI
Django 4+ async views may benefit from ASGI (Uvicorn) — evaluate separately from this Gunicorn WSGI baseline.
Database connection pooling
Configure CONN_MAX_AGE in Django database settings for persistent connections under Gunicorn — balance against PostgreSQL max_connections on small VPS plans.
Logging to journald
Route Django LOGGING to stdout for systemd journal capture — simplifies correlation with Gunicorn and Nginx errors during 502 investigations.
requirements.txt pinning
Pin exact versions in production requirements — reproducible deploys on VPSGrid NVMe reduce surprise breakages after pip install -r.
pip-audit and supply chain
Run pip-audit or similar on requirements.txt periodically — Python dependencies on public VPS need patch cadence like OS packages.
Celery workers (optional)
Background tasks may need separate Celery systemd units — ensure Redis/RabbitMQ persistence and backup if queues hold financial data.
WSGI vs ASGI
Django 4+ async views may benefit from ASGI (Uvicorn) — evaluate separately from this Gunicorn WSGI baseline.
Database connection pooling
Configure CONN_MAX_AGE in Django database settings for persistent connections under Gunicorn — balance against PostgreSQL max_connections on small VPS plans.
Logging to journald
Route Django LOGGING to stdout for systemd journal capture — simplifies correlation with Gunicorn and Nginx errors during 502 investigations.
requirements.txt pinning
Pin exact versions in production requirements — reproducible deploys on VPSGrid NVMe reduce surprise breakages after pip install -r.
pip-audit and supply chain
Run pip-audit or similar on requirements.txt periodically — Python dependencies on public VPS need patch cadence like OS packages.
Celery workers (optional)
Background tasks may need separate Celery systemd units — ensure Redis/RabbitMQ persistence and backup if queues hold financial data.
WSGI vs ASGI
Django 4+ async views may benefit from ASGI (Uvicorn) — evaluate separately from this Gunicorn WSGI baseline.
Database connection pooling
Configure CONN_MAX_AGE in Django database settings for persistent connections under Gunicorn — balance against PostgreSQL max_connections on small VPS plans.
Logging to journald
Route Django LOGGING to stdout for systemd journal capture — simplifies correlation with Gunicorn and Nginx errors during 502 investigations.
requirements.txt pinning
Pin exact versions in production requirements — reproducible deploys on VPSGrid NVMe reduce surprise breakages after pip install -r.
pip-audit and supply chain
Run pip-audit or similar on requirements.txt periodically — Python dependencies on public VPS need patch cadence like OS packages.
Celery workers (optional)
Background tasks may need separate Celery systemd units — ensure Redis/RabbitMQ persistence and backup if queues hold financial data.
WSGI vs ASGI
Django 4+ async views may benefit from ASGI (Uvicorn) — evaluate separately from this Gunicorn WSGI baseline.
Database connection pooling
Configure CONN_MAX_AGE in Django database settings for persistent connections under Gunicorn — balance against PostgreSQL max_connections on small VPS plans.
Logging to journald
Route Django LOGGING to stdout for systemd journal capture — simplifies correlation with Gunicorn and Nginx errors during 502 investigations.
requirements.txt pinning
Pin exact versions in production requirements — reproducible deploys on VPSGrid NVMe reduce surprise breakages after pip install -r.
pip-audit and supply chain
Run pip-audit or similar on requirements.txt periodically — Python dependencies on public VPS need patch cadence like OS packages.
Celery workers (optional)
Background tasks may need separate Celery systemd units — ensure Redis/RabbitMQ persistence and backup if queues hold financial data.
WSGI vs ASGI
Django 4+ async views may benefit from ASGI (Uvicorn) — evaluate separately from this Gunicorn WSGI baseline.
Database connection pooling
Configure CONN_MAX_AGE in Django database settings for persistent connections under Gunicorn — balance against PostgreSQL max_connections on small VPS plans.
Logging to journald
Route Django LOGGING to stdout for systemd journal capture — simplifies correlation with Gunicorn and Nginx errors during 502 investigations.
requirements.txt pinning
Pin exact versions in production requirements — reproducible deploys on VPSGrid NVMe reduce surprise breakages after pip install -r.
pip-audit and supply chain
Run pip-audit or similar on requirements.txt periodically — Python dependencies on public VPS need patch cadence like OS packages.
Celery workers (optional)
Background tasks may need separate Celery systemd units — ensure Redis/RabbitMQ persistence and backup if queues hold financial data.
WSGI vs ASGI
Django 4+ async views may benefit from ASGI (Uvicorn) — evaluate separately from this Gunicorn WSGI baseline.
Django deployment checklist: Django deployment checklist.
Frequently Asked Questions
Which database for Django on VPSGrid?
PostgreSQL or MariaDB both work — install in the guest OS you manage. SQLite suits development only, not concurrent production traffic.
Where does DEBUG belong?
Set DEBUG=False in production settings loaded from environment variables. DEBUG exposes sensitive error pages publicly.
Does VPSGrid run migrations for me?
No — run python manage.py migrate during your deploy process on unmanaged VPS.
How do I serve user uploads?
Configure MEDIA_ROOT and Nginx alias — back up media separately from code deploys.
Related Articles
Next steps on VPSGrid
Ready to deploy your app on an unmanaged VPS? A VPSGrid Linux VPS gives you root access and a clean environment for Node.js, Flask, Django, Nginx, and related tools you install and maintain.
Need More Help?
Search this knowledgebase for related guides. If the issue persists, open a ticket at billing.vpsgrid.net with your service ID, primary IP, and steps already tried. See What Information to Include in a Support Request and Security Responsibilities on Unmanaged VPS for scope and required details.
Was this answer helpful?