Page loads but assets return 404

Hello everyone,

I’ve tried to install Ghost last night on one of my machines. Except for the part where it won’t detect Nginx because I have it built, not installed (so dpkg won’t return anything) everything went just fine.

After configuration of Nginx, the website is accessible but won’t load any local assets for some reason, throwing 404 on them, so the website is not styled and throws JavaScript errors. But routing works because I can click and read the default articles.

Then I’ve started another machine, installed Nginx there through aptitude, went through the same setup process and Ghost seem to work just fine there. Yet the only difference I could find is the absence of Nginx .conf file in system/files and the fact that my Nginx configuration is a bit different from the template (but includes everything from the template based on the config generated on the other machine.

There were no failures in the installation process. The only difference was the Nginx configuration but that is something I wouldn’t expect to have an effect considering the main config is the same.

I’ve searched the forums but while people had this issue before, it has been with older version and I couldn’t find a solution there or in documentation.

Node: 8.12.0
active-version: 2.2.0
cli-version: 1.9.6

Please, if you have the time to spare to help me out, don’t hesitate to ask whatever debugging info needed :slight_smile: I’ll be happy to provide it.

Could you post your current (redacted if required) nginx config?

I sure can. And I’m also adding two of the included files so you have a full picture.

sites/example.com.conf

## Redirect HTTP to HTTPS
#########################
server {
  listen 80;
  listen [::]:80;
  server_name example.com www.example.com;
  return 301 https://example.com$request_uri;
}

## Redirect www to non-www
#########################
server {
  server_name www.example.com;
  include conf/ssl.conf;
  ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
  ssl_trusted_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
  return 301 https://example.com$request_uri;
}

## Main configuration
#########################
server {
  ## Basic configuration
  server_name example.com;
  root /var/www/example.com/ghost/system/nginx-root;
  client_max_body_size 50m;

  ## Logs
  error_log /var/www/example.com/ghost/.log/nginx/error.log;
  access_log /var/www/example.com/ghost/.log/nginx/access.log;

  ## SSL
  ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
  ssl_trusted_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
  include conf/ssl.conf;

  ## Cache
  include conf/cache.conf;

  ## Security
  server_tokens off;
  add_header X-Frame-Options SAMEORIGIN;
  add_header X-Xss-Protection "1; mode=block";
  add_header X-Content-Type-Options nosniff;
  add_header Referrer-Policy "origin";

  ## Let's Encrypt
  location ^~ /.well-known {
    allow all;
  }

  ## And now for something completely different
  location / {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $http_host;
    proxy_pass http://127.0.0.1:2368;
  }
}

conf/ssl.conf

## Listen on 443 only
listen 443 ssl;
listen [::]:443 ssl;

## Turn off support for old, broken and insecure shit
ssl_protocols TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA$
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 180m;
ssl_session_tickets off;
ssl_ecdh_curve secp384r1:secp256k1;
ssl_dhparam /etc/ssl/dhparams.pem;

## HSTS (6 months)
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload";

## OCSP
ssl_stapling on;
ssl_stapling_verify on;

## Resolver
resolver 8.8.8.8 8.8.4.4 [2001:4860:4860::8844] [2001:4860:4860::8888] valid=86400s;
resolver_timeout 5s;

conf/cache.conf

## Cache control for most common cases
######################################

# Some files we do not wish to cache
location ~* \.(?:manifest|xml|json)$ {
  expires -1;
}

# Feed
location ~* \.(?:rss|atom)$ {
  expires 1h;
  add_header Cache-Control "public";
}

# Media
location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
  expires 1M;
  access_log off;
  add_header Cache-Control "public";
}

# CSS and JavaScript
location ~* \.(?:css|js)$ {
  expires 1M;
  access_log off;
  add_header Cache-Control "public";
}

Out of a frustration, I’ve just tried to simplify it to the bone. And found the culprit! It was indeed the Nginx configuration.

location ~* \.(?:css|js)$ {
    expires 1M;
    access_log off;
    add_header Cache-Control "public";
}

This is causing the problem. When removed, the page works. When returned, it crashes again. So, maybe it’s going to save the time to someone else in the future.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.