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.