I have a WordPress site (in /var/www/html/
path) with an nginx server, now I want a specific page to be in nextjs (in /var/www/html/
path) by proxy, for port 3000.
I’m requesting, example.com/specific-next-page
The page does load, but all static files (js/css) are not found (404). for example:
GET https://example.com/_next/static/css/1ca183f3cca214b7.css net::ERR_ABORTED 404
This is what I see in nginx logs.
2022/06/10 14:47:25 [error] 3015605#3015605: *10 open() "/var/www/html/_next/static/BA1dIGPMYI7hn430ayZ2f/_buildManifest.js" failed (2: No such file or directory), client: 172.70.200.XXX, server: example.com, request: "GET /_next/static/BA1dIGPMYI7hn430ayZ2f/_buildManifest.js HTTP/2.0", host: "example.com", referrer: "https://example.com/specific-next-page"
I understand that the problem is that nginx is looking for the files in the /var/www/html
folder which is the WordPress folder, and nextjs is in /var/www/next
That is, the correct path for the static files is /var/www/next/.next/static
I really tried a lot of options and I failed.
This is my nginx config file.
upstream php-handler-https {
server 127.0.0.1:9000;
}
server {
listen 443 ssl http2 ;
listen [::]:443 ssl ;
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
root /var/www/html/;
index index.php;
client_max_body_size 2G;
fastcgi_buffers 64 4K;
access_log /var/log/nginx/wordpress_https_access.log combined;
error_log /var/log/nginx/wordpress_https_error.log;
server_tokens off;
location = /favicon.ico {
log_not_found off;
access_log off;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
# NEXT PROXY
location /__nextjs_original-stack-frame {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /content {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
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;
}
location /_next {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
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;
}
# specific-page - next.js
location /specific-next-page {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
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;
}
# END NEXT
location / {
try_files $uri $uri/ /index.php?$args ;
}
# protected area (XHProf)
location ^~ /xhprof/xhprof_html/ {
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/htpasswd/xhprof;
location ~ .php(?:$|/) {
fastcgi_split_path_info ^(.+.php)(/.+)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PHP_FLAG "session.auto_start=off n mbstring.encoding_translation=off";
fastcgi_param PHP_VALUE "assert.active=0 n mbstring.http_input=pass n mbstring.http_output=pass";
fastcgi_pass php-handler-http ;
fastcgi_read_timeout 60s;
}
}
# protected area (phpmyadmin)
location ^~ /mysqladmin/ {
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/htpasswd/phpmyadmin;
location ~ .php(?:$|/) {
fastcgi_split_path_info ^(.+.php)(/.+)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PHP_FLAG "session.auto_start=off n mbstring.encoding_translation=off";
fastcgi_param PHP_VALUE "assert.active=0 n mbstring.http_input=pass n mbstring.http_output=pass";
fastcgi_pass php-handler-http ;
fastcgi_read_timeout 60s;
}
}
location ^~ /wp-admin/install.php {
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/htpasswd/wpadmin;
location ~* .(htaccess|htpasswd) {
deny all;
}
location ~ .php(?:$|/) {
fastcgi_split_path_info ^(.+.php)(/.+)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param HTTPS on;
fastcgi_param PHP_VALUE "auto_prepend_file=/var/www/html/xhprof/external/header.php";
fastcgi_pass php-handler-https;
fastcgi_read_timeout 60s;
}
}
location ~* .(htaccess|htpasswd) {
deny all;
}
location ~* .(?:ini|conf|txt)$ {
deny all;
}
location ~ .php(?:$|/) {
fastcgi_split_path_info ^(.+.php)(/.+)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param HTTPS on;
fastcgi_param PHP_VALUE "auto_prepend_file=/var/www/html/xhprof/external/header.php";
fastcgi_pass php-handler-https;
fastcgi_read_timeout 60s;
}
# set long EXPIRES header on static assets
location ~* .(?:jpg|jpeg|gif|bmp|ico|png|css|js|swf)$ {
expires 30d;
access_log off;
}
}
2
Answers
If
/var/www/html
is the root of your web server, clients are not being served files from/var/www/next
. The.next
folder must be in a place served by nginx and available publicly to clients.I suggest putting
.next
under/var/www/html
Do you understand how nginx select a location for handling the request? Do you understand location priorities according to used modifier? Did you read
location
directive documentation at all? You already use the^~
location modifier in you configuration. Do you understand what does it mean and how is it work?Because of your regex
location ~* .(?:jpg|jpeg|gif|bmp|ico|png|css|js|swf)$ { ... }
none of any requests for these file types will ever be handled by any prefix location without the^~
modifier (well, at least until there will be another regex location inside the longest prefix one). The minimal fix for your configuration will be at least to use the^~
modifier for the/_next
prefix location:However serving static files by nginx itself without proxying that requests to the app will be much more effective. To do it you can use the following location:
Generally, using any additional regex location that can be avoided is a performance penalty since it (most probably, if the request won’t be captured by another prefix location with
^~
modifier or regex location before) will eliminate an expensive PCRE library call to perform a match against the regex pattern. These two locations:can be easily combined into the single one:
and if disabling assets requests logging is not essential for you, this one:
can be replaced with somewhat bigger yet much more effective configuration to adding cache policy according to the
Content-Type
HTTP response header (according to the default MIME types being used by nginx 1.21):Moreover, this way you will be able to easily add the same cache policy to your
Next.js
app, if needed (using the^~
modifier won’t be necessary anymore):I described this method much more comprehensively here.
About the following lines in your configuration:
These are used for the WebSocket protocol proxying and can break your app under some circumstances if WebSocket is not being used. I’m really doubt you need those lines for every
Next.js
related location. Read more technical details here.