3

I'm trying to setup nginx to return a 503 if a particular file exists (probably something like "upgrading"). I'm trying to use the try_files directive, but when it finds the /upgrading.html file, it serves it rather than following the directive. Why is that?

location / {
    try_files /upgrading.html @keepgoing;
}

location = /upgrading.html {
    return 503;
}

location @keepgoing {
    #do stuff here to do whatever I would normally do...
}

In the log when I turn on debugging I see the following:

3388    2010/07/01 19:44:21 [debug] 76327#0: *8 test location: "/"
3389    2010/07/01 19:44:21 [debug] 76327#0: *8 using configuration "/"
3390    2010/07/01 19:44:21 [debug] 76327#0: *8 http cl:-1 max:52428800
3391    2010/07/01 19:44:21 [debug] 76327#0: *8 generic phase: 2
3392    2010/07/01 19:44:21 [debug] 76327#0: *8 post rewrite phase: 3
3393    2010/07/01 19:44:21 [debug] 76327#0: *8 generic phase: 4
3394    2010/07/01 19:44:21 [debug] 76327#0: *8 generic phase: 5
3395    2010/07/01 19:44:21 [debug] 76327#0: *8 access phase: 6
3396    2010/07/01 19:44:21 [debug] 76327#0: *8 access phase: 7
3397    2010/07/01 19:44:21 [debug] 76327#0: *8 post access phase: 8
3398    2010/07/01 19:44:21 [debug] 76327#0: *8 try files phase: 9
3399    2010/07/01 19:44:21 [debug] 76327#0: *8 try to use file: "/upgrading.html" "/usr/local/nginx/html/upgrading.html"
3400    2010/07/01 19:44:21 [debug] 76327#0: *8 try file uri: "/upgrading.html"
3401    2010/07/01 19:44:21 [debug] 76327#0: *8 content phase: 10
3402    2010/07/01 19:44:21 [debug] 76327#0: *8 content phase: 11
3403    2010/07/01 19:44:21 [debug] 76327#0: *8 content phase: 12
3404    2010/07/01 19:44:21 [debug] 76327#0: *8 http filename: "/usr/local/nginx/html/upgrading.html"

Seems like it can't find the directive, but it's there, so not sure what I'm doing wrong.

Also, more generally, is this an acceptable approach to solving this problem? Other ways to do it?

2 Answers 2

4

From this page: https://calomel.org/nginx.html

## System Maintenance (Service Unavailable) 
if (-f $document_root/system_maintenance.html ) {
    error_page 503 /system_maintenance.html;
    return 503;
}

The important part being the '-f', I believe - it tests to see if the file exists.

4
  • Not recommended: wiki.nginx.org/IfIsEvil try_files is the correct approach. Jul 2, 2010 at 3:02
  • quote from there The only safe things may be done inside if in location context are: return ...; and rewrite ... last; Jul 2, 2010 at 9:13
  • Martin, SaveTheRbtz: the example I pointed to did not use 'if' within a 'location' statement - it was at the 'server' level, which is considered fine. However, it is good to point out that it's not recommended within a 'location' statement - that might come up for the OP or anyone else stumbling across this reply. Jul 2, 2010 at 14:20
  • Not sure if this has changed over time, but in the version of nginx (1.8) that I am using, error_page is only allowed in an if nested in a location.
    – JDL
    Jun 23, 2016 at 21:19
0

I suggest that you don't use the try_files here and instead look for the file and return the error code if it exists. Then you can handle the error code separatly. Look at the example below.

# If the maintenance.html file exists, return status 503
if (-f $document_root/maintenance.html) {
  return 503;
}

# Then on status 503, use the @maintenance location
error_page 503 @maintenance;

# I  the @maintenance location, render the maintenance.html
location @maintenance {
  rewrite ^(.*)$ /maintenance.html break;
}

If you plan to do this regualry and whant the same maintenance.html every time you could also change the first part to be something like below. Then you can have the maintenance.html always in place and just att the empty .maintenance file when needed.

if (-f $document_root/.maintenance) {
  return 503;
}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .