17

So I'm using digital ocean and nginx. I want to host multiple websites (my projects) but dont want to buy a domain for each one.

Is there a way to host multiple websites on nginx and digital ocean while accessing them using that one ip?

6
  • Host them on different folders (X.Y.Z.W/foo, X.Y.Z.W/bar)? Why can't you get domains for them? (You can assign the same IP to multiple domains)?
    – muru
    May 2, 2016 at 12:39
  • You would need multiple domains to do that. There is a free domain service, though: freenom.com gives you free .tk, .ml, .ga, .cf and .gq domains. May 2, 2016 at 12:39
  • @muru I think they don't want to spend money on multiple domains. They want some way to have multiple websites on one URL. May 2, 2016 at 12:40
  • @Zacharee1 they only need the one domain, and can do subdomains. If they refuse to do that, they'll have to do the evil IP-based method, which depending on the type of application/project they're using may not be able to support the 'subfolder' location methods.
    – Thomas Ward
    May 2, 2016 at 13:21
  • @ThomasW. I was thinking sub domains wouldn't be an option May 2, 2016 at 13:24

1 Answer 1

23

There's two ways to achieve this. Either you do everything by IP address, with subfolder locations, or you will need to buy one domain and then have multiple subdomains on that domain (subdomains shouldn't cost anything, if you purchase the domain, but check with your registrar).

I don't advise the IP-address method if only because it's very evil to have to remember IP addresses, and if you try sharing information to others, you also have the same problem of others having to remember the IP address.


The one-IP, many subfolders approach, without a domain name

NOTICE! We don't have any information about your projects you are working on. We need to know more to determine whether you can do this approach, as many web frameworks will not work without a true domain name tied to it.


WARNING: In ongoing testing of these examples, it was discovered that the "One domain, many subdirectories" approach does not take kindly to reverse-proxying data to the backend, as the requested URI will include the subdirectories within the URI; this might make backend servers have problems behaving properly.

On the nginx side, we need to do an 'evil' approach to this - one IP address, many docroots and subfolder locations. This is a very very evil approach and can cause a lot of problems with some web frameworks.

Assuming a default nginx install as a base from the repositories, then we have to create a site configuration to handle each project subdirectory request. Then we have to symlink it in the right location.

Create /etc/nginx/sites-available/my-projects with the following (use this as a template/guide - it assumes three projects with static HTML and no dynamic web applications in PHP or python or similar, and you can copy the individual location blocks and make new locations accordingly; it also assumes your server IP is 1.2.3.4).

server {
    listen 80 default_server;

    server_name 1.2.3.4;

    location / {
        return 410;  # Default root of site won't exist.
    }

    location /proj1/ {
        alias /var/www/proj1;
        try_files $uri $uri/ =404;

        # any additional configuration for non-static content
    }

    location /proj2/ {
        alias /var/www/proj2;
        try_files $uri $uri/ =404;

        # any additional configuration for non-static content
    }

    location /proj3/ {
        alias /var/www/proj3;
        try_files $uri $uri/ =404;

        # any additional configuration for non-static content
    }
}

Now we replace the default config (remove it) and add ours:

sudo rm /etc/nginx/sites-enabled/default
sudo ln -s /etc/nginx/sites-available/my-projects /etc/nginx/sites-enabled

And then restart the nginx service:

# If on 14.04, use this:
sudo service nginx restart

# If on 15.10 or newer, use this:
sudo systemctl restart nginx

The one-domain, multiple subdomains approach.

This answer section assumes you have one domain and multiple subdomains therein. If you do not have this, please clarify this in your question

With each nginx server {} block in the configuration, you will need to define the server name, and likely set a fourth server block as a 'catch all' for other requests.

Example: I have three projects, proj1, proj2, proj3. I have a domain called evil-projects.net (NOTE: Doesn't exist really). I want three different subdomains, one for each nginx configuration which will point to one project each. My server resides at 1.2.3.4, and it will serve all sites.

With the above scenario, we have two parts: domains and subdomains, and the server configuration.

(1): DNS Configuration

Set up your DNS at your host such that the following is true with the DNS records:

evil-projects.net  IN A  1.2.3.4
proj1.evil-projects.net  IN A  1.2.3.4
proj2.evil-projects.net  IN A  1.2.3.4
proj3.evil-projects.net  IN A  1.2.3.4

(2): NGINX configuration at server (1.2.3.4)

Now for your nginx configurations. I am assuming you are going to have the default nginx setups and the packages from the Repositories (I'm going to use 14.04 as a base example). We'll have four configuration files put into /etc/nginx/sites-available, first. You may need to use sudo when creating these files, as the folder in question is owned by root.

/etc/nginx/sites-available/catch-all - this will be the 'catch all' for any nonvalid domains. I like returning http error code 410 (GONE).

server {
    listen 80 default_server;

    server_name _;

    return 410;
}

Next, we set up the configuration for your sites/projects. I'm going to assume they're all static files, though. Each of these implies that you have different web directories for each project on the server as well (different 'document roots').

/etc/nginx/sites-available/proj1.evil-projects.net:

server {
    listen 80;

    server_name proj1.evil-projects.net;

    root /var/www/proj1;
    index index.htm index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

/etc/nginx/sites-available/proj2.evil-projects.net:

server {
    listen 80;

    server_name proj2.evil-projects.net;

    root /var/www/proj2;
    index index.htm index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

/etc/nginx/sites-available/proj3.evil-projects.net:

server {
    listen 80;

    server_name proj3.evil-projects.net;

    root /var/www/proj3;
    index index.htm index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

We then have to remove the 'default' configuration from /etc/nginx/sites-enabled, and add our own. Again, sudo is needed here.

sudo rm /etc/nginx/sites-enabled/default
sudo ln -s /etc/nginx/sites-available/proj1.evil-projects.net /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/proj2.evil-projects.net /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/proj3.evil-projects.net /etc/nginx/sites-enabled/

And then we restart the nginx process:

# If on 14.04, use this:
sudo service nginx restart

# If on 15.04 or newer, use this:
sudo systemctl restart nginx

Once DNS propagates, the sites will work as they should.

4
  • in this configuration where would you place blocks for proxy_cache ? Suppose proj1, proj2, proj3 have all same endpoints, with different roots, and want to cache response on distinct folders.
    – user305883
    May 18, 2017 at 8:54
  • @user305883 Sounds like that's a new question.
    – Thomas Ward
    May 18, 2017 at 12:28
  • 1
    The one IP, many sub folders approach is exactly what I want to do. However, I can't get this to work. I copied the code exactly and changed server_name for my IP. I also have 3 basic index.html files at locations /var/www/proj1 and /var/www/proj2 and /var/www/proj3 where the permissions have been set to 755. But when I navigate to myip/proj1 I see the same 410 page as if I pass no /proj1. What's going wrong? It's 2020 and I'm using Nginx 1.10.3 - has the syntax changed?
    – SLater01
    Feb 13, 2020 at 23:49
  • @SLater01 the syntax remains the same, but you need to ask your own question for that as it's an entirely separate issue to this answer, and needs a lot more time/effort/details than comments can provide. However, you probably need to read the nice big yellow box in that section which indicates that most websites/services don't behave that way so it won't like being served out of a subdirectory and not a root domain.
    – Thomas Ward
    Feb 14, 2020 at 0:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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