0

I have a config like this for my Nginx server:

server {
  listen 80;
  listen 443 ssl;

  ssl_certificate /etc/nginx/cert/domain.csr;
  ssl_certificate_key /etc/nginx/cert/domain.key;

  server_name ~^(\w+)\.(\w+)$ ;

  location / {
    rewrite ^\/(.*) /$1 break;
    proxy_pass https://my-app.ondigitalocean.app/ ;
  }

  error_page 500 502 503 504 /50x.html;
  location = /50x.html {
    root  /usr/share/nginx/html;
  }

  error_page 444 =200 @unavailable.html;
  location = @unavailable.html {
    #root   /usr/share/nginx/html;
    proxy_pass https://myapp.ondigitalocean.app/unavailable.html;
    allow all;
  }

  if ($allowed_country = no) {
    return 444;
  }
}

It works fine, but I can't get unavailable.html page I allocated at the remote server (see proxy_pass), my error log shows:

 [error] 20#20: *1 could not find named location "@unavailable.html", client: 172.17.0.1, server: ~^(\w+)\.(\w+)$

What I'm missing? Is it even possible? Or I have to copy-paste such page to Nginx home?

anx
  • 8,963
  • 5
  • 24
  • 48
M_F
  • 101
  • But should this error_page 444 =200 change it back to 200? Besided I've checked it with 403 error code result the same I cant see the page – M_F Nov 09 '20 at 20:10
  • Why not I want to send my own custom page this has nothing to do with laws. So I need a body with 200 at the end just one custom page for the blocked countries. So the question isn't about HTTP error code because with different code I have also no page – M_F Nov 09 '20 at 20:26
  • I edited your comment below into your question - thank you for providing the error, now it is much clearer where exactly you are stuck. I think my updated question should now get you at least one step towards a working configuration. – anx Nov 12 '20 at 11:17

1 Answers1

1

You can not use the = equals prefix in named locations (indicated by the @ at sign). Those are always exact matches anyway - and are not prefixed like regular URIs, as shown in the two distinct syntax descriptions for location:

location [ = | ~ | ~* | ^~ ] uri { ... }
location @name { ... }

You can then force the path passed to your upstream to be the one you want:

location @unavailable.html {
  rewrite ^ /unavailable.html break;
  proxy_pass https://myapp.ondigitalocean.app;
}

The Nginx docs actually recommend not putting the URI into the proxy_pass directive here; emphasis mine:

In some cases, the part of a request URI to be replaced cannot be determined: When location is specified using a regular expression, and also inside named locations. In these cases, proxy_pass should be specified without a URI.

Side note: You should not use return 444 unless you want the special behaviour Nginx assigns to that value. You should also not return a status code 200 unless you successfully return the requested resource.

If you have made the resource unavailable for your sites visitor based on the country you suspect him browsing from, return a code specific to the reason you made that so (typically 403 Forbidden or 451 Unavailable For Legal Reasons))

anx
  • 8,963
  • 5
  • 24
  • 48
  • But how it should work with IF section? – M_F Nov 12 '20 at 07:54
  • Actually I've got this ``` [error] 20#20: *1 could not find named location "@unavailable.html", client: 172.17.0.1, server: ~^(\w+)\.(\w+)$, – M_F Nov 12 '20 at 09:07
  • Oh just remove that extra `=` equals sign (just `location @unavailable.html`), you actually want a *named location* as nginx already guessed from you using the `@` at sign in the `error_page` – anx Nov 12 '20 at 11:05
  • actually @ never works for location section I have error. ginx: [emerg] "proxy_pass" cannot have URI part in location given by regular expression, or inside named location, or inside "if" statement, or inside "limit_except" block i – M_F Nov 13 '20 at 21:39
  • actually it doesnt matter about location. All I want show specific error page if IP is blocked. – M_F Nov 15 '20 at 11:44