4

I want to disable the access to an app during a certain period of the day.

Is it possible to do something like this in Nginx?

if(hour > '04:00:00' && hour < '05:00:00') {
    root /var/www/maintenance;
} else {
    root /var/www/site;
}
1
  • I've just thought I could use a symlink and make a bash script to change it... but I'm still interested if it's possible directly in nginx
    – the_nuts
    May 1, 2017 at 15:12

3 Answers 3

3

I can only think of 2 ways of doing this (other than the cron changing the symlink):

1) http://nginx.org/en/docs/http/ngx_http_ssi_module.html#variables

2) Create a very small PHP/Python/Whatever app that returns 200 if not maintenance hours and 403 otherwise. Use the http auth module. http://nginx.org/en/docs/http/ngx_http_auth_request_module.html

1

Just create a bash script to update a file and set it as a cronjob, e.g:

#!/usr/bin/env bash

SiteStatus="$1"
SiteStatusConfig="/etc/nginx/status.conf"

if [ "$SiteStatus" = "maintenance" ]; then
    echo "root /var/www/maintenance;" > $SiteStatusConfig
else
    echo "root /var/www/site;" > $SiteStatusConfig
fi
nginx -s reload

Then just place into your nginx site config (replacing root directive):

include status.conf;

Then the cronjob:

0 4 * * * /opt/scripts/nginx-site-script.sh maintenance
0 5 * * * /opt/scripts/nginx-site-script.sh

Trying to do this in nginx, via an if statement and the like can slow nginx down as nginx evaluates the server block (stored in memory) with each request.

1

The approach I typically use for this is to include a downtime handler whenever I first enable an app in nginx. Here's example config:

location /app_1/ {
    proxy_pass http://127.0.0.1:8001/;
    proxy_set_header   Host             $host;
    proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
    error_page 502 =200 /502-app_1-maintenance.html;
}
location /502-app_1-maintenance.html {
    root /var/www/html/error;
    try_files $uri /502-app_1-maintenance.html;
}

Whenever nginx cannot connect to app_1 on port 8001, it produces a 502 error. That error is redirected via error_page 502 =200 /502-app_1-maintenance.html; to a custom page in the second location block that contains a simple "App 1 Under Maintenance" message. Visitors will get this custom "Under Maintenance" page any time app_1 is down. That seamlessly handles unscheduled as well as scheduled downtimes.

In this example, the response code to the user for this maintenance page is a 200 (OK), however, you can change that to an error response if you prefer by changing =200 to the return code of your choice.

You can also add a bit of javascript to have the page reload periodically. Since the url of the maintenance page is the same as the app's url, when app_1 comes back online, it will replace the maintenance page on the next auto-reload.

In your case, since you want to disable public access during certain times, you could combine this nginx configuration with a scheduled app shutdown via crontab. If you wanted, you could then bring your app up on a different port while you perform maintenance. As long as it's not listening on its usual port, visitors will see the Under Maintenance page.

You must log in to answer this question.

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