How To Run Multiple Sites From One Server and Give Each One Their Own IPv6 Address

It's often the case that one server or VPS can easily run multiple sites, each with their own domain names. Even though it sacrifices some security, SNI is pretty much what we've collectively chosen to use to make this possible while still using TLS (HTTPS, SSL).

This is largely necessary because it's the norm for multiple sites to share the same IP address. When running multiple sites from a VPS, it's possible for this to mean anyone visiting one of your sites can see the TLS certificates for the other domains you serve up, and regardless, it's very easy to simply perform a reverse lookup on an IP address to look at all the domains pointing to it as DNS records are public.

And this may just be me, but it feels a bit “hacky.” Whenever someone visits your site, the browser can work out which is the correct vhost to talk to thanks to SNI, but having a bunch of rejected and invalid TLS certs coming from that same IP is just not a “clean” setup.

It's not an issue if you only run multiple subdomains, but for multiple domain names pointing to totally different sites, you may well want each one to just have its own IP address without having to pay extra money. Indeed some hosts will allow you to assign extra IPv4 addresses to your VPS, but the cost per address is usually not much less than simply setting up a second low end VPS. This isn't because they're being greedy, it's because we have totally run out of fresh IPv4 addresses since 2018, so the remaining ones we have left to recycle are a hot commodity and your host had to pay a lot of money for them. Some hosts now even offer IPv6 only base plans. It is likely that the cost of web hosting in all forms is being artificially inflated by the high cost of IPv4 addresses. It'll be a great day indeed when we finally complete the transition to IPv6.

While we're not fully transitioned yet, thankfully IPv6 adoption has rapidly increased in recent years, and we largely live on an internet where IPv4 and IPv6 coexist.

As the number of IPv6 addresses is literally 340 trillion trillion trillion – that's 340,282,366,920,938,463,463,374,607,431,768,211,456 to be precise – it's safe to say hosts can hand them out a lot more liberally than the scarce IPv4's. It is normal for some hosts to even assign a full /64 block of IPv4 addresses to each user. Others aren't so generous, but will give you 10 per VPS and you can usually just ask for more if needed.

Point is – if you have one VPS and multiple websites, you can help usher your sites into the 21st century and give each site its own IP address thanks to IPv6.

Now, for obvious reasons I cannot give exact instructions on obtaining a set of IPv6 addresses for every single host in existence. It's worth checking your host's FAQ, help, or support pages or just searching “[name of host] IPv6” on your search engine of choice. You'll find the info you need.

Once you have assigned the IPv6 addresses to your VPS on the host's end, choose which one you want for which site and add one to each of your domain's AAAA records. This will be done wherever you registered your domain, but any domain registrar will allow you to set an AAAA record. These tell clients where to find your site through IPv6. As a tip, it's a good idea to set the TTL on any new DNS record to the lowest allowed – usually 300. This makes the new DNS record propagate throughout the internet much faster. You can increase this value after the initial propagation with no ill effect if you wish.

Finally, you will need to set them up on your actual VPS. I recommend ensuring you have a backup before doing this. It is a very simple process and I've never broken anything by doing it, but better safe than sorry!

So let's get to it.

Below is focused on Ubuntu, but I also include more general info as well so it's worth skimming even if you use another distro. Instructions for other distros are below.

Ubuntu and Ubuntu based distros

Ubuntu uses its own configuration format to manage this with YAML files, but the settings you're changing are pretty basic and universal across Linux so only the file path and configuration layout should differ.

But assuming you're using Ubuntu, open an SSH session and run:

sudo nano /etc/netplan50-cloud-init.yaml

If your VPS was preconfigured with IPv6 support, as mine from Stuxhost was, you should get a file that looks something like this:

# This file is generated from information provided by the datasource.  Changes
# to it will not persist across an instance reboot.  To disable cloud-init's
# network configuration capabilities, write a file
# /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following:
# network: {config: disabled}
network:
    version: 2
    ethernets:
        eth0:
            addresses:
            - 2001:dv8:c010:cd72::1/64
            - 2001:dv8:c010:cd72::420/64
            dhcp4: true
            gateway6: fe80::1
            match:
                macaddress: 69:00:00:a0:11:b1
            set-name: eth0

Ignore the message at the top, we'll be running a command to make our changes persistent afterwards.

The only change I had to make here is adding an extra IPv6 address, copying the original but changing the last section. How much you can change depends on how many addresses you were allotted.

I added /64 at the end of the IP to let my server know I was allotting an address from the /64 block allotted to me by my host. Notice that the IPv6 already listed also has /64 at the end, so this is a good way to tell how many addresses you have if your host doesn't make it clear elsewhere.

You will find a block of /64 IPv6 addresses is common as it's the minimum that can be allotted for multiple IPv6 addresses and, if your host allows you access to the whole thing, you have enough bits for a single IPv6 subnet. Putting it in those terms may not sound like much, but one IPv6 subnet gives you 18,446,744,073,709,551,616 addresses. If that's not enough for you I'd like to know just how specced up your VPS is!

Other hosts may have a file instead laid out like this:

network:
version: 2
ethernets:
    eth0:
	addresses:
	- 203.0.113.213/20
	- 192.0.2.11/16
	gateway4: 206.189.208.1
	match:
	    macaddress: 5e:5x:5a:2m:8p:le
	nameservers:
	    addresses:
	    - 67.207.67.2
	    - 67.207.67.3
	    search: []
	set-name: eth0

You will notice no mention of IPv6 at all here. Usually this is because the VPS was created with IPv6 disabled by default, so you need to add the settings yourself.

Thankfully this is also easy. The above example is from Digital Ocean, who provide the following instructions to add IPv6 support:

network:
version: 2
ethernets:
    eth0:
	addresses:
	- 203.0.113.213/20
	- substitute_your_primary_ipv6_address/64
	- 192.0.2.11/16
	gateway4: 206.189.208.1
	gateway6: substitute_your_ipv6_gateway
	match:
	    macaddress: 5e:5x:5a:2m:8p:le
	nameservers:
	    addresses:
	    - 67.207.67.2
	    - 67.207.67.3
	    - 2001:4860:4860::8844
	    - 2001:4860:4860::8888
	    search: []
	set-name: eth0

As you can see it's quite self-explanatory. Literally, they tell you where to add your IPv6 details. Only edit those bits. If these details are not filled in already, your host's help pages will tell you what they are or where to find them for your account.

In my examples there I added only one or two addresses. But if your host allows it, you can add many more IPv6 addresses like so:

            addresses:
            - 2001:dv8:c010:cd72::1/64
            - 2001:dv8:c010:cd72::420/64
            - 2001:dv8:c010:cd72::69/64
            - 2001:dv8:c010:cd72::123/64
            - 2001:dv8:c010:cd72::1337/64

And so on. As long as you can create those address allocations with your VPS provider, the sky's the limit.

Make sure everything is spaced correctly. Indentations matter in a YAML file! Ensure the new lines you add use the same number of spaces as the existing ones.

Now save the changes by hitting ctrl+O then enter and let's save the new config by running:

sudo netplan apply --debug

Again, self-explanatory. This command checks for errors in your config. If it finds none, it applies them to the system. If you get no feedback from that command, it means there was no errors and it worked.

Before rebooting, you may also wish to check IPv6 is enabled in your vhosts. For example in Nginx, you want them to be listening on both IPv4 and IPv6 by ensuring this second line exists:

  listen 443 ssl http2;
  listen [::]:443 ssl http2;

That second line just tells Nginx to listen for IPv6 connections. Without it, this won't work.

You should also add the same for port 80 if you have a redirect in place:

    listen 80;
    listen [::]:80;

Remember to check out my guide to a secure Nginx config if you haven't already!

Then just reboot:

sudo reboot

Debian and Debian based distros (except Ubuntu)

Much the same as above except you run:

sudo nano /etc/network/interfaces

You should add something like this:

iface eth0 inet6 static
    address substitute_your_primary_ipv6_address
    netmask 64
    gateway substitue_your_ipv6_gateway
    autoconf 0
    dns-nameservers 2001:4860:4860::8844 2001:4860:4860::8888 1.1.1.1 1.0.0.1

Yes, you need to add this whole block. This is a whole new section just for IPv6.

Some hosts do not require you to enter your own nameservers, in which case you add something more like this:

iface ens3 inet6 static
address 2001:db8:1000::100
netmask 64
up /sbin/ip -6 addr add dev ens3 2001:db8:1000::200

As you can see, the above setup also shows you how to add extra addresses. The last line is a second IPv6 address.

If your host does tell you to add nameservers, you can still add extra IPv6 addresses as above.

Once the setup is done you can simply run this to apply it:

sudo systemctl restart networking.service

Rebooting also works.

Wrapping it up

Assuming you set up the AAAA records and the vhosts correctly, and used IPv6 addresses within the block allotted by your host, it should all now “just work.” When the server comes back up it should accept IPv6 connections.

This is easy to check by just pasting your URL into a site like this. It'll confirm the right address comes back and if a connection to the server was successful.

Additionally, when you do an SSL Labs test (always a good thing to check up on) if there is an IPv6 record present it'll test it and show the address. If it's able to connect via IPv6 and run the test, you guessed it, IPv6 is working.

You can try this with all your domains and it'll hopefully work with all of them. If only one or two fail to connect, make sure you enabled IPv6 in the server or reverse proxy config. If it's possible to connect through IPv6 and your config looks okay but the site won't load up via IPv6, it could be an upstream issue with the web app you're reverse proxying to.

That would be out of scope for this tutorial, but in my experience you should be able to login to the account for that application and simply change the necessary config, or if it's a Docker install you can usually rebuild the Docker image, at which point it'll generate the internal server again and pick up you have IPv6 enabled this time. For more specific help check the docs of those projects.

Oh, and if you are reverse proxying S3 through Nginx, simply change the bucket URL to the dual-stack endpoint.

P.S. Seriously. Check out Bitcoin For The World.

#HTTPS #SSL #TLS #VPS #IPv4 #IPv6 #domains #Linux #Nginx #server #configuration #tutorial #guide