nginx configuration for serving a next.js app

Hi,

I am having some problems configuring nginx to serve content from a next.js server. Specifically, I am getting 404 errors on all .js files, images and any non-html files.

I used to have a very simple configuration using the default configuration files provided by nginx and letting certbot modify my .conf files to add the certificates. These configuration files were very simple and I understood them, but gave me problems with the management of SSL certificates and redirections from www to the non-www version of the domains, so I hired someone to create custom configuration templates for me. They work very well for my static websites, but they are causing problems on those based on a next.js server.

I suppose these templates have elements that I don't need and that they are causing nginx to not find the files. I have been suggested to follow the advice on

https://gist.github.com/iam-hussain/2ecdb934a7362e979e3aa5a92b181153

But, again, this includes items I don't understand, so I am reluctant to use this suggestion. I believe that the problem lies on the included general.conf file (which is listed below).

I would really appreciate some help to finally solve this issue. I have lost already a lot of time trying to understand nginx configuration files. Specially considering that my needs are fairly basic.

Thank you very much in advance.

Here is the full content of my nginx.conf file:

# /etc/nginx/nginx.conf

user                 nginx;
#pid                  /var/run/nginx.pid;
worker_processes     auto;
worker_rlimit_nofile 65535;

# Load modules
events {
    multi_accept       on;
    worker_connections 65535;
}

http {
charset                utf-8;
sendfile               on;
tcp_nopush             on;
tcp_nodelay            on;
server_tokens          off;
log_not_found          off;
types_hash_max_size    2048;
types_hash_bucket_size 64;
client_max_body_size   16M;

# MIME
include                mime.types;
default_type           application/octet-stream;

# Logging
access_log             /var/log/nginx/access.log;
error_log              /var/log/nginx/error.log warn;

# SSL
ssl_session_timeout    1d;
ssl_session_cache      shared:SSL:10m;
ssl_session_tickets    off;

# Diffie-Hellman parameter for DHE ciphersuites
# ssl_dhparam            /etc/nginx/dhparam.pem;

# Mozilla Intermediate configuration
ssl_protocols          TLSv1.2 TLSv1.3;
ssl_ciphers            ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;

# OCSP Stapling
ssl_stapling           on;
ssl_stapling_verify    on;
resolver               1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=60s;
resolver_timeout       2s;

# Load configs
include                /etc/nginx/conf.d.old/*;  # These are the old configuration files. To be removed
include                /etc/nginx/conf.d/*;
}

And here is the template for a next.js based domain:

# /etc/nginx/conf.d/sample.nextjs.conf

server {
listen                  443 ssl http2;
listen                  [::]:443 ssl http2;
server_name             domain.tld;
location                /
   {
        proxy_pass      http://localhost:3050;
   } 

# SSL
ssl_certificate         /etc/letsencrypt/live/domain.tld/fullchain.pem;
ssl_certificate_key     /etc/letsencrypt/live/domain.tld/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/domain.tld/chain.pem;

# security
include                 config/security.conf;

###########################################################
# Contents of config/security.conf
###########################################################

# /etc/nginx/config/security.conf
# security headers
add_header X-XSS-Protection          "1; mode=block" always;
add_header X-Content-Type-Options    "nosniff" always;
add_header Referrer-Policy           "no-referrer-when-downgrade" always;
add_header Content-Security-Policy   "default-src 'self' http: https: ws: wss: data: blob: 'unsafe-inline'; frame-ancestors 'self';" always;
add_header Permissions-Policy        "interest-cohort=()" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

###########################################################

# . files
location ~ /\.(?!well-known) {
    deny all;
}

# logging
access_log              /var/log/nginx/domain.tld.access.log;
error_log               /var/log/nginx/domain.tld.error.log warn;

# additional config
include config/general.conf;

###########################################################
# Contents of config/general.conf
###########################################################

# /etc/nginx/config/general.conf

# 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;
}

# gzip
gzip            on;
gzip_vary       on;
gzip_proxied    any;
gzip_comp_level 6;
gzip_types      text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;

###########################################################     
}

# subdomains redirect
server {
listen                  443 ssl http2;
listen                  [::]:443 ssl http2;
server_name             www.domain.tld;

# SSL
ssl_certificate         /etc/letsencrypt/live/domain.tld/fullchain.pem;
ssl_certificate_key     /etc/letsencrypt/live/domain.tld/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/domain.tld/chain.pem;
return                  301 https://domain.tld$request_uri;
}

# HTTP redirect
server {
listen      80;
listen      [::]:80;
server_name domain.tld;
include     config/letsencrypt.conf;

location / {
    return 301 https://domain.tld$request_uri;
    }
}

1 Reply

Update:

As I suspected, the problem was in the security.conf or general.conf files. I have commented their import and now the server works.

But I would like to restore the parts that make sense, like the headers and the gzip part.

So I am still interested in understanding where is the problem exactly.

Reply

Please enter an answer
Tips:

You can mention users to notify them: @username

You can use Markdown to format your question. For more examples see the Markdown Cheatsheet.

> I’m a blockquote.

I’m a blockquote.

[I'm a link] (https://www.google.com)

I'm a link

**I am bold** I am bold

*I am italicized* I am italicized

Community Code of Conduct