I have an nginx server proxying my express application (which renders ejs files to html), and in trying to load static css/image files it throws a 404 from nginx. This works locally (where I don’t have nginx).
<!-- This is the relevant part of head of my index.ejs file -->
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="/style.css">
<title>Document</title>
</head>
<!-- Additionally, I want to load an image later: -->
<img src="logo.png" class="img-fluid rounded" alt="Image failed to load">
// this is where the directory is registered to be static
app.use(express.static(join(__dirname, "public")));
Below is my file tree structure
public/
style.css
logo.png
views/
index.ejs
index.js
The relevant part of the Nginx config:
server {
listen :443 ssl http2;
listen [::]:443 ssl http2;
server_name cygrind.xyz;
# . files
location ~ /.(?!well-known) {
deny all;
}
# logging
access_log /var/log/nginx/cygrind.xyz.access.log;
error_log /var/log/nginx/cygrind.xyz.error.log warn;
# index.php
index index.php;
# reverse proxy
location / {
proxy_pass http://The IP was here:8080;
proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;
# Proxy headers
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
# Proxy timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# favicon.ico
location = /favicon.ico {
log_not_found off;
access_log off;
}
# robots.txt
location = /robots.txt {
log_not_found off;
access_log off;
}
# assets, media
location ~* .(?:css(.map)?|js(.map)?|jpe?g|png|gif|ico|cur|heic|webp|tiff?|mp3|m4a|aac|ogg|midi?|wav|mp4|mov|webm|mpe?g|avi|ogv|flv|wmv)$ {
expires 7d;
access_log off;
}
# svg, fonts
location ~* .(?:svgz?|ttf|ttc|otf|eot|woff2?)$ {
add_header Access-Control-Allow-Origin "*";
expires 7d;
access_log off;
}
}
The full nginx config file can be found here (please ignore any syntax errors regarding curly braces)
You can find the site here to view the dev console if need be
Thanks in advance!
2
Answers
Make sure you have this command: app.use(express.static(‘public’));
Also, make sure that your view engine is set properly in your main express file.
Express will look in the views folder that should be set at the root level of your project.
I would assume for your question it has to be with Nginx config file.
May I ask why are you using nginx? for production deploy for simple nodejs apps, I use PM2 for running the app and Docker for containerization.
Your issue is that you have location blocks for various assets (css, favicon, etc.) to turn off logging, but they don’t do anything else, the request just ends there, so Nginx returns a 404. You can see that it’s not even hitting Express by looking for the
x-powered-by
header (from your Express app, it’s coming back asExpress
; from the styles, favicon, etc. routes, that response header isn’t there).Location blocks don’t get combined. (See the section "When Does Location Block Evaluation Jump to Other Locations?" here for situations exceptions.)
For each of your more specific location blocks, you’ll need to add the same proxy-related directives. You could also nest them under the
location /
which might cut down in the copy-pasting a little bit, but request handlers aren’t inherited from parent location blocks, so you will still have some duplication there.