How to: OpenERP 6.1, Ubuntu 10.04 LTS, nginx SSL Reverse Proxy
This article follows on (hopefully not unsurprisingly) from the basic 6.1 installation howto.
In this post I’ll describe one way of providing SSL encrypted access to your shiny new OpenERP 6.1 server running on Ubuntu 10.04 LTS.
This time I thought I’d use the nginx (pronounced like “Engine X”) webserver to act as a reverse proxy and do SSL termination for web, GTK client and WebDAV/CalDAV access. nginx is gaining in popularity and is now the second most popular web server in the world according to some figures. It has a reputation for being fast and lean – so it seemed like a good choice for a relatively simple job like this.
I’m indebted to xat for this post which provided the main configuration script for a reverse proxy on OpenERP 6.0. The changes I have made to xat’s original configuration are: different port number, some additional rewrite rules to support WebDAV and the new mobile interface, new location for static files.
NB: For the purposes of this how to, we’ll be using self-signed certificates. A discussion of the pros and cons of this choice is beyond the scope of this article.
Step 1. Install nginx
On your server install nginx by typing:
sudo apt-get install nginx
Next, we need to generate a SSL certificate and key.
Step 2. Create your cert and key
I create the files in a temporary directory then move them to their final resting place once they have been built (the first cd
is just to make sure we are in our home directory to start with):
cd
mkdir temp
cd temp
Then we generate a new key, you will be asked to enter a passphrase and confirm:
openssl genrsa -des3 -out server.pkey 1024
We don’t really want to have to enter a passphrase every time the server starts up so we remove the passphrase by doing this:
openssl rsa -in server.pkey -out server.key
Next we need to create a signing request which will hold the data that will be visible in your final certificate:
openssl req -new -key server.key -out server.csr
This will generate a series of prompts like this: Enter the information as requested:
You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter ‘.’, the field will be left blank.
—–
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:
Email Address []:Please enter the following ‘extra’ attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:The Client’s Company
And finally we self-sign our certificate.
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
We only need two of the files in the working directory, the key and the certificate. But before we can use them they need to have their ownership and access rights altered:
sudo chown root:www-data server.crt server.key
sudo chmod 640 server.crt server.key
And then we put them in a sensible place:
sudo mkdir /etc/ssl/nginx
sudo chown www-data:root /etc/ssl/nginx
sudo chmod 710 /etc/ssl/nginx
sudo mv server.crt server.key /etc/ssl/nginx/
Now the key and certificate are safely stored away, we can tell nginx where they are and what it should be doing…
Step 3. Create the nginx site configuration file
We create a new configuration file
sudo nano /etc/nginx/sites-available/openerp
with the following content:
Note: You will need to change all references to 10.0.0.26
in the following file to either the domain name or static IP address of your server. This was the IP address of the machine I built this test script on. It will not work unless changed to suit your own system!
upstream openerpweb { server 127.0.0.1:8069 weight=1 fail_timeout=300s; } server { listen 80; server_name 10.0.0.26; # Strict Transport Security add_header Strict-Transport-Security max-age=2592000; rewrite ^/mobile.*$ https://10.0.0.26/web_mobile/static/src/web_mobile.html permanent; rewrite ^/webdav(.*)$ https://10.0.0.26/webdav/$1 permanent; rewrite ^/.*$ https://10.0.0.26/web/webclient/home permanent; } server { # server port and name listen 443 default; server_name 10.0.0.26; # Specifies the maximum accepted body size of a client request, # as indicated by the request header Content-Length. client_max_body_size 200m; # ssl log files access_log /var/log/nginx/openerp-access.log; error_log /var/log/nginx/openerp-error.log; # ssl certificate files ssl on; ssl_certificate /etc/ssl/nginx/server.crt; ssl_certificate_key /etc/ssl/nginx/server.key; # add ssl specific settings keepalive_timeout 60; # limit ciphers ssl_ciphers HIGH:!ADH:!MD5; ssl_protocols SSLv3 TLSv1; ssl_prefer_server_ciphers on; # increase proxy buffer to handle some OpenERP web requests proxy_buffers 16 64k; proxy_buffer_size 128k; location / { proxy_pass http://openerpweb; # force timeouts if the backend dies proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; # set headers proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forward-For $proxy_add_x_forwarded_for; # Let the OpenERP web service know that we're using HTTPS, otherwise # it will generate URL using http:// and not https:// proxy_set_header X-Forwarded-Proto https; # by default, do not forward anything proxy_redirect off; } # cache some static data in memory for 60mins. # under heavy load this should relieve stress on the OpenERP web interface a bit. location ~* /web/static/ { proxy_cache_valid 200 60m; proxy_buffering on; expires 864000; proxy_pass http://openerpweb; } }
UPDATE: 04/04/2012. I have added a line to the above file: client_max_body_size 200m;
thanks to Praxi for reminding me about this. The default setting is just 1MB which will stop users from uploading any files larger than that, including databases!
And then we can enable the new site configuration by creating a symbolic link in the /etc/nginx/sites-enabled
directory.
sudo ln -s /etc/nginx/sites-available/openerp /etc/nginx/sites-enabled/openerp
Step 4. Change the OpenERP server configuration file
The next step is to re-configure the OpenERP server so that non-encrypted services are not accessible from the outside world.
In /etc/openerp-server.conf
the non-encrypted services will only listen on localhost, i.e. not from external connections so in effect only traffic from nginx will be accepted.
After opening the file for editing, just add 127.0.0.1 to the xmlrpc and netrpc interface lines as shown below.
sudo nano /etc/openerp-server.conf
xmlrpc_interface = 127.0.0.1
netrpc_interface = 127.0.0.1
That’s it. Everything is now configured.
Step 5. Try it out
Restart the services to load the new configurations
sudo service openerp-server restart
sudo service nginx restart
You should not be able to connect to the web client on port 8069 and the GTK client should not connect on either the NetRPC (8070) or XMLRPC (8069) services.
For web access you just need to visit https://your-ip-or-domain and in the GTK client you will need to use port 443 (https) and choose the XMLRPC (Secure) protocol.
The nginx configuration above will also redirect any incoming requests for port 80 to port 443 (https) and it also makes sensible redirects for the mobile and WebDAV/CalDAV services. (From what I can gather however WebDAV clients really don’t handle redirects so this bit is probably not that useful). I think the best bet for WebDAV/CalDAV is just to provide the correct URL in the first place.
For CalDAV access then, the URL to a calendar will be something like this:
https://your-ip-or-domain/webdav/DB_NAME/calendars/users/USERNAME/c/CALENDAR_NAME
There you have it. In OpenERP 6.1 this job actually proved to be a little simpler than the previous version largely due to the integrated web interface. There are also fewer configuration changes required in openerp-server.conf
.
Finally, I really wanted to try and make use of the WSGI support in OpenERP 6.1 instead of the method above, but my efforts to get this to work from nginx or Apache have so far ended in failure 🙁 Obviously if anyone wants to provide a working config for that please feel free to add a comment and link.
How to install OpenERP 6.0 on Ubuntu 10.04 LTS Server (Part 2 – SSL)
This article follows on (hopefully not unsurprisingly) from part 1.
In this post I’ll describe our current way of providing SSL encrypted access to a shiny new OpenERP server running on Ubuntu 10.04 LTS Server.
We’re using the Apache webserver to act as a proxy and do SSL termination for web client access and for WebDAV/CalDAV access. The GTK client will also be running over an encrypted XMLRPC link directly to the OpenERP Server. Apache is the most widely used webserver in the world and there is oodles of documentation about it so I do not plan to go into any great detail about the configuration choices. One document that is worth pointing out however is the information about how to configure and administer Apache specifically under Debian/Ubuntu. The way Apache is packaged and set up is quite different from most other Linux distributions. A very useful document can be found here /usr/share/doc/apache2.2-common/README.Debian.gz
on your server.
NB: For the purposes of this how to, we’ll be using self-signed certificates. A discussion of the pros and cons of this choice is beyond the scope of this article.
Step 1. Install Apache and required modules
On your server install apache2 by typing
sudo apt-get install apache2
Now we’ll tell apache that we want to use a few modules (mod_ssl, mod_proxy, mod_proxy_http, mod_headers and mod_rewrite [optional]) that are not enabled by default:
sudo a2enmod ssl proxy_http headers rewrite
Next, we need to generate a SSL certificate and key.
Step 2. Create your cert and key
I create the files in a temporary directory then move them to their final resting place once they have been built (the first cd
is just to make sure we are in our home directory to start with):
cd
mkdir temp
cd temp
Then we generate a new key, you will be asked to enter a passphrase and confirm:
openssl genrsa -des3 -out server.pkey 1024
We don’t really want to have to enter a passphrase every time the server starts up so we remove the passphrase by doing this:
openssl rsa -in server.pkey -out server.key
Next we need to create a signing request which will hold the data that will be visible in your final certificate:
openssl req -new -key server.key -out server.csr
This will generate a series of prompts like this: Enter the information as requested:
You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter ‘.’, the field will be left blank.
—–
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:
Email Address []:Please enter the following ‘extra’ attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:The Client’s Company
And finally we self-sign our certificate.
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
We only need two of the files in the working directory, the key and the certificate. But before we can use them they need to have their ownership and access rights altered:
sudo chown openerp:root server.crt server.key
sudo chmod 640 server.crt server.key
And then we put them in a sensible place:
sudo mkdir /etc/ssl/openerp
sudo chown openerp:root /etc/ssl/openerp
sudo chmod 710 /etc/ssl/openerp
sudo mv server.crt server.key /etc/ssl/openerp/
Now the key and certificate are safely stored away, we can tell Apache where they are:
Step 3. Create the Apache site configuration file
We create a new Virtual Host configuration file
sudo nano /etc/apache2/sites-available/openerp-ssl
with the following content:
SSLEngine on
SSLCertificateFile /etc/ssl/openerp/server.crt
SSLCertificateKeyFile /etc/ssl/openerp/server.keyProxyRequests Off
Order deny,allow
Allow from all
ProxyVia On
ProxyPass /webdav/ http://127.0.0.1:8069/webdav/
ProxyPassReverse /webdav/
Order Deny,Allow
Allow from all
Satisfy Any
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse /
RequestHeader set "X-Forwarded-Proto" "https"
# Fix IE problem (httpapache proxy dav error 408/409)
SetEnv proxy-nokeepalive 1
Note there are two Proxy configurations. One for /webdav/
and one for /
. If you do not intend to use WebDAV or CalDAV then you can remove that section. But essentially, we are telling apache that WebDAV traffic needs to go to the XMLRPC port on the OpenERP server, and normal web traffic needs to go to the web client that is listening on port 8080. The order is also important. If /
came before /webdav/
then it wouldn’t work.
And then we can enable the new site configuration.
sudo a2ensite openerp-ssl
Optionally, you can use mod_rewrite to redirect any normal (non-encrypted) web browser traffic to the SSL port (443).
To do this, add the following lines (outside of the
config blocks) into the file /etc/apache2/sites-available/default
RewriteEngine on
RewriteCond %{SERVER_PORT} ^80$
RewriteRule ^(.*)$ https://%{SERVER_NAME}$1 [L,R]
Step 4. Change the OpenERP server and web-client configuration files
The next step is to re-configure the OpenERP server and Web client so that the non-encrypted services are not accessible from the outside world.
In /etc/openerp-server.conf
the two non-encrypted services will only listen on localhost, i.e. not from external connections so in effect only traffic from Apache will be accepted. We also tell the XMLRPC-SSL service where to find the necessary key and certificate.
Make the following changes:
sudo nano /etc/openerp-server.conf
xmlrpc = True
xmlrpc_interface = 127.0.0.1
xmlrpc_port = 8069netrpc = True
netrpc_interface = 127.0.0.1
netrpc_port = 8070xmlrpcs = True
xmlrpcs_interface =
xmlrpcs_port = 8071
secure_pkey_file = /etc/ssl/openerp/server.key
secure_cert_file = /etc/ssl/openerp/server.crt
If you want to have WebDAV/CalDAV access add the following at the bottom of the config file.
[webdav]
enable = True
vdir = webdav
Then in the web client config file /etc/openerp-web.conf make the following changes so that it also only accepts traffic from localhost:
sudo nano /etc/openerp-web.conf
# Some server parameters that you may want to tweak
server.socket_host = “127.0.0.1”# Set to True if you are deploying your App behind a proxy
# e.g. Apache using mod_proxy
tools.proxy.on = True# If your proxy does not add the X-Forwarded-Host header, set
# the following to the *public* host url.
tools.proxy.base = ‘https://your-ip-or-domain’# Set to false to disable CSRF checks
tools.csrf.on = False
That’s it.
Step 5. Try it out
Restart the services to load the new configurations
sudo service openerp-server restart
sudo service openerp-web restart
sudo service apache2 restart
You should not be able to connect to the web client on port 8080 and the GTK client should not connect on either the NetRPC (8070) or XMLRPC (8069) services. For the web access you just need to visit https://your-ip-or-domain and in the GTK client you will need to use port 8071 and choose the XMLRPC (Secure) protocol.
For CalDAV access the URL to a calendar will be something like this:
https://your-ip-or-domain/webdav/DB_NAME/calendars/users/USERNAME/c/CALENDAR_NAME
I hope that is helpful and obviously we’d love to hear comments and suggestions for improvements.
When you book an airline ticket, you use FOSS
This article on ReadWriteWeb really caught my eye today.
From my previous life in data and telecoms I know a little of the scale of the Sabre network. It’s BIG. By the sounds of things most of it runs on Open Source software too. They have announced a partnership with a commercial Open Source vendor Progress to use a number of their FUSE Open Source products.
By default, Sabre only chooses off-the-shelf software
as its last option ifwhen no open-source solution is available. If there is neither an open-source nor an off-the-shelf solution, Sabre’s own technology team will provide an in-house solution.
Sabre, as Progress’s Debbie Moynihan proudly pointed out to us, can’t afford any downtime – and FUSE’s Supplier-Side Gateway, which currently handles about 1.5 million transaction a day, has now run on Sabre’s system for 14 months without any error.
Besides FUSE’s offerings, which are based on Apache products, Sabre also extensively uses Apache’s web server, MySQL, Hibernate, Terracotta and a number of other open source products. Also, two-thirds of Sabre’s 5000 servers currently run Linux and the company expects to expand this number over time.
Nice figures. Good story.
It’s when I hear about these really massive and important networks that can’t really go down using FOSS because it works and works well that I really wonder why uptake across the whole enterprise space is so shockingly small in comparison. And then I remember why I think it is so.
The Huge Marketing Budgets of one or two proprietary vendors. But, you know what. I think the times they are a changing….
Another tale of Open Sourcery
Martyn, from Severn Delta Ltd, emailed me saying he had an Open Source story to tell. I’ve had this in my inbox for a while now, but have finally got round to publishing it.
Alan,
I own 50% of a manufacturing company in Bridgwater. When we bought the company out of receivership in ’03 we had no systems at all. Our former parent company was running a character based ERP system called MAX on Unix and a Windows file serving network.
So day 1 (ish!) we set up two RH servers and installed samba, sendmail, apache etc on one for file print intranet and email and the Linux port of MAX on the other.
See this post for some other detail.
http://blogs.severndelta.co.uk/?p=5
We have not been able to find a “right-sized” ERP solution for our needs to replace the ageing character based system (which had been “sunsetted” by infor in ’05). We also needed some form of CRM package to mange the growth of the company once we had moved into our new building in ’05.
So…. we decided to develop our own system in combination with an open source CRM package from a company called Senokian Solutions (http://www.senokian.com) called EGS.
EGS is PHP/Ajax based and runs against PostgreSQL. It also has its own development framework based on MVC that allows you to add modules. EGS 2.0 core has CRM, Project Management, Ticketing modules and a framework that allows for integrated e-commerce apps and site content management. It is free and open source.
The tools on which the system is built are:
Linux (Ubuntu)
Apache
PostgreSQL
PHP 5
Ajax
Smarty Template Engine
EZ pdf
XML/SWF ChartsIn November 2006 I took on a developer, Dave Easeman, to help code the accounts/ERP system as I specified it – we are now 99% of the way through – although I guess we will never finish the project! We are about to go live (Jan 1st) and then the aim is to polish everything up in Quarter 1/2 2009.
See here for a link on our blog
http://blogs.severndelta.co.uk/?p=58Maybe what I’ll do is update you as we progress to “go live” on Jan 1.
Regards
Martyn Shiner
Financial Director
Severn Delta Limited
Thanks for the story Martyn, it’s very encouraging how companies such as yours (i.e. not some global enterprise with billions of dollars in the bank) are able to deploy, manage, run and develop their own IT systems using FOSS. This is a great example of just how flexible and accessible FOSS really is.
I love this quote (from the first blog link):
I will never buy a Windows based PC ever again.
Are you listening Bill?
That was written in August last year. I’m interested if you have managed to stick to that goal Martyn?
Good luck with your deployment. I genuinely hope it goes well, and please do keep us updated on your progress. You seem to have a similar tenacity to Adrian Steele at Mercian Labels who has also been blogging about their own migration to FOSS. And they also developed a core application from scratch too – for them it was a CRM/MIS app.
Alfresco, a bit like Quickr but Bettr
Quickr, for those who are lucky enough not to know, is the morphologically challenged relative of Lotus Quickplace. In reality it is Quickplace with two new themes, two new placetypes and two versions of dojo dumped on the filesystem to make things look a bit more “Web 2.0” and some windows-only integration with Microsoft only applications. So why I am I telling you about proprietary software here on “The Open Sourcerer”? Well I have a bit of a background in the IBM/Lotus area and I have been developing corporate themes for Quickplace since sometime in the last millennium. It hasn’t changed much, but there is a very serious Free and Open Source alternative now.
In brief, Quickr is a website creating tool, each site is known as a “place” and within a place you can have folders and rooms. Rooms are like sub-places, they can have their own access control rules and a different style. They can contain rooms as well so you can have a hierarchy of places. It looks quite pretty, and 10 years ago it was 5 years ahead of its time. It has now got a client install, which integrates with some legacy Windows applications, more on that later.
Alfresco is an Open Source Enterprise Content Management System, which runs as a J2EE application on Linux and other platforms (I would stick to Linux+Apache+Tomcat+MySQL for preference). Like Quickr you create areas for storing stuff, in Alfresco they are called “Spaces”. Spaces can contain files, folders and more spaces.
Inheritance of security to sub-spaces/rooms
So in Quickr you create a place, you add members to that place, you create a room within the place, you carefully check the checkbox labeled “inherit members from parent place” as you create it so that all the members of the place can get into the room. Lovely. Now add another member to the place. You would expect them to be able to access the room wouldn’t you?
No. Inheritance is a one shot deal when you create a room, it just copies the access control list from the parent room as it creates the subroom. Now imagine an place in an enterprise with 100+ rooms and managing user access to this lot. It gets messy.
In Alfresco, inheritance works just like it should. You can set a space to inherit from the parent space, and override it at will. Nice, friendly and fit for the enterprise user/administrator.
Access as a file system
The big new feature in Quickr (the pretty skins don’t count as they are only skin deep) is the Quickr Connectors. This Windows only program installs as a Windows Explorer extension and sits alongside the network neighbourhood, it sort of works like a filesystem.
You can’t do linked spreadsheets (OpenOffice.org or Symphony, or the other one) because the files don’t reside at a resolvable UNC path.
Folders are deeply broken. You can create folders, and nested folders, but they look rubbish in most of the web themes which are designed for a single level of folders. If you do use a web theme with a hierarchical folder tree and then use the web interface to move folders between rooms, they break in the connector. Moving them in the web doesn’t update some important UNID field somewhere, I couldn’t figure out which, but I reported it as a bug.
Personal spaces (aka Quickr Entry) were supposed to be a wonderful thing, when you send an email with an attachment from a proprietary email client (Lotus Notes or the other one) it asks you if you want to store the attachment in your Quickr place and send a link instead. This sort of works. With no security. Your place is public, anyone can see stuff you put in it (with a lame security-by-obscurity option which I haven’t figured out how to get to yet). So you want to organise your space, putting stuff in folders etc. well you can’t. Folders aren’t allowed in personal spaces. Tough.
So how does file system access work in Alfresco? Well it will act as a WebDav server or a CIFS server or both. There is no mucking about with locally installed connector clients and Windows Explorer extensions to make it look a little bit like a network filesystem. It is a network filesystem. WebDAV is well supported on Linux and Mac and it works on Windows too. Once you connect to your server via WebDAV it just looks like another bit of your filesystem. You can drag and drop documents into and out of it, double click things to open them etc. Linked spreadsheets work fine, and in fact every application that expects to be storing or accessing data on a regular drive works just fine with your remote content management system. It isn’t just any remote drive though, it is still a content management system, if the business rules for a space where you drop a file dictate version control then that is exactly what happens.
Version control
So lets say you have a document in Quickr created with a form set up for optional version control (which is a bit of a sloppy concept in itself). You are doing some edits and what started as correcting a few typos turns into a major re-factoring session. You now want to save your document as a new version. Tough. Too late. You have to create a new version before you start editing it, otherwise you are just editing and overwriting the existing version. Quickplace always had a published version + working draft system, it now has a sort of revision history stuffed into it. The two models don’t seem to like each other very much.
Version control in Alfresco is somewhat more thought out, it has a very powerful Advanced Versioning Manager, which can track back not just individual files, but directories, it can show you the state of the whole repository at a particular point in time. Very useful for the multiple linked spreadsheets example. It can do way more than this, it is configurable as
So what does work Bettr in Quickr?
Well Quickr has a truly sickening theme/skin engine. It only works in Internet Explorer with ActiveX and you can upload 6 files (stylesheet + 5 HTML files) which it scoops up along with any referenced images. The HTML files basically duplicate each other, or you can upload just one HTML file and have it guess what the others should look like. There is no community site to share and sell Quickr skins that I know of, unlike Joomla! and WordPress etc. However, rubbish as the theme engine is, it is better than Alfresco which doesn’t yet have a skinning capability (you can edit the stylesheet and all the .jsp files, but that isn’t the same as a facility for uploading a package of skin elements so that places can be individually styled.)
Quickr isn’t just for storing files, it has a nice calendar that can show custom forms on it. I haven’t yet seen a calendar view for Alfresco. The Gantt chart view in Quickr isn’t very sophisticated at all, I wouldn’t miss that, but the calendar is useful.
When uploading files though the web interface from some Microsoft Office applications it does an ActiveX/COM control thing that gets the application to save as HTML as well as the native binary format and it uploads both the HTML version and the native format. It then serves up the HTML version to browser clients, which would be a nice trick. If it worked a bit better. It doesn’t do this trick if using the windows explorer integration, so if you use a mixture of the Quickr connector and the web client you get a great big muddle and a mess.
In conclusion
If I had to do a 15 minute sales demo, on Windows, I could easily make Quickr look fantastic, but when comparing Quickr against Alfresco as a serious tool for long term use in a modern business, Quickr falls short and Alfresco is the one I would choose.
Microsoft’s IIS vs. Apache: is Apache really in decline?
After reading about the latest netcraft survey (that shows Apache undergoing serious market share decline compared to M$’s IIS), following a link from Glyn Moody’s blog and clicking further to here, we will eventually end up looking at another survey of web servers that shows a rather different result:
How strange… One shows Apache in apparent terminal decline, whilst this survey from www.securityspace.com shows something completely different. The survey above is rather more stringent about what it thinks is a valid web site and what isn’t. And as we have seen before, when large registrars are paid to switch millions of parked domains from Apache to IIS, the Netcraft survey numbers take a rather large jump in favour of the M$ product.
I know which Web Server I depend on. And it isn’t Microsoft’s….