In development Django serves static files for you, but in production you must configure this properly — getting it wrong causes missing CSS and broken uploads. Here's the correct setup.
Static vs media
- Static files — your CSS, JS and images that ship with the app.
- Media files — user uploads.
Settings
STATIC_URL = "/static/"
STATIC_ROOT = "/var/www/myapp/staticfiles"
MEDIA_URL = "/media/"
MEDIA_ROOT = "/var/www/myapp/media"
Collect static files
python manage.py collectstatic --noinput
This gathers all static files into STATIC_ROOT so Nginx can serve them.
Serve them with Nginx
location /static/ { alias /var/www/myapp/staticfiles/; }
location /media/ { alias /var/www/myapp/media/; }
Now Nginx serves assets directly — fast, and it takes load off Gunicorn. Re-run collectstatic on every deploy. For media, ensure the upload directory is writable by your app's user and consider access controls for private files.