Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

host multiple public sites on service fabric

I have a service fabric cluster deployed with a domain of foo.northcentralus.cloudapp.azure.com

It has a single node type with a single public ip address / load balancer.

Lets say I have the following two apps deployed:

  • http://foo.northcentralus.cloudapp.azure.com:8101/wordcount/
  • http://foo.northcentralus.cloudapp.azure.com:8102/visualobjects/

How can I set this up so I can have multiple domains each hosted on port 80? (assuming I own both of these domains obviously)

  • http://www.wordcount.com
  • http://www.visualobjects.com

Do I need more than one public ip address in my cluster to support this?

like image 498
Dismissile Avatar asked Aug 01 '16 13:08

Dismissile


1 Answers

You should be able to do this with a single public IP address through some http.sys magic.

Assuming you're using Katana for your web host (the word count and visual object samples you reference use Katana), then it should be as simple as starting the server using the domain name in the URL:

WebApp.Start("http://visualobjects.com:80", appBuilder => this.startup.Invoke(appBuilder));

The underlying Windows HTTP Server API will register that server with that URL, and any HTTP request that comes in with a Host: visualobjects.com header will automatically be routed to that server. Repeat for any number of servers with their own hostname. This is the host routing that http.sys does for multi-website hosting on a single machine, same as you had in IIS.

The problem you'll run into is with reserving the hostname, which you have to do under an elevated user account before you open the server. Service Fabric has limited support for this in the form of Endpoint configuration in ServiceManifest.xml:

<!-- THIS WON'T WORK FOR REGISTERING HOSTNAMES -->
<Resources>
  <Endpoints>
    <Endpoint Protocol="http" Name="ServiceEndpoint" Type="Input" Port="80" />
  </Endpoints>
</Resources>

The limitation here is that there is nowhere to specify a hostname, so Service Fabric will always register "http://+:[port]". That unfortunately doesn't work if you want to open a server on a specific hostname - you need to register just the hostname you want to use. You have to do that part manually using netsh (and remove any Endpoints for the same port from ServiceManifest.xml, otherwise it will override your hostname registration).

To register the hostname with http.sys manually, you have to run netsh for the hostname, port, and user account under which your service runs, which by default is Network Service:

netsh http add urlacl url=http://visualobjects.com:80/ user="NT AUTHORITY\NETWORK SERVICE"

But you have to do this from an elevated account on each machine the service will run on. Luckily, we have service setup entry points that can run under elevated account privileges.

edit

One thing you will need to do in order for this to work is open up the firewall on the same port you are listening on. You can do that with the following:

<Resources>
   <Endpoints>
      <Endpoint Protocol="tcp" Name="ServiceEndpoint" Type="Input" Port="80" />
   </Endpoints>
</Resources>

Note that the Protocol is tcp instead of http. This will open up the firewall port but not override the http.sys registration that you set up with the .bat script.

like image 163
Vaclav Turecek Avatar answered Nov 02 '22 12:11

Vaclav Turecek