2

I have an Ubuntu host machine with 3 guests. All of them have different webservices running on port 80. How can I tell the host to forward the request to the appropriate guest based on the hostname?

Host: example.com

Guests: git.example.com, www.example.com, psql.example.com

2
  • The host will only be able to forward to the guests if the initial request is coming in to the host. Is that the case?
    – Tim
    Dec 29, 2011 at 16:08
  • Yes, all requests come in to the host because the host's IP is the only public one.
    – Cojones
    Dec 29, 2011 at 16:12

3 Answers 3

8

Since you need to route based on hostname instead of port, the iptables solution of NAT'ing the traffic to the VMs is out.

What you're left with is running a web server in reverse proxy mode, that reads the request host header and proxies to the different private IPs based on the request's header.

Exact configuration will depend on which web server you use, and which web server you select will depend on what features you need (SSL?) as well as personal preference. Let me know which web server you'd prefer and I can edit the answer to include an example config, if needed.

edit: Basic nginx config:

http {

    # ...existing config basics... server_name, NOT servername

    server {
        listen 80;
        server_name git.example.com;
        location / {
            # git server IP below:
            proxy_pass http://10.x.x.x:80/;
            # re-send the host header - this may not be necessary
            proxy_set_header Host $host;
            # set the X-Forwarded-For header, so that the public IP of the client is available to the backend server
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
    server {
        listen 80;
        server_name psql.example.com;
        location / {
            # psql server IP below:
            proxy_pass http://10.x.x.x:80/;
            # re-send the host header - this may not be necessary
            proxy_set_header Host $host;
            # set the X-Forwarded-For header, so that the public IP of the client is available to the backend server
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
    server {
        listen 80;
        server_name www.example.com;
        location / {
            # www server IP below:
            proxy_pass http://10.x.x.x:80/;
            # re-send the host header - this may not be necessary
            proxy_set_header Host $host;
            # set the X-Forwarded-For header, so that the public IP of the client is available to the backend server
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}
8
  • All guests have nginx running so I'd go that.
    – Cojones
    Dec 29, 2011 at 16:20
  • Clear answer and similar to what I was thinking. Go with this IMO.
    – Tim
    Dec 29, 2011 at 16:28
  • @Cojones Edited in a basic nginx config outline. Dec 29, 2011 at 16:34
  • Since there's no other way then that I guess I'll have to use that. Thanks a lot for the config!
    – Cojones
    Dec 29, 2011 at 16:43
  • Do you know anything about performance issues? Is it wise to use this approach in a production environment with heavy traffic?
    – Cojones
    Dec 29, 2011 at 17:02
0

You have to install on a host, which have access to the internet, web server and use "name-based virtual hosts configuration" (try to use in google with name of yours web server). Every name-based virtuals have to be a proxy for one virtual server. You can use apache, nginx, lighttpd, whenever you choose...

2
  • That's probably the only solution to my problem, right? Some forwarding would be better but I guess I'll have to proxy it then. Thanks!
    – Cojones
    Dec 29, 2011 at 16:42
  • If destination host don't have a public IP address, you cannot use forwarding, but only proxying/reverse-proxying.
    – Jan Marek
    Dec 29, 2011 at 16:50
0

Bridge all the connections. That way your guests can acquire IP on same network as host. Now add "A" record for these three guests in DNS.

Keep in mind that if request is meant for git.example.com, it will never come to example.com unless you have a "CNAME" set for the same.

[EDIT on the basis of comment]
Since you cannot use DNS, I would recommend not running Virtual machines at all. Instead create some virtual hosts and use them . In your nginx just define multiple server_name. Check nginx wiki for an example.

2
  • The guests do have access to the internet but only have private IP addresses since I only got one from my provider which is in use by the host. So I can't really use the DNS solution...
    – Cojones
    Dec 29, 2011 at 16:13
  • Yeah, I know about the virtual hosts and I told my client about it but he insisted on using VMs... any other idea?
    – Cojones
    Dec 29, 2011 at 16:41

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .