Here is a way to set the site offline with a customized message to everyone visiting it. The administrator, user 1, is always allowed to access the site so he can do whatever he wants, while everyone else is not.

There is currently one drawback to this patch: You can lock yourself out of your own site! If you are logged in as admin and turn this setting ON, you will be fine. However, if you log off, you will NOT be able to login back.

The workaround for this is easy: in settings.php, you can have the following to override whatever is in the admin menus.

$conf = array(
  'site_offline' => 0
);

Comments

kbahey’s picture

StatusFileSize
new3.06 KB

Modified to make it a 503 service unavailable, so that it does not get indexed by search engines.

Thanks for Gabor Hojtsy for the hint.

factoryjoe’s picture

StatusFileSize
new4.59 KB

For all those naysayers who think this feature doesn't deserve to be exposed in a popular community platform. Consider Flickr's approach. Oh yes, I want this too (see attached).

Gerhard Killesreiter’s picture

Chris: I've absolutely no idea what this screen is trying to tell me...

kbahey’s picture

Just a little bit of background.

This feature has come up before the recent discussion in the drupal-devel, for example, displaying a friendly site down message and still use the site.

Up until now, I used a crude solution for this, but this warrants a "proper" Drupal solution.

Jeremy’s picture

Status:Needs review» Needs work

I applied the patch and verified it works as promised. I like the idea very much. But a few things:

Minor things: "Site Maintenance" should be "Site maintenance" and "Site Status" should be "Site status" to match everything else on the settings page.

Usibility issue: Here's a problem I ran into, granted it was a user error:
1) logged in as user #1
2) set "Site Status" to "Offline" and configured a custom message
3) I navigated around as user #1 and verified the site still worked for me
4) I logged out and verified as a non-administrator I saw the error I configured
5) Now I'm stuck: I can't log back in to put the site back online. Unless I happen to have direct database access (to delete the 'site_offline' row from the variables table, and to flush the cache), the site is going to stay offline.

Feature request: Why tie this to user #1? Couldn't it be tied to a permission instead? If a non-user#1 can enable this mode (they can), then a non-user#1 should also be able to maintain the site when in maintenance mode.

drumm’s picture

I think it would be a good idea to make this an optional replacement for the friendly database error screens as a way of optionally protecting database login information. This means that all the data would have to be stored in settings.php since the database might not be accessible.

kbahey’s picture

Status:Needs work» Needs review
StatusFileSize
new3.1 KB

Implemented suggestions by Jeremy. Wording has been changed, and all user account with "administer site settings" will be allowed to see everything in the site.

As for logging out locking you out, the solution is to change settings.php as described at the top of this issue.

kbahey’s picture

StatusFileSize
new3.16 KB

Must use correct theme page.

Here is the correct patch.

Jeremy’s picture

Status:Needs review» Needs work

Looks good, a few final picky comments...

It might be good to expand the text on the settings page to reflect the fact that site administrators can still access the site. For example, maybe change "This allows you to take the site offline for maintenance." to something like:
"When set to 'Online', all visitors will be able to browse your site normally. When set to 'Offline', only users with 'administer site configuration' permission will be able to access your site to perform maintenance, all other visitors will see the site offline message configured below."

Also you have a typo in the default message:

Out site is currently under maintenance. We should be back shortly. Thank you for your patience.

"Out" should be "Our". Better yet, replace the sentence with something like:
t('%site is currently under maintenance. We should be back shortly. Thank you for your patience.', array('%site' => variable_get('site_name', 'This site')));

As for logging out locking you out, the solution is to change settings.php as described at the top of this issue.

That seems like an accident waiting to happen. Why not allow access the the login page? I'd even go so far as to provide a link on the front page that says something like "Site administrators can log in here." Anyone else that tries to login will just get the offline message. Changing settings.php is not always an easy thing to do, depending on your hosting situation.

kbahey’s picture

StatusFileSize
new3.91 KB

Jeremy

All of your suggestions are addressed now in this patch.

The admin is not locked out of his own site. If he visits user/login, he will be back in.

Tobias Maier’s picture

+1 for this patch (untested because tired)

maybe a just stupid question of i tired man:
when someone wants to access the update.php, xmlrpc.php or the cron.php (site is under maintance user has not "administer site settings")
is he also looked out and gets the same message there (or will be referred to index.php)?
is this necessary?

cu tobias

Jeremy’s picture

Almost, however you replaced the wrong comment on the settings page. ;) The "Site offline message" box has the new help text that was intended for the "Site status" setting.

Otherwise, it works like a charm. I hope to see it merged.

bhagman’s picture

Just out of curiosity, why not create an access privilege for administering the site (during downtime)?
e.g. "Offline Access"

Then you can have multiple site maintainers.

kbahey’s picture

Fixed the help text to go to the relevant field.

kbahey’s picture

StatusFileSize
new3.9 KB

Here is the patch.

bhagman: You can have multiple maintainers now by defining a new role (e.g. admin) and assigning it the "administer blah" settings.

bhagman’s picture

wow, I see it now, back at #7

I must be really tired.

Well done kbahey!

kbahey’s picture

Status:Needs work» Reviewed & tested by the community

I guess all the concerns are addressed, so settings this to ready for commit.

Any other issues?

chx’s picture

Status:Reviewed & tested by the community» Needs work
<?php
if (variable_get('site_offline', 0) && !user_access('administer site configuration') && (drupal_get_normal_path($_GET['q']) != 'user/login'))
?>

A separate function? Three IFs? You are paying for ANDs or what :)?

kbahey’s picture

No, I think ANDs are still free here in Canada.

However, the code is clearer and more readable this way, and hence more maintainable.

I don't think there is much of a performance penalty, since site_offline being set is a rare occasion compared to it being not set, and hence we bail out early from the function and proceed normally (hence only one if in most cases).

Also, I orderd the if by decreasing likeliness, the second one is for users with admin privileges, and normally there are only a few of those compared to others (anonymous and authenticated).

chx’s picture

Hint: PHP if is greedy. Therefore, you do not execute most of that if in most cases, too.

kbahey’s picture

Status:Needs work» Reviewed & tested by the community

Here is a benchmark I did on my test machine, which is a Pentium III 550 MHz, 630MB RAM, Linux 2.6.x kernel, Apache 2, MySQL 4.1.11. Not much else running.

Before each test, I shutdown MySQL and Apache and restarted them, so that MySQL caching does not play a role in skewing the results.

As you can see the results are comparable (2 ms slowness worst case).

So, the patch is ready to go since it does not impact performance.

Command is: ab -n 100 http://test.example.com/

Scenario 1: With no patch applied to HEAD, anonymous users

Document Path:          /
Document Length:        3713 bytes
Without a patch:

Time taken for tests:   43.904 seconds
Requests per second:    2.33 [#/sec] (mean)
Time per request:       430.009 [ms] (mean)
Time per request:       430.009 [ms] (mean, across all concurrent requests)
Transfer rate:          9.12 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:   423  429  14.4    427     556
Waiting:      399  426  15.9    426     554
Total:        423  429  14.4    427     556

Percentage of the requests served within a certain time (ms)
  50%    427
  66%    428
  75%    429
  80%    430
  90%    431
  95%    435
  98%    489
  99%    556
100%    556 (longest request)

============================
Scenario 2: With patch applied, and site is online (as it will normally be), anonymous users

Document Path:          /
Document Length:        3713 bytes

Time taken for tests:   43.258600 seconds
Requests per second:    2.31 [#/sec] (mean)
Time per request:       432.586 [ms] (mean)
Time per request:       432.586 [ms] (mean, across all concurrent requests)
Transfer rate:          9.06 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:   426  431  12.8    429     501
Waiting:        0  421  61.5    429     491
Total:        426  431  12.8    429     501

Percentage of the requests served within a certain time (ms)
  50%    429
  66%    430
  75%    431
  80%    432
  90%    433
  95%    441
  98%    492
  99%    501
100%    501 (longest request)

chx’s picture

I just found the code too long. Really not performance issue :( tried to talk with you on irc :(

Dries’s picture

- 'Site Offline' should be 'Site offline'.

- variable_get('site_name', 'This site') is not consistent.

Otherwise looks good.

Jeremy’s picture

> variable_get('site_name', 'This site') is not consistent.

Not consistent with what? There are 18 occurences of site_name in the modules directory. They default to the following values:
- "Drupal", 1 occurence, aggregator.module
- "drupal", 10 occurences, multiple modules
- "this web site", 1 occurence, drupal.module
- "this website", 1 occurence, user.module
- "''", 2 occurences, drupal.module and ping.module
- "0", 1 occurence, ping.module
- "local", 2 occurences, user.module

It seems the default for site_name is whatever makes sense in the current context. What do you recommend instead? Just over half of the time the default is 'drupal', but if that is used then the default error will be "drupal is currently under maintenance. We should be back shortly. Thank you for your patience." How is that better than "This site is currently under maintenance. We should be back shortly. Thank you for your patience."?

kbahey’s picture

StatusFileSize
new3.9 KB

- Changed "Offline" to "offline"
- Rerolled for current offset

Otherwise, the "This site" is no more inconsistent than other cases that Jeremy has pointed out. Making it "drupal" is not a good idea. Perhaps all the instances should be standardized on some wording, but that is not related to this issue.

Hope it gets committed.

Dries’s picture

I was under the impression that we always used 'drupal'.

The 'This site' can't be translated ... so it's still buggy.

Tobias Maier’s picture

maybe we should say that this should everytime be "Drupal website" because drupal alone is a little bit less

shouchen’s picture

Perhaps the web site admin could specify the text of the message in a setting somewhere. That would be my preference, anyway.

kbahey’s picture

StatusFileSize
new4.21 KB

Here is the patch with a t()'d string.

It was also updated for using the new form API.

kbahey’s picture

@shouchen: it is already configurable the way you want it to.

Dries’s picture

Status:Reviewed & tested by the community» Fixed

Committed. Thanks.

kbahey’s picture

Status:Fixed» Reviewed & tested by the community
StatusFileSize
new637 bytes

Dries,

Regarding user/login not working. I think that form is broken because of the new Form API patch from yesterday.

Here is a patch that provides a workaround (just used "user" instead of "user/login").

Dries’s picture

Not sure I want people to browse or edit user profiles while performing site maintenance.

kbahey’s picture

This will not allow them to edit, nor browse other user's profile.

At worst, it wll allow them to see their own user profile.

I think the real solution is to restore user/login though, since that will be the only form that works while the site is offline. I am not sure what is wrong with it though. Did the Form API patch break it?

gtcaz’s picture

With the latest CVS, if you move to a new broweser, the user/login page shows up, but you can't do anything. So, in this case, you're still locked out even though you can access the login page.

kbahey’s picture

Yes, this is a bug in CVS it seems.

After you apply the patch in #29, apply this patch.

Dries’s picture

Priority:Normal» Critical
Status:Reviewed & tested by the community» Needs work

kbahey: #29 has been applied, not?

kbahey’s picture

Yes, it was applied in #31.

THe reason this is open is that ?q=user/login is not working with HEAD. It gives a page that is missing the sidebars, and the login tab has nothing under it.

I think all this is because of the new Form API patch.

When it is fixed, we can close this one I guess.

kbahey’s picture

Status:Needs work» Fixed

Dries commited the change of "user/login" to "user" and that takes care of the problem.

See details here http://drupal.org/node/35410

Anonymous’s picture

Status:Fixed» Closed (fixed)
abelleba’s picture

Version:x.y.z» 6.0-rc4

Thanks for the post, got my butt out of Maintence Mode finally!

Regards,
Andy Belleba
http://tools.mywikiinfo.com

trimex’s picture

Version:6.0-rc4» 5.x-dev