{"id":194,"date":"2009-03-06T17:07:00","date_gmt":"2009-03-07T01:07:00","guid":{"rendered":"http:\/\/onehub.com\/blog\/posts\/rails-maintenance-pages-done-right"},"modified":"2009-03-06T17:07:00","modified_gmt":"2009-03-07T01:07:00","slug":"rails-maintenance-pages-done-right","status":"publish","type":"post","link":"https:\/\/www.onehub.com\/blog\/2009\/03\/06\/rails-maintenance-pages-done-right\/","title":{"rendered":"Rails Maintenance Pages Done Right"},"content":{"rendered":"\n<p>A maintenance page is a common feature in a rails deployment. This feature enables the developers to put their application into &#8220;maintenance mode&#8221;, returning 503 (Service Temporarily Unavailable) and a helpful page that describes what is happening and when the user can expect service to resume.<\/p>\n<p>In an <a href=\"http:\/\/nginx.net\/\">nginx<\/a> configuration file this would be something like this:<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\nif (-f $document_root\/system\/maintenance.html) {\n  return 503;\n}\n\nerror_page 404 \/404.html;\nerror_page 500 502 504 \/500.html;\nerror_page 503 @503;\nlocation @503 {\n  rewrite ^(.*)$ \/system\/maintenance.html break;\n}\n<\/pre>\n<p>The page can then be activated or deactivated from a simple <a href=\"http:\/\/capistrano.org\/\">Capistrano<\/a> task:<\/p>\n<pre class=\"brush: ruby; title: ; notranslate\" title=\"\">\n# Swap in the maintenance page\nnamespace :web do\n  task :disable, :roles =&gt; :web do\n    on_rollback { run &quot;rm #{shared_path}\/system\/maintenance.html&quot; }\n\n    run &quot;if [[ !(-f #{shared_path}\/system\/maintenance.html) ]] ; then ln -s #{shared_path}\/system\/maintenance.html.not_active #{shared_path}\/system\/maintenance.html ; else echo 'maintenance page already up'; fi&quot;\n  end\n\n  task :enable, :roles =&gt; :web do\n    run &quot;rm #{shared_path}\/system\/maintenance.html&quot;\n  end\nend\n<\/pre>\n<p>This pretty typical configuration is lacking two desirable features. First, what if you want your logo image on your maintenance page? Lets try this:<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\nif (-f $document_root\/system\/maintenance.html) {\n  return 503;\n}\n\nerror_page 404 \/404.html;\nerror_page 500 502 504 \/500.html;\nerror_page 503 @503;\nlocation @503 {\n  # Serve static assets if found.\n  if (-f $request_filename) {\n    break;\n  }\n\n  rewrite ^(.*)$ \/system\/maintenance.html break;\n}\n<\/pre>\n<p>This configuration will serve any static assets nginx can find on disk, but it will continue to return the 503 HTTP Status Code.<\/p>\n<p>Finally, nginx, like most webservers will not let you POST to a static file. If a user loads your login page, then you switch on your maintenance page, the user will be greeted with the standard nginx 405 (Method Not Allowed) page. The solution is to capture 405 errors in your @503 location block, serving the maintenance page. In addition, you will have to enable @recursive<em>error<\/em>pages@, since you are first, intentionally, throwing a 503 error, and then the user is throwing a 405 by posting to your static file:<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\nrecursive_error_pages on;\n\nif (-f $document_root\/system\/maintenance.html) {\n  return 503;\n}\n\nerror_page 404 \/404.html;\nerror_page 500 502 504 \/500.html;\nerror_page 503 @503;\nlocation @503 {\n\n  error_page 405 = \/system\/maintenance.html;\n\n  # Serve static assets if found.\n  if (-f $request_filename) {\n    break;\n  }\n\n  rewrite ^(.*)$ \/system\/maintenance.html break;\n}\n<\/pre>\n<p>Now you can serve your stylish maintenance page no matter what the situation is.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A maintenance page is a common feature in a rails deployment. This feature enables the developers to put their application into &#8220;maintenance mode&#8221;, returning 503 (Service Temporarily Unavailable) and a helpful page that describes what is happening and when the [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_themeisle_gutenberg_block_has_review":false},"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/www.onehub.com\/blog\/wp-json\/wp\/v2\/posts\/194"}],"collection":[{"href":"https:\/\/www.onehub.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.onehub.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.onehub.com\/blog\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/www.onehub.com\/blog\/wp-json\/wp\/v2\/comments?post=194"}],"version-history":[{"count":0,"href":"https:\/\/www.onehub.com\/blog\/wp-json\/wp\/v2\/posts\/194\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.onehub.com\/blog\/wp-json\/wp\/v2\/media?parent=194"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.onehub.com\/blog\/wp-json\/wp\/v2\/categories?post=194"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.onehub.com\/blog\/wp-json\/wp\/v2\/tags?post=194"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}