Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

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

share|improve this question
    
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 '11 at 16:08
    
Yes, all requests come in to the host because the host's IP is the only public one. –  Cojones Dec 29 '11 at 16:12
add comment

3 Answers

up vote 5 down vote accepted

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;
        }
    }
}
share|improve this answer
    
All guests have nginx running so I'd go that. –  Cojones Dec 29 '11 at 16:20
    
Clear answer and similar to what I was thinking. Go with this IMO. –  Tim Dec 29 '11 at 16:28
    
@Cojones Edited in a basic nginx config outline. –  Shane Madden Dec 29 '11 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 '11 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 '11 at 17:02
show 4 more comments

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...

share|improve this answer
    
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 '11 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 '11 at 16:50
add comment

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.

share|improve this answer
    
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 '11 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 '11 at 16:41
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.