Nginx Maintenance Mode (503) in Subdirectory with PHP-FPM

503-errornginxphp-fpm

I'm using Nginx with PHP-FPM, and I want to restrict access to a subdirectory of PHP files on my site so that only traffic from my IP address is allowed.

Here is what I have tried, assuming my IP is 1.1.1.1:

location ^~ /blocktest/
    {
            if ($remote_addr != "1.1.1.1")
            {
                    return 503;
            }
    }

This blocks the public, but PHP scripts are no longer executed for me, and I'm just prompted to download the raw file. So, I tried including my PHP configuration file in the block, like this:

location ^~ /blocktest/
    {
            if ($remote_addr != "1.1.1.1")
            {
                    return 503;
            }

            include /usr/local/nginx/conf/php.conf;
    }

…but then the public could access the PHP files again. Ugh. Any idea on how I could get this to work? Thanks!

For reference, here's my php.conf file:

location ~ \.php$ {
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    try_files $uri =404;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;

    fastcgi_connect_timeout 60;
    #fastcgi_send_timeout 180;
    #fastcgi_read_timeout 180;
    fastcgi_send_timeout 2000;
    fastcgi_read_timeout 2000;
    fastcgi_buffer_size 256k;
    fastcgi_buffers 4 256k;
    fastcgi_busy_buffers_size 256k;
    fastcgi_temp_file_write_size 256k;
    fastcgi_intercept_errors on;

    fastcgi_param  PATH_INFO          $fastcgi_path_info;
    fastcgi_param  PATH_TRANSLATED    $document_root$fastcgi_path_info;

    fastcgi_param  QUERY_STRING   $query_string;
    fastcgi_param  REQUEST_METHOD     $request_method;
    fastcgi_param  CONTENT_TYPE   $content_type;
    fastcgi_param  CONTENT_LENGTH     $content_length;

    fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
    fastcgi_param  REQUEST_URI        $request_uri;
    fastcgi_param  DOCUMENT_URI   $document_uri;
    fastcgi_param  DOCUMENT_ROOT      $document_root;
    fastcgi_param  SERVER_PROTOCOL    $server_protocol;

    fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
    fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

    fastcgi_param  REMOTE_ADDR        $remote_addr;
    fastcgi_param  REMOTE_PORT        $remote_port;
    fastcgi_param  SERVER_ADDR        $server_addr;
    fastcgi_param  SERVER_PORT        $server_port;
    fastcgi_param  SERVER_NAME        $server_name;

    # PHP only, required if PHP was built with --enable-force-cgi-redirect
    fastcgi_param  REDIRECT_STATUS    200;
}

Best Answer

I've figured this out. Apparently, the only way to actually prevent the PHP files from being processed by PHP-FPM is to use HttpAccessModule's "deny all", you can't just "return 503".

Here is a Nginx configuration snippet which defines a custom 503 error page and lets you block all public access to a subdirectory, including PHP files generated by PHP-FPM. You can define which IPs have access to the blocked subdirectory using the rules defined by the Nginx HttpAccessModule documentation.

# DEFINE CUSTOM 503 ERROR PAGE
error_page  503 /maintenance/503.htm;

location = /maintenance/503.htm
{
    internal;
}

# BLOCK A DIRECTORY
location ^~ /directory_to_block/
{
    error_page 403 =503 /maintenance/503.htm;

    allow 1.1.1.1; # your IP here
    deny all;

    include /usr/local/nginx/conf/php.conf;
}