Running Seaside, Apache, and IIS on One Machine

Coming from the .Net world, I have many projects I have to support that require my machine to have IIS (Internet Information Server) installed. Though Seaside is now my preferred development environment, and Apache my preferred web server, they need to all co-exist for me to do my job.

Seaside's web server isn't built for handling the kind of load Apache and IIS are capable of, and there's a lot of things a web site needs to serve up besides dynamic pages. Offloading all the static content, images, Javascript, CSS, HTML, zip files, and any other large downloads, is handled much better by a battle tested web server like Apache or IIS.

So the question arises, why use Apache at all, why not just use IIS? The answer is quite simple, IIS sucks for anything but using ASP.Net; it's not a pluggable web server like Apache is. When I first started using Seaside, I tried to get IIS to reverse proxy for me, it was a no go, I'd have to write code. Reverse proxying isn't something IIS can do out of the box, yet it's a simple configuration change in Apache. Apache has far more capabilities as a web server, than IIS does, or ever will. So I bit the bullet and learned how to use Apache, and I'm glad I did, it's an awesome web server.

Problem is, web servers want to run on port 80, so which one gets to own that? You'd think that you could easily run them both on port 80, and bind them to different IP addresses. In fact, this is possible, but it's a royal pain in the ass to accomplish, because IIS isn't well behaved and grabs onto whatever port it's running on, on every address on the machine, even when it isn't configured to do so, preventing Apache from being able to bind. There are instructions out there, on getting IIS to behave, but I gave up, it wasn't worth the effort.

Apache on the other hand, behaves perfectly, and does exactly what you tell it to do. Apache also supports reverse proxying out of the box. Given these options, I decide to run Apache as my primary web server on port 80, and run both IIS and Squeak on other ports and use Apache to simply reverse proxy to them both. This configuration works great. I went into my IIS sites in Internet Service Manager, changed each site to bind to port 81 instead. In Apache, you'll need to edit the httpd.conf (equivalent of Internet Service Manager) and bind to the local address on 80...


Uncomment the following (I think they already are, but don't recall)...

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule rewrite_module modules/mod_rewrite.so

Enable virtual hosting...

NameVirtualHost *:80

And then create a virtual host, this is where all the magic happens

<VirtualHost *:80>
    ServerName localhost       #bind hostname, could be onsmalltalk.com for example
    RewriteEngine On             #enable url rewriting
    ProxyVia Block                #enable reverse proxy
    ProxyPreserveHost On     #make proxy rewrite urls in the output
    #for each .Net app, add a rewrite rule to intercept and proxy it
    RewriteRule ^/DotNetApp(.*)$ http://localhost:81/DotNetApp/$1 [P,L]
    #only allow Seaside rewrite rule to fire, when request doesn't match an existing file
    RewriteCond C:/Inetpub/websites/%{REQUEST_FILENAME} !-f
    #if no file was found, proxy the request to Seaside
    RewriteRule ^/(.*)$ http://localhost:3001/$1 [P,L]

Which looks much simpler without all the comments

<VirtualHost *:80>
    ServerName localhost
    RewriteEngine On
    ProxyVia Block
    ProxyPreserveHost On
    RewriteRule ^/DotNetApp(.*)$ http://localhost:81/DotNetApp/$1 [P,L]
    RewriteCond C:/Inetpub/websites/%{REQUEST_FILENAME} !-f
    RewriteRule ^/(.*)$ http://localhost:3001/$1 [P,L]

And that's it. Apache now acts as the front end, enabling the seamless appearance of running all the web servers on port 80. Visual Studio fires up and binds to .Net web sites without a hiccup, none the wiser that Apache is proxying the request. Mod rewrite now allows me to pick, based upon anything in the URL, which web server needs to handle the request. .Net sites run great, Apache handles all the static content, and Squeak only receives requests for dynamic page generation. Apache can also handle all the SSL requirements, certs, and leave Squeak blissfully unaware that the client is connecting through HTTPS. I use essentially the same setup in production.

Comments (automatically disabled after 1 year)

[...] Running Seaside, Apache, and IIS on One Machine | OnSmalltalk: A Squeak, Smalltalk, Seaside, Web Development Blog Smart setup to run Seaside and Apache on the same webserver, use Apache to proxy on to Seaside. (tags: squeak seaside apache) [...]

[...] Ramon Leon of OnSmalltalk put up a post recently that also talks about how to configure Apache so it works with Seaside and IIS! [...]

isaiah 6220 days ago

hey ramon, i tried the configuration you suggested, not very familiar with apache. everytime i put a url pointing to one of my .NET apps i get a 503 error from apache. the .NET app work fine from port 81 any ideas why this may be have i missed something

Ramon Leon 6220 days ago

Send me your config and I'll take a look.

Curtis 6204 days ago

I was able to use your RewriteRule to get IIS running with Apache to use some classic ASP and just wanted to say thanks. Apache is quite impressive.

Ramon Leon 6204 days ago

Yes it is, and you're welcome.

Mark 6163 days ago

Hi, This is what I'm trying to achieve on a Win2K server.

Apache -will be hosting www.domain.com on port 80

IIS -will be hosting office.domain.com/address on 8080

I've followed u'r instructions but Apache refuses to start..so I must be doing something wrong.

Do i have to put virtual host for both www and office in the httpd.conf ?


Ramon Leon 6162 days ago

Break it up into two steps. Get Apache working first with IIS completely shutdown, i.e. "net stop w3svc".

Only after Apache is working should you bother with IIS. IIS has a bad habit of grabbing port 80 even when it shouldn't.

Aatish 6157 days ago

I am trying to redirect all requests for *.asp that come to apache server to an iis server located elsewhere. I read your instructions, but i am still not able to get it working. can you shed some light no that ?

John M. 6076 days ago

If I set up my IIS site on port 81 and reverse proxy as in your example, do I still need to open up port 81 on my firewall?

Ramon Leon 6076 days ago

No, the port 81 traffic will be totally local between Apache and IIS.

Lisandro B. 6029 days ago

This almost works for me, except for one thing: the .net site is based in ajax, and it seems it is unable to get the data it is supossed to receive from the database. When you click in a link, it grabs some data from the db and outputs it in a div. It works ok when I do http://localhost:81/file.aspx, but it does not work with the proxy thing. What can i do?

Ramon Leon 6029 days ago

I guess it'd depend on the Ajax framework, and what the server expects. You don't really give enough information, but it's possible the Ajax framework is aware of the port it's being served and needs some setting or something to work behind a proxy.

Mesh 5974 days ago

Hello , i want to use Apache as main webserver , to host ASP,ASPX , i setup IIS and its running perfectly on port 8888

so when i type http://localhost i get apache page , when i type http://localhost:8888/ASP i get my asp page ,

how shall i configure apache ?? i loaded modproxy,modhttpproxy,modrewrite successfully

shall i enable the #Include conf/extra/httpd-vhosts.conf ?

then what ? , plz help me

thanx !

Mesh 5974 days ago

forget to say that , my asp files are on c:\ASP\

i intend that the forward occures what ever typed in the borwser from my localhost , to an ip from the network for example ( or from a computer that is out side the network through a Dyndns serveice (http://mesh.homelinux.org)

how i can accomplish that ?

thank u

Mesh 5974 days ago

worked at last , didnt know where is the problem , thanx any way , as a noob , i noticed that the rewrite is a mod for url modification ..

here is the conf of the virtual host

RewriteEngine On
ProxyVia Full
ProxyPreserveHost On
RewriteRule ^/(.*)$ http://localhost:8888/ASP/$1 [P,L]
RewriteCond C:/Inetpub/websites/%{REQUEST_FILENAME} !-f
ServerName localhost
Ramon Leon 5974 days ago

You should probably put the rewriteCond before the rule, so apache can serve up pages if they exist, otherwise proxy to Apache.

Vladimir 5959 days ago


I have just configured Apache as mentioned above for my trends app:

ServerName localhost
RewriteEngine On
ProxyVia Block
ProxyPreserveHost On
RewriteRule ^/(.*)$ http://localhost:8008/seaside/go/trends/$1 [P,L]

And I expected to work in following way: 1. When I enter http://localhost/ the trends apps shows up. 2. All links on the page of trends app have names like http://localhost/?s=xCYFCgzFbYbbMTrr&k=rrgJHMRr

  1. is ok, but 2. is not working as I expected, instead I have link names like http://localhost/seaside/go/trends?s=xCYFCgzFbYbbMTrr&k=rrgJHMRr.

As additional question: how could I configure to transparent proxy http://localhost/trends to http://localhost:8008/trends, the way that all urls have http://localhost/trends for outside users, I've tried RewriteRule ^/trends/(.*)$ http://localhost:8008/seaside/go/trends/$1 [P,L] but it's not working as expected again.

Ramon Leon 5959 days ago

You need to set the #serverPath in your config to / on the configuration page. This'll make Seaside generate the links correctly.

Vladimir 5959 days ago

Thanks, Ramon!

I've just successfully configured it as I want. Excellent!

Vladimir 5956 days ago

I meet minor problem with configuration above.

When seaside session expires I'm being redirected to /seaside/go/trends (which is not found through httpd) instead of /trends.

Quick fix for me is to add: Redirect /seaside/go/trends /trends.

But I'm looking for right solution.

Ramon, did you meet the same problem?

Ramon Leon 5956 days ago

You need to subclass WAApplication and do something like this..

handleExpiredRequest: aRequest 
    "this makes an expired session go to / instead of /seaside/examples/counter
    Should be able to use a redirectHandler class for this, but 2.8 broke it"
    ^ super handleExpiredRequest: (WARequest 
            method: aRequest nativeRequest method
            url: '/'
            headers: aRequest nativeRequest header
            fields: {   }
            cookies: aRequest nativeRequest cookies
            nativeRequest: aRequest nativeRequest)

It's a known issue with 2.8. To install it, do this in your root component class side.

applicationNamed: aString
    "plug in my custom application class"
    | application |
    application := MyCustomWAApplicationSubclass named: aString.
    application configuration addAncestor: WARenderLoopConfiguration new.
    application preferenceAt: #rootComponent put: self.
    ^ application

Then your root component can set itself up normally...

    "self initialize"
    | app |
    app := self registerAsApplication: 'myApp'.
        preferenceAt: #sessionClass
        put: MySessionClass.
    app libraries add: SULibrary

It'll be fixed in 2.9. This area was due for a refactoring, there was a redirect handler in 2.7 but it got broken somehow.

about me|good books|popular posts|atom|rss