Monday, August 28, 2017

Temporarily redirect *all* HTTP/HTTPS requests in IIS to a "server maintenance" page



We've got an IIS server that hosts hundreds of separate web apps, and the physical database server that hosts these apps is going to be taken offline for maintenance for a brief period (we expect it to take less than 15 minutes).



During that period, we want to redirect ALL traffic that comes in, for any website, to a "we're currently undergoing maintenance" page.




I realize I could do this by going to every web app, and setting up an IIS rewrite rule that sends the user to another page for all requests in that app. But, it would take us longer to do that than it will to do the database maintenance!



I've tried three things, none of which have worked:





I've been searching for a simple way to apply a rule to all sites, in one fell swoop--and then be able to "undo" that rule in one equally painless step. So far, none of my attempts have worked. I did try putting this rewrite rule in my global web.config at W:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\web.config:






















This didn't work. We're running .NET 4.0 64 bit in IIS, but "just in case" I put the same thing the 32 bit and 2.0 global web.config files, and still no change.






One other suggestion I've seen is the app_offline.htm "special" file, but we're back the same issue of it taking longer to deploy this file to the app root of all our apps than it would to actually do the maintenance.





All our sites are setup in IIS with a single IP. This works for us even without SNA because all our apps share a single SSL certificate (it's a UCC). One thing that occurred to me was that perhaps I could setup a site in IIS that matched all traffic to the IP we're using, and did not specify a host header value. The hope was that I could give it a higher "precedence" and that it, when started, would match all traffic to that IP, before any of the other sites had a chance to match. I could set that site up to serve the same page for all requests, regardless of the request URL.



Start that site when undergoing maintenance, and stop it when finished.



But, I wasn't able to get this working either, as IIS seems to match an HTTP request to a more specific site before less specific. So, by omitting a host-header value for this "tell users we're offline" site, it didn't get matched unless the request didn't have a host-header value that matched another site. Which puts us back at the same problem of having to manually go to each web app and perform an action to take it offline and then put it back online when we're done with maintenance




Is there a simple way to accomplish this? It would seem that surely we are not the first to encounter this issue.



-Josh


Answer



I would go with your third approach "We're offline" Site in IIS, say you named it Offline, if it has no host header specified it will serve all requests not picked up by any of the other sites which have a matching host header. To prevent this you just stop all other sites.



Assuming you have IIS Scripting installed, open an elevated PowerShell:



import-module webadministration



now you can stop all sites except the Offline one:



Get-ChildItem IIS:\Sites | Where {$_.Name -ne "Offline"} | Stop-WebSite


when the SQL-Server is back up, start them up again:



Get-ChildItem IIS:\Sites | Where {$_.Name -ne "Offline"} | Start-WebSite



If you have FTP sites as well, the commands will show an error because you can not pipe an FTP site to a Stop-WebSite cmdlet, but it still works for all the web sites.



If you have sites that normally not run, you have to exclude them in the second command, like:



Where {$_.Name -ne "Offline" -and $_.Name -ne "foobar.com"}


If you don't have the PowerShell cmdlets for IIS installed, you can use appcmd.exe to do the same, I haven't used that in years though.


No comments:

Post a Comment

linux - How to SSH to ec2 instance in VPC private subnet via NAT server

I have created a VPC in aws with a public subnet and a private subnet. The private subnet does not have direct access to external network. S...