I'm trying to setup a website using a synology with php 5.6 and nginx. The website is WordPress and a theme. When processing a demo import, we have a NGINX error 405 (not allowed).
It's kind of frustrating because I like when things are properly done.
I've looked in the php.ini file and the nginx.conf file.
# Copyright (c) 2000-2016 Synology Inc. All rights reserved.
worker_processes auto;
#worker_cpu_affinity auto;
worker_rlimit_nofile 65535;
include conf.d/main.conf;
events {
use epoll;
multi_accept on;
worker_connections 1024;
include conf.d/events.conf;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log off;
#access_log syslog:server=unix:/dev/log,facility=local7,tag=nginx_access,nohostname main;
error_log syslog:server=unix:/dev/log,facility=local7,tag=nginx_error,nohostname error;
sendfile on;
server_tokens off;
proxy_request_buffering off;
fastcgi_request_buffering off;
scgi_request_buffering off;
proxy_buffering off;
fastcgi_buffering off;
scgi_buffering off;
resolver_timeout 5s;
client_header_timeout 10s;
client_body_timeout 60s;
send_timeout 60s;
keepalive_timeout 65s 20s;
client_max_body_size 0;
server_names_hash_max_size 8192;
ssl_certificate /usr/syno/etc/certificate/system/default/fullchain.pem;
ssl_certificate_key /usr/syno/etc/certificate/system/default/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA;
ssl_dhparam /usr/syno/etc/ssl/dh2048.pem;
ssl_prefer_server_ciphers on;
gzip_disable "msie6";
gzip_min_length 1000;
gzip_types text/plain text/css application/javascript application/json;
gzip_vary on;
gzip_static on;
upstream synoscgi {
server unix:/run/synoscgi.sock;
}
index index.html index.htm index.php;
set_real_ip_from 127.0.0.1;
real_ip_header X-Real-IP;
server {
listen 5000 default_server;
listen [::]:5000 default_server;
server_name _;
gzip on;
include app.d/alias.*.conf;
root /usr/syno/synoman;
index index.cgi;
ignore_invalid_headers off;
include app.d/dsm.*.conf;
include /usr/syno/share/nginx/conf.d/dsm.*.conf;
include conf.d/dsm.*.conf;
location = / {
try_files $uri /index.cgi$is_args$query_string;
}
location ~ ^/volume(?:X|USB|SATA|Gluster)?\d+/ {
internal;
root /;
include app.d/x-accel.*.conf;
include conf.d/x-accel.*.conf;
}
location ~ /webman/modules/(PersonalSettings|ExternalDevices|FileBrowser)/index_ds.php$ {
alias /usr/syno/share/OAuth/index_ds.php;
default_type text/html;
}
location ~ \.cgi {
include scgi_params;
scgi_read_timeout 3600s;
scgi_pass synoscgi;
}
error_page 403 404 500 502 503 504 @error_page;
location @error_page {
root /usr/syno/share/nginx;
rewrite (.*) /error.html break;
}
location ~ ^/webman/modules/Indexer/ {
deny all;
}
location ~ ^/webapi/lib/ {
deny all;
}
location ~ ^/webapi/(:?(:?.*)\.lib|(:?.*)\.api|(:?.*)\.auth|lib.def)$ {
deny all;
}
location ~ /\. { access_log off; log_not_found off; deny all; }
location ~* \.(?:js|css|png|jpg|gif|ico)$ {
access_log off;
log_not_found off;
}
location = /favicon.ico {
access_log off;
log_not_found off;
}
location = /robots.txt {
allow all;
access_log off;
log_not_found off;
}
}
server {
listen 5001 default_server ssl;
listen [::]:5001 default_server ssl;
server_name _;
include app.d/alias.*.conf;
root /usr/syno/synoman;
index index.cgi;
ignore_invalid_headers off;
include app.d/dsm.*.conf;
include /usr/syno/share/nginx/conf.d/dsm.*.conf;
include conf.d/dsm.*.conf;
location = / {
try_files $uri /index.cgi$is_args$query_string;
}
location ~ ^/volume(?:X|USB|SATA|Gluster)?\d+/ {
internal;
root /;
include app.d/x-accel.*.conf;
include conf.d/x-accel.*.conf;
}
location ~ /webman/modules/(PersonalSettings|ExternalDevices|FileBrowser)/index_ds.php$ {
alias /usr/syno/share/OAuth/index_ds.php;
default_type text/html;
}
location ~ \.cgi {
include scgi_params;
scgi_read_timeout 3600s;
scgi_pass synoscgi;
}
error_page 403 404 500 502 503 504 @error_page;
location @error_page {
root /usr/syno/share/nginx;
rewrite (.*) /error.html break;
}
location ~ ^/webman/modules/Indexer/ {
deny all;
}
location ~ ^/webapi/lib/ {
deny all;
}
location ~ ^/webapi/(:?(:?.*)\.lib|(:?.*)\.api|(:?.*)\.auth|lib.def)$ {
deny all;
}
location ~ /\. { access_log off; log_not_found off; deny all; }
location ~* \.(?:js|css|png|jpg|gif|ico)$ {
access_log off;
log_not_found off;
}
location = /favicon.ico {
access_log off;
log_not_found off;
}
location = /robots.txt {
allow all;
access_log off;
log_not_found off;
}
}
server {
listen 80 default_server;
listen [::]:80 default_server;
listen 443 default_server ssl;
listen [::]:443 default_server ssl;
server_name _;
location ~ ^/volume(?:X|USB|SATA|Gluster)?\d+/ {
internal;
root /;
include app.d/x-accel.*.conf;
include conf.d/x-accel.*.conf;
}
include app.d/www.*.conf;
include app.d/alias.*.conf;
include /usr/syno/share/nginx/conf.d/www.*.conf;
include conf.d/www.*.conf;
location = /webman/pingpong.php {
rewrite /webman/pingpong.php /webman/pingpong.cgi break;
root /usr/syno/synoman;
include scgi_params;
scgi_pass synoscgi;
}
location = /webdefault/images/logo.jpg {
alias /usr/syno/share/nginx/logo.jpg;
}
error_page 405 =200 $uri;
location ~* \.php$ {
include fastcgi_params;
fastcgi_index index.php;
fastcgi_read_timeout 240;
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
error_page 403 404 500 502 503 504 @error_page;
location @error_page {
root /usr/syno/share/nginx;
rewrite (.*) /error.html break;
}
location ^~ /.well-known/acme-challenge {
root /var/lib/letsencrypt;
default_type text/plain;
}
include app.d/.location.webstation.conf*;
location ~ ^/$ {
if ($scheme = https) {
rewrite / https://$host:5001/ redirect;
}
rewrite / http://$host:5000/ redirect;
}
}
include conf.d/http.*.conf;
include app.d/server.*.conf;
include sites-enabled/*;
}
I've searched a lot on internet and so far only some interesting leads but nothing worked.
I've tried to add the following to the nginx.conf (that's why my actual nginx.conf has those lines) but it didn't solved my problem.
location ~* \.php$ {
include fastcgi_params;
fastcgi_index index.php;
fastcgi_read_timeout 240;
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
For information, here is the error in log file :
2017/02/10 18:14:07 [error] 18555#18555: *2563 upstream timed out (110: Connection timed out) while reading response header from upstream, client: xxx.xxx.xxx.xxx, server: example.com, request: "POST /wp-admin/admin-ajax.php HTTP/1.1", upstream: "fastcgi://unix:/run/php-fpm/php56-fpm.sock", host: "www.example.com", referrer: http://example.com/wp-admin/admin.php?page=laborator-demo-content-installer&install-pack=agency&
If you have any idea to solve this problem... because I've been struggling since some weeks now... Thanks a lot in advance
tl;dr—Your WordPress is too slow. Jump to the bottom to see how you can make NGINX return you the proper 504 GATEWAY TIMEOUT
status code.
The longer version: You have a bunch of separate issues working together in an unhelpful way.
1. WordPress, your upstream server, is not responding fast enough
It takes longer than 4 minutes, that's why you see a 110: Connection timed out
in your logs. The solution to the slowness is to speed up WordPress. As a workaround, you could give it more time to process the request. To do that, increase the number in your fastcgi_read_timeout 240;
rule. Note that the timeout is given in seconds, so if you're fine with waiting 10 minutes, set this to 600
.
I'd advise against increasing the timeout, though. You should really address the performance issue itself. Such long requests block resources in NGINX and WordPress, and therefore allow you to be DDoSed quite easily, even accidentally by yourself.
Because your upstream takes too long, NGINX would respond with a 504 GATEWAY TIMEOUT
. It cannot because…
2. POST requests cannot be answered with static files
In your error_page
location, you're telling NGINX to use static files to handle the requests. That's fine for GET
or HEAD
, but it does not work for POST
, because it would ask NGINX to overwrite/create files. That's neither intended nor supported by NGINX. (The request would also fail using other modifying verbs such as PUT
and DELETE
, for the same reason.)
Note that you are using a named location, @error_page
, for which the method remains POST, as the manual says:
If there is no need to change URI and method during internal redirection it is possible to pass error processing into a named location.
You already know part of this, which is why you added the error_page 405 =200 $uri;
rule. Unfortunately, this did not save you, because…
3. Internal error_page redirects are not recursive by default
This is not mentioned in the documentation for the error_page
manual, as far as I can see, but it is mentioned in the docs of the following directive:
Workaround: Enable recursive error_page redirects
The directive recursive_error_pages allows you to handle errors that occur while a previous error is being handled. From the docs:
Enables or disables doing several redirects using the error_page directive. The number of such redirects is limited.
If you enable this, by putting recursive_error_pages on;
into your server block, you'll allow the error_page 405
directive to kick in.
Unfortunately, since you're still requesting the same resource with your $uri
part, WordPress will be queried again for the same URL, this time with a GET request. No idea how your WordPress handles that, but chances are the error that will occur then will not help you to debug this.
This really is just jumping around the problem; what you should get is the original 504
. Therefore, I suggest you do the following, instead of enabling recursive error page redirects:
Solution: Use GET
to fetch your error pages
I assume you still want to return your error.html even on a POST request. For that you need to force NGINX to drop the POST
and handle the error with GET
, so that static files can be used. The only way I've found to make this happen is to not use a named location (the ones with @
at the beginning), but an internal one instead.
To use this option, change your @error_page
location to include a pseudo-path and the internal
directive, for example like so:
location /error_page {
internal;
root /usr/syno/share/nginx;
rewrite (.*) /error.html break;
}
Afterwards, modify the error_page
directive, to use the new location:
error_page 403 404 500 502 503 504 /error_page;
Resources: A helpful discussion on the NGINX mailing list.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With