Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

The reliable production fix is to separate static and dynamic traffic: Django collects CSS, JavaScript, images, and admin assets into STATIC_ROOT; Nginx serves that directory directly; Gunicorn handles only application requests. Run collectstatic, make the Nginx URL-to-filesystem mapping exact, grant Nginx read and directory-traverse permission, then test the real asset URL with curl. A 404 usually means collection or path mapping is wrong, while a 403 usually means filesystem permissions are wrong.

Why static files work with runserver but fail behind Gunicorn

Django’s development server is designed to be convenient. With DEBUG enabled, it can locate files in application static directories and, depending on your setup, serve them while it runs the application. That behavior is not the production delivery architecture.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Gunicorn is an application server. It receives requests that reach the Python application, but it should not be responsible for serving every stylesheet, script, image, or admin asset. In production, Nginx should answer requests whose paths begin with your static URL prefix and should pass other requests to Gunicorn. Sending a static request to Gunicorn can produce a 404, add needless application work, or make a configuration mistake harder to see.

The request flow should look like this:

  • The browser requests an address such as /static/css/site.css.
  • Nginx matches location /static/ and looks for the corresponding file in the collected static directory.
  • If the file exists, Nginx returns it without involving Django or Gunicorn.
  • A request that does not match a static file is handled by the application location and proxied to Gunicorn.

This division also explains why changing a template or stylesheet in a development directory does not automatically change production: the file that Nginx serves is the copy in the collected directory, not the source file in an app.

#1 Best Overall
Sale
Compressed Air Duster,130000RPM Super Power Cordless Air Duster,Rechargeable Brushless Blower,3 Gear Adjustable Blower with LED Light,Dust Remover for Computer/House/Outdoor/Car
  • Powerful Turbo Fan:CAGIWIRU Electric Air Duster have reached speed up to 130000RPM,Can efficient remove dust and debris.With LED light and Three Adjustable Speed to meet with different cleaning tasks.
  • With Attached USB C Fasting Charging cable.Charing 3 hours,Enjoy up to 240 minutes of use on the lowest setting, For third speed can use for 25mins.with four charging options to meet with your needs.
  • Wide Application:Upgraded attached 5 different nozzles,making it suitable for a variety of scenes, such as car,pet, pc, keyboards, and other electronic devices. It also serves for office and home clean duster.
  • Handy Design & Portable:Cordless air duster electric nozzle is Light weight and small size, design and comfortable to hold and space saving, convenient to carry around. You can put it in your room or inside the car without taking up space.
  • Warranty & Support: Our Electric air duster comes with 5 years warranty and 24/7 customer service. During this period, if you have any questions,pls kindly feel free to contact us.

Think of the setup as two independent checks. First, Django must produce the right file in one deployment directory. Second, Nginx must translate the public URL to that exact directory. Gunicorn is involved only after those checks fail to match a static location or when the request is genuinely dynamic.

Set Django’s static paths and collect the files

Use settings equivalent to the following. Adjust BASE_DIR to match your project layout.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
STATIC_URL = "/static/"
STATIC_ROOT = BASE_DIR / "staticfiles"
# Optional source directory for project-level assets:
STATICFILES_DIRS = [BASE_DIR / "static"]

STATIC_URL is the URL prefix written into rendered HTML. STATIC_ROOT is the single destination that deployment should expose to Nginx. STATICFILES_DIRS is an optional list of additional source directories; each installed Django app can also contribute a static directory.

Keep the roles separate: STATICFILES_DIRS and app-level static directories are sources, while STATIC_ROOT is an output directory. Pointing Nginx at a source tree can make one developer’s files appear while leaving app or admin files unavailable. Pointing STATIC_ROOT at a directory that also contains source files can make cleanup operations destructive.

Run the collection command

  1. Activate the same virtual environment and configuration used by the deployment.
  2. From the directory containing manage.py, run:
python manage.py collectstatic --noinput

The command gathers files discovered by the enabled static-file finders into STATIC_ROOT. Nginx cannot serve a file that was never copied there, so this step must be part of every deployment that changes assets or installs an app with assets.

Run it after adding an application that supplies static files, upgrading Django (which can change admin assets), or changing a stylesheet or script. If the command reports that no files were copied, that does not prove the public URL is correct; it only means the collection output is already current according to Django’s finder and storage configuration.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Confirm which source file Django selects

If a file is missing or the wrong version appears, ask Django where it finds the name:

python manage.py findstatic css/site.css --verbosity 2

The verbose output lists the searched locations and the selected file. This is especially useful when two apps contain the same relative path: Django’s finder order determines which one is collected. Check the relative name exactly as it appears in the rendered URL; a file called css/Site.css is not the same as css/site.css on a Linux host.

Remove stale files when necessary

Removed applications and renamed assets can leave old files in STATIC_ROOT. To clear files that are no longer provided before collecting the current set, run:

python manage.py collectstatic --clear --noinput

Use this deliberately on a directory that is dedicated to collected assets. Do not point STATIC_ROOT at a directory containing source files you still need. After clearing and recollecting, check both the old and new URLs so a stale HTML reference is not mistaken for an Nginx problem.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #2
EVEO® Screen Cleaner Spray Kit (Streak-Free) TV Screen Cleaner for Smart TV, Lcd, LEd, Oled | Computer Screen Cleaner Spray and Wipe Microfiber Cloth - TV, Monitor, Laptop, iPad, Car - 6.7oz 1 Pack
  • Screen Cleaner is Your Screen’s New Bestfriend! - EVEO is proud to present a screen cleaner that’s perfectly suited for your TV. Meet your new screen cleaner, computer screen cleaner, laptop cleaner, iPad cleaner, Macbook,tv cleaner or any other electronic device. Our screen cleaner spray and wipe along with the included plush microfiber cloth, easily removes dust, fingerprints & other smudges on the screen’s surface. Clean effectively for a streak-free screen
  • Gentle on your Screens - Our screen cleaner spray and wipes is compatible to be used even for the most sensitive LCD, LED, CRT, and OLED screens in proper use. Be at ease knowing that this product is compatible with all the major brands: LG, SONY, Samsung, Sharp, iPad, iPhone, Android screens, Kindle, PC monitors - we’ve got you covered! Can be used as LCD screen cleaner, tv cleaner, smart tv screen cleaner, and more
  • Premium Super Soft Plush Microfiber Cloth - Included in this efficient screen cleaning kit. This screen cleaner spray and wipe has our signature plush microfiber cloth specially designed to comply with screens and monitors and leave them streak-free. Has been shown to effectively absorbs stubborn stains, zero streaks, and no fiber shedding. Always use this together with our screen cleaner for the best results
  • Easy-to-Use Screen Cleaner Kit + microfiber cleaning cloth - The EVEO Screen Cleaning Kit will easily be your new favorite tool when it comes to taking care of the things you love most, quick and easy solution for a streak-free screen. Simply screw on the sprayer gun on the screen cleaner bottle. Spray the cleaning liquid onto the microfiber cloth, then wipe the screen until desired cleanliness & shine is achieved.
  • Quality Screen Care Kit Worth Purchasing - Enjoy a convenient Screen Cleaner anytime, anywhere you need it. Your satisfaction is our top priority. We stand behind the quality of our products and that’s why, you shouldn’t be worrying at all. We manufacture the Best Screen Cleaner. and can be used for laptop cleaning kit, laptop screen cleaner, tv screen cleaner for smart tv. MacBook screen cleaner, monitor cleaner or screen cleaner spray for electronic devices with microfiber cleaning cloth

Map /static/ to the collected directory in Nginx

The most common production error is a mismatch between the URL prefix and the filesystem path. Nginx’s two directives behave differently:

Directive How Nginx builds the path Example for /static/
alias Replaces the matching location prefix with the alias target. location /static/ { alias /srv/myapp/staticfiles/; }
root Appends the complete request URI to the configured directory. root /srv/myapp; resolves /static/css/site.css as /srv/myapp/static/css/site.css.

If the collected directory itself is /srv/myapp/staticfiles/, alias is usually the clearest mapping because the location prefix is replaced directly. Keep the trailing slash on both location /static/ and the alias path. A missing slash can change how path concatenation works and lead to unexpected 404s.

Always calculate one real request by hand before testing. For /static/css/site.css and alias /srv/myapp/staticfiles/, remove /static/ and append css/site.css; the result is /srv/myapp/staticfiles/css/site.css. With root /srv/myapp, append the complete URI and expect /srv/myapp/static/css/site.css. If that calculation does not match the file’s actual location, changing proxy headers will not solve the problem.

Working Nginx configuration with alias

server {
    server_name example.com;

    location /static/ {
        alias /srv/myapp/staticfiles/;
        access_log off;
        expires 7d;
        try_files $uri =404;
    }

    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://unix:/run/gunicorn.sock;
    }
}

With this configuration, a request for /static/css/site.css maps to /srv/myapp/staticfiles/css/site.css. The try_files $uri =404; check makes a missing asset fail at Nginx instead of being silently forwarded to Gunicorn. The cache setting is optional; it does not create a file or correct a path, so troubleshoot collection and mapping first.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Equivalent configuration with root

If your files are arranged under a parent directory as /srv/myapp/static/css/site.css, use the parent as the root:

location /static/ {
    root /srv/myapp;
    try_files $uri =404;
}

Here Nginx appends the entire URI, so /static/css/site.css becomes /srv/myapp/static/css/site.css. Do not use root /srv/myapp/staticfiles; when you expect a request for /static/css/site.css to find /srv/myapp/staticfiles/css/site.css; that root would append /static/ again.

Do not accidentally proxy static requests

Keep the static location separate from the application location. Combining an alias with an unrelated proxy_pass in the same block can hide a path error by sending the request to Gunicorn. If you intentionally design a fallback, make its behavior explicit; otherwise, return a direct 404 for a missing static file.

The same separation applies when you use another prefix. If STATIC_URL is /assets/, change the location to location /assets/ and calculate paths using that prefix. A valid alias under /static/ is irrelevant if the browser is requesting /assets/.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Apply the configuration safely

  1. Validate the configuration that Nginx will load:
sudo nginx -t

Fix every syntax or path-related error before reloading.

  1. Reload the running instance:
sudo systemctl reload nginx

A reload applies configuration without stopping existing connections. If your machine has several Nginx installations or configuration trees, verify which compiled configuration path the running binary uses:

Rank #3
BladeHawks RGB Gaming Mouse Pad Extra Large Extended 31.5x12 Inch-Black
  • 【Large size】:Measuring 800 x 300 mm/ 31. 5×12 inches, which is wider and taller than others. Large mouse pad can perfectly fit your keyboard and mouse of any size, and there is also ample space for peripherals such as phones, tablets, etc.
  • 【LED backlight mouse pad】:Blade Hawks RGB mouse pad provides 7 static modes and 7 dynamic modes will give you the options you are looking for. Power-off memory function remembers the last lighting mode you selected. The super glow fiber Chroma will give you a colorful gaming setup that you want.
  • 【Anti-slip rubber base】:Made from Natural rubber, this gaming mousepad will firmly grip your desktop, allowing you to enjoy the ultimate precision in the games you are most passionate about. It also comes with a texture that enhances this ability even further.
  • 【Smooth and waterproof surface】: Micro-textured cloth surface, for extremely precise mouse control and a smooth movement. When liquid splashes on the gaming mouse pad, it forms water droplets and slides down. Will not delay your work or gameplay.
  • 【Plug and play】: This mouse and keyboard pad is powered by USB, plug and play, no driver required. One button control light modes. Press one time to change the lighting mode, press twice to change the brightness, press and hold about 3 seconds turn ON/OFF.
nginx -V 2>&1 | tr ' ' 'n' | grep -- --conf-path

This catches the common situation where an administrator edits an unused file and then wonders why a valid change has no effect. Test after the reload, not before it, and make the request against the host name that selects the intended server block.

Diagnose a 404 systematically

A 404 means the requested URL did not resolve to a file in the location Nginx is serving, or the request is reaching an application path that has no matching view. Work from the browser’s actual request rather than guessing a filename.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

1. Copy the exact asset URL

Open the rendered page source or browser developer tools and copy the failing URL, for example /static/css/site.css. Check the path, capitalization, and prefix exactly. Linux filesystems are case-sensitive, so Site.css and site.css are different names.

2. Check the collected file

For an alias /srv/myapp/staticfiles/ mapping, the expected file is:

/srv/myapp/staticfiles/css/site.css

If it is absent, rerun collectstatic. If it still does not appear, use findstatic to determine whether Django can discover the source file at all. If Django discovers a different file with the same relative name, inspect finder order and the selected path rather than copying files by hand.

3. Compare both prefixes

The value of STATIC_URL and the Nginx location prefix must describe the same URL space. For example, STATIC_URL = "/assets/" requires a matching location /assets/; a location /static/ block will never match those requests.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

4. Resolve the mapping by hand

  • For alias, replace the location prefix with the alias target.
  • For root, append the complete URI to the root directory.

Write the resulting path down and check it on the server. This simple calculation exposes doubled prefixes, a wrong deployment directory, and missing trailing slashes.

5. Check location precedence and typos

Another server block or a more specific location can shadow the block you edited. Confirm that the request’s host name selects the intended server block and that no regular-expression location captures the same path first. Also check spelling in filenames and directories.

6. Decide whether the 404 came from Nginx or Gunicorn

Watch the access log while requesting one known asset. If the request is logged by the static location and returns 404, focus on collection and filesystem mapping. If it reaches the application proxy, inspect location matching and remove any unintended fallback. This distinction prevents changing Django views when the request should never have reached Django.

Diagnose a 403 or “permission denied” response

A 403 generally means Nginx found the path but its worker process cannot traverse a directory or read the file. Inspect the configured Nginx error log while making one request:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #4
Sale
Vaydeer Wrist Rest for Keyboard and Mouse, Computer Ergonomic Wrist Support Pad, Soft Memory Foam Arm Cushion for Desk, Palm Hand Office Laptop Typing
  • 【Softer and More Comfortable】Vaydeer wrist rest has unique diamond pattern, which is the combination of softness and aesthetics. The materials of wrist rest are improved into higher quality memory foam and covered with silky smooth lycra. The computer wrist rest makes you as comfortable and cushiony as like rest your wrists on clouds.
  • 【Ergonomic Wrist Saver】The wrist rests for keyboard and mouse comes with a 17.32×3.15×0.83 inch keyboard wrist pad and a 5.94×3.15×0.83 inch mouse wrist support. Based on ergonomic design, the unique concave shape is the perfect fit for your wrist joints. The wrist rest pad fits most computer keyboards and laptops, improve hand and wrist posture, release your wrist and arm stress.
  • 【Non-Slip Rubber Bottom】Featuring an anti-skid silicone base on the bottom, this wrist keyboard support stays firmly in place on your desk, preventing the padding from sliding around, ensuring stable and consistent wrist support during extended computer sessions.
  • 【Better Experience & Pain Relief】Our keyboard arm rest is beneficial to alleviate the soreness caused by direct contact and friction between your arm and a hard desk surface, reducing the risk of wrist fatigue or carpal tunnel. The soft texture of memory foam can evenly distribute the pressure around your wrists and provide good support with just enough give.
  • 【Helpful in Multiple Scenarios】Whether you're working, studying, writing, typing, gaming, this keyboard and mouse rest combo is an essential accessory to add comfort and support to your hands and wrists. It’s also a great gift for men, women, family, friend, coworker, gamer, teacher, etc.
tail -f /var/log/nginx/error.log

The log identifies the exact path and often the failing permission check. The Nginx worker user needs:

  • Execute permission on every parent directory leading to the collected tree.
  • Read permission on each static file.
  • Read and execute permission on directories that contain those files.

Grant only the access required for the collected static tree. Do not make the entire project directory world-writable as a shortcut; that creates an unnecessary privilege and tampering risk. If deployment creates files as a different user, set ownership, group membership, or directory modes so the Nginx identity can read the output without exposing secrets, source code, or the virtual environment.

Check the whole path, not just the final file. A readable file still produces a 403 when Nginx cannot execute (traverse) one of its parent directories. Conversely, changing permissions on the project root may expose unrelated settings, source, or credentials; limit access to the collected tree and its required parents.

When HTML loads but CSS or JavaScript does not

Use the browser’s developer tools, open the Network panel, reload the page, and inspect each failed asset request. The status code and requested URL distinguish several causes:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • 404: the file was not collected, the URL prefix is wrong, or Nginx maps the URI to the wrong directory.
  • 403: the file exists but Nginx cannot traverse or read it.
  • Requests go to the wrong host or scheme: a stale template, mixed HTTP/HTTPS URL, or host mismatch is generating an address your server does not serve.
  • An old file is returned: browser or intermediary caching may be serving earlier HTML or assets; verify the response and the filename currently present in STATIC_ROOT.

Inspect the final HTML, not just Django settings. The browser requests exactly what the template rendered. A correct Nginx block cannot fix an HTML tag that points to an obsolete prefix or hostname. If a storage backend creates hashed filenames, compare the name in the HTML with the actual collected name instead of assuming the unhashed source name remains available.

Django admin files and hashed filenames

The admin interface uses static assets supplied by Django. After installing or upgrading Django, run collectstatic again and verify a representative path such as:

/static/admin/css/base.css

If your configured storage backend generates hashed filenames, the names referenced by the rendered HTML must be the names that actually exist in STATIC_ROOT. Do not manually substitute an unhashed filename when the storage backend has produced a hashed one. Check the generated HTML and the collected directory together.

An admin page that renders without styling is therefore useful evidence: dynamic HTML reached Django, but the separate admin CSS request failed. Troubleshoot that request URL and status independently of the login view or Gunicorn socket.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Test delivery from the server’s public URL

Once collection, mapping, and permissions are corrected, test the same URL a visitor uses:

curl -I https://example.com/static/admin/css/base.css
curl -sS https://example.com/static/admin/css/base.css -o /dev/null -w '%{http_code}n'

Interpret the result in context:

Observed status What it normally indicates Next check
200 Nginx delivered the requested asset. Open the page and verify the browser requests the same URL.
404 Collection, URL prefix, location selection, or filesystem mapping is wrong. Check the collected path, STATIC_URL, and root/alias calculation.
403 The path is present but blocked by traversal or read permissions. Read the Nginx error log and inspect the worker identity and directory modes.

Run the request while watching both access and error logs. The access log confirms which server handled the request; the error log explains filesystem failures. A successful curl proves the public delivery path works, but the browser can still request a different URL if the rendered HTML contains a wrong prefix, host, or scheme.

Best Value
Sale
Under Desk Cable Management Tray No Drill, Metal Mesh Cable Management Under Desk with Clamp Mount, 2 Hole Cable Tray with Wire Management and Cord Organizer for Home Office Standing Desk
  • 【No Drill Mounted】Cable management tray can be assembled in as little as 3 minutes or less-simply. Side clips easily clampe the edge of desk, pass through the holes on the sides, and secure excess cables with baskets. Desk cable management supports inward or outward installation to meet your needs in different scenarios, and provides you with great convenience when collecting and organizing wires.
  • 【Rubber Pad Protects Desk】Wire organizer under desk built-in soft rubber pads on the clamp protect your desk from scratches, so you will not damage your furniture or office.
  • 【Sturdy and Beautiful】Cord management under desk is made of high-quality carbon steel and holds about 15 lbs. The wire basket has 2 holes on each side of the tray to enable your cables to pass freely. Cable baskets are suitable for desk thickness use from 0.4" to 2.4".
  • 【Space Saving & Keep Organized】Desk cable management tray holds all your power cords, outlet strips, USB hubs and computer transformers hidden from your feet, and the data cables will not enter the vacuum cleaner to keep your desk clean and tidy. Desk wire organizer is also suitable for use in the kitchen and outdoors.
  • 【Reduce Safety Risks】Cable tray under desk keeps all plugs away from your kids, no more worry about tripping. Using 2 holes wire tray saves extra space, helps you easily cabling and wire protection. The mesh design is not easy to accumulate dust, but avoids safety accidents caused by messy wires.

A deployment checklist that prevents regressions

  • STATIC_URL is the same URL prefix used by the Nginx static location.
  • STATIC_ROOT is a dedicated, known directory on the deployed host.
  • collectstatic --noinput runs after asset changes and dependency installs.
  • findstatic can discover every required project and admin asset.
  • The Nginx mapping uses either a correctly calculated alias or a parent-directory root.
  • Both the static location and an alias target end with the appropriate trailing slash.
  • The static location is not unintentionally proxied to Gunicorn.
  • Nginx’s worker user can traverse parent directories and read collected files.
  • sudo nginx -t passes, and the active instance is reloaded.
  • A direct curl request returns the expected status for a real asset.
  • The access and error logs are checked during one test request.
  • Rendered HTML uses the same, current filenames that exist in the collection directory, including any hashes.

When to use a CDN or object storage instead

Nginx-local delivery is one valid architecture, especially when the application host owns the collected directory. Larger deployments may place collected assets in object storage or behind a CDN instead. The debugging questions remain the same: are assets collected into the expected destination, do rendered URLs point to that destination, and does the serving layer have permission to read them? If a CDN or object store is involved, verify its URL and cache behavior separately from the Gunicorn proxy. Do not add a second Nginx fallback merely to conceal a missing upload or an incorrect prefix.

For a comparison between deployments, examine five things: URL-to-filesystem mapping (root versus alias), whether everything is collected into one STATIC_ROOT, which layer serves files locally or remotely, which identity has read access, and how caching or hashed filenames are handled. Changing serving layers does not remove the need for a deterministic collection step.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Common fixes that do not solve the underlying problem

  • Restarting Gunicorn repeatedly: this cannot create a file missing from STATIC_ROOT or change an Nginx mapping.
  • Adding a wildcard proxy: forwarding every request to the application can make static 404s look like Django routing errors and consumes application workers.
  • Changing permissions on the entire project: this may hide a 403 while exposing source code and secrets; grant access only to the collected tree.
  • Editing a configuration file without checking the active path: nginx -V can reveal that the running binary uses another compiled configuration path.
  • Testing only the home page: HTML can return 200 while every CSS and JavaScript request fails. Test one real asset URL directly.

What the correct final state looks like

Django’s source assets may be spread across project and app directories, but deployment produces one known collection target. Nginx’s static location maps the public prefix to that target and returns a direct 404 when a file is absent. The broader location proxies application requests to the Gunicorn socket with the forwarded host, client IP, forwarding chain, and scheme headers. After a configuration reload, a direct request for an existing asset returns 200, while a missing asset fails clearly instead of consuming an application worker.

Frequently Asked Questions

Why do static files work with runserver but not with Gunicorn?

runserver can serve development static directories when debugging is enabled. Gunicorn is an application server and should not be the static-file server in production. Run collectstatic, let Nginx serve STATIC_ROOT, and proxy only dynamic requests to Gunicorn.

Should I use Nginx root or alias?

Use alias when the location should map directly to the collected directory, such as location /static/ { alias /srv/myapp/staticfiles/; }. Use root when the configured directory is the parent of the URL path, such as root /srv/myapp; for files under /srv/myapp/static/. Calculate one real URL by hand before choosing.

Why does Nginx return 404 for a file that exists?

The file may exist in a source directory but not in STATIC_ROOT, or root/alias may resolve the URL to a different path. Compare the exact browser URL, run findstatic, calculate the filesystem path, and check for a mismatched prefix or shadowing location.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What causes a 403 for /static/?

The Nginx worker usually cannot traverse a parent directory or read the collected file. Inspect the Nginx error log and grant the worker identity the necessary directory execute and file read access without making the whole project world-writable.

How can I tell whether the request is reaching Gunicorn?

Watch the Nginx access log while requesting a known asset. A correctly matched static location should serve the file directly. If the request is proxied, inspect location precedence and remove an unintended proxy_pass fallback from the static block.

Why is the Django admin unstyled after an upgrade?

The admin assets may not have been recollected. Run python manage.py collectstatic --noinput, then request /static/admin/css/base.css directly. If storage generates hashed names, verify that the name in rendered HTML matches the file in STATIC_ROOT.

What should I test after editing Nginx?

Run sudo nginx -t, reload Nginx, confirm the active configuration path with nginx -V if necessary, and test the public asset URL with curl -I. A 200 confirms delivery; 404 points to collection or mapping; 403 points to permissions.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The Bottom Line

Collect the assets into a dedicated STATIC_ROOT, map the exact STATIC_URL prefix to that directory with a correctly calculated alias or root, and keep static requests out of Gunicorn. Then validate and reload Nginx, inspect permissions and logs, and test a real asset URL. This sequence turns an unexplained missing stylesheet into a specific collection, mapping, or access problem.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.