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.