Configuring IPv6 on VPS and Dedicated Servers
Level: Beginner / Intermediate
Estimated time: ~30 minutes
Goal: Enable and setup ipv6 dedicated server or VPS networking so the server is reachable over IPv6 and all network services work correctly with the new address.
Introduction
Your INTROSERV server likely already has an IPv6 address assigned - it just isn't configured yet. In this ipv6 network setup vps guide, you will enable ipv6 linux server networking, assign a static IPv6 address, perform an ipv6 gateway configuration linux setup, and verify connectivity. The guide covers Ubuntu (Netplan), Debian (/etc/network/interfaces), and AlmaLinux (nmcli).
What is IPv6?
IPv6 (Internet Protocol version 6) is the current generation of the Internet Protocol, designed to replace IPv4. The most important practical differences for server administrators:
- An IPv6 address is 128 bits long, written as eight groups of four hexadecimal digits separated by colons:
2001:db8:85a3::8a2e:370:7334. - A Global Unicast Address (GUA) is the IPv6 equivalent of a public IPv4 address - routable on the internet. Your VPS will be assigned one of these.
- A link-local address is automatically assigned to every IPv6-capable interface (prefix
fe80::/10). It is not routable beyond the local segment, but it is required for neighbor discovery and routing protocols. - A subnet (IPv6 prefix) defines which part of the address identifies the network. For a typical VPS, you will see a
/64or/128prefix. - The default gateway (IPv6) is the router your server sends packets to when the destination is not on the local link. Your provider will supply this address.
Prerequisites
Before you begin, make sure the following conditions are met:
- Operating system: Ubuntu 20.04/22.04/24.04 LTS, Debian 11/12/13, or AlmaLinux/RHEL 8/9/10
- Access: sudo or root access to the server via SSH
- IPv6 allocation: An IPv6 address, subnet prefix, and default gateway provided by your hosting provider. Find these in your control panel before starting.
- Required knowledge: Confident use of the Linux command line and basic configuration file editing
On INTROSERV, you can find your assigned IPv6 address, prefix, and gateway in the Client Area - navigate to your service, then open the Network or IP Addresses tab. INTROSERV VPS plans typically receive a /112 prefix, while dedicated servers receive a /64 prefix. If no IPv6 address is listed, contact INTROSERV support to request allocation.
Step 1: Check the current IPv6 state
Before touching any configuration, see what the kernel already knows.
Run:
ip -6 addr show
Expected output on a server with no IPv6 configuration applied yet:
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 state UNKNOWN inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP inet6 fe80::250:56ff:fe00:1/64 scope link valid_lft forever preferred_lft forever
The fe80:: address is the link-local address - automatically assigned by the kernel regardless of configuration. The absence of a scope global entry means no Global Unicast Address is configured yet.
Also check whether IPv6 is enabled in the kernel:
sudo sysctl net.ipv6.conf.all.disable_ipv6
On Debian 13, regular users do not have /usr/sbin in their $PATH, so running sysctl without sudo will return command not found. Furthermore, a minimal Debian 13 installation does not include sudo by default. You will need to switch to the root user (su -), install sudo (apt install sudo), and add your user to the sudoers group before proceeding.
Expected output:
net.ipv6.conf.all.disable_ipv6 = 0
A value of 0 means IPv6 is enabled. If you see 1, IPv6 has been disabled at the kernel level.
To re-enable it temporarily:
sudo sysctl -w net.ipv6.conf.all.disable_ipv6=0
To make it permanent, check /etc/sysctl.conf or files in /etc/sysctl.d/ for a line reading net.ipv6.conf.all.disable_ipv6 = 1 and remove or comment it out, then run:
sudo sysctl -p
Step 2: Find your interface name
You need the exact name of your public network interface before editing any configuration file.
Run:
ip -br link
Expected output:
lo UNKNOWN 00:00:00:00:00:00 <LOOPBACK,UP,LOWER_UP> eth0 UP 00:50:56:00:00:01 <BROADCAST,MULTICAST,UP,LOWER_UP>
The interface in state UP with a MAC address is your primary interface. Common names are eth0, ens3, ens18, ens33, ens160 (common on VMware and modern kernels), and similar ensXX/enpXsX variations. Use the exact name that ip -br link shows in all configuration steps below.
Step 3: Configure a static IPv6 address
The configuration method depends on your distribution. Ubuntu 18.04 and later use Netplan; Debian uses /etc/network/interfaces by default; AlmaLinux uses NetworkManager or interface scripts under /etc/sysconfig/network-scripts/.
Gather the following values from your provider's control panel before proceeding:
| Field | Example |
|---|---|
| IPv6 address |
2001:db8:1000::10
|
| Prefix length |
64
|
| Default gateway (IPv6) |
2001:db8:1000::1
|
Replace these example values with the real ones throughout the steps below.
3.1 Ubuntu (Netplan)
Ubuntu uses netplan ipv6 configuration. Configuration files live in /etc/netplan/.
First, list the contents of the /etc/netplan/ directory to find your configuration file:
ls /etc/netplan/
A hardcoded filename like 00-installer-config.yaml does not exist on most VPS. On cloud-init images, it is typically named 50-cloud-init.yaml. Use the real filename found from the previous command in the steps below.
Back up the existing file (replace 50-cloud-init.yaml with your actual filename):
sudo cp /etc/netplan/50-cloud-init.yaml /etc/netplan/50-cloud-init.yaml.bak
Open the file:
sudo nano /etc/netplan/50-cloud-init.yaml
Add the addresses and routes blocks under your interface. A complete file with both IPv4 (already configured) and the new static IPv6 address setup looks like this:
network: version: 2 ethernets: eth0: addresses: - 203.0.113.10/24 # existing IPv4 address - 2001:db8:1000::10/64 # new IPv6 address routes: - to: default via: 203.0.113.1 # existing IPv4 gateway - to: default via: 2001:db8:1000::1 # IPv6 default gateway nameservers: addresses: - 8.8.8.8 - 2001:4860:4860::8888 # Google public DNS over IPv6
If your server receives its IPv4 address via DHCP (which is common for many fresh VPS setups), your file will look slightly different. Do not blindly copy the static IPv4 setup above, or you will lose your working IPv4 connection. Here is an example with dhcp4: true:
network: version: 2 ethernets: eth0: dhcp4: true addresses: - 2001:db8:1000::10/64 # new IPv6 address routes: - to: default via: 2001:db8:1000::1 # IPv6 default gateway nameservers: addresses: - 2001:4860:4860::8888 # Google public DNS over IPv6
Netplan uses YAML. Indentation is significant - use spaces, never tabs. A single misaligned line will cause the configuration to fail silently or refuse to apply.
Test the configuration before applying it:
sudo netplan try
netplan try applies the configuration with a 120-second timer. If you do not confirm, it automatically reverts - safe to run over SSH. If the output looks correct, confirm:
# Press Enter when prompted, or type: sudo netplan apply
Always use netplan try instead of netplan apply when working over SSH. If the new configuration breaks your connection, the automatic revert will bring you back in.
3.2 Debian (/etc/network/interfaces)
On Debian, the classic way to add IPv6 to /etc/network/interfaces is to add a second iface stanza for the same interface using the inet6 family.
Back up first:
sudo cp /etc/network/interfaces /etc/network/interfaces.bak
Open the file:
sudo nano /etc/network/interfaces
Your existing IPv4 block will look something like:
auto eth0 iface eth0 inet static address 203.0.113.10 netmask 255.255.255.0 gateway 203.0.113.1
Add the IPv6 stanza immediately below it:
iface eth0 inet6 static address 2001:db8:1000::10 netmask 64 gateway 2001:db8:1000::1
Do not add a second auto eth0 line. The single auto directive brings up both inet and inet6 stanzas when the interface initializes.
Apply the new configuration without a full reboot:
sudo ifdown eth0 && sudo ifup eth0
Running ifdown eth0 over SSH drops your connection. Execute this command from the provider's serial/web console, or use ifreload -a. Note that ifreload -a requires the ifupdown2 package, which is not included in the base Debian installation. Install it via sudo apt install ifupdown2 to reload interfaces without dropping active sessions.
3.3 AlmaLinux / RHEL (nmcli)
On AlmaLinux and RHEL 8/9, NetworkManager is the default. Use nmcli to add the IPv6 address without editing files by hand.
Find your connection name:
nmcli connection show
Expected output:
NAME UUID TYPE DEVICE eth0 5fb06bd0-0bb0-7ffb-45f1-d6edd65f3e03 ethernet eth0
Add the static IPv6 address setup:
sudo nmcli connection modify eth0 \ ipv6.method manual \ ipv6.addresses "2001:db8:1000::10/64" \ ipv6.gateway "2001:db8:1000::1"
Apply the configuration without dropping the SSH connection:
sudo nmcli device reapply eth0
Step 4: Test IPv6 connectivity
Once the configuration is applied, verify that the address is assigned and that routing works.
4.1 Verify the address is assigned
ip -6 addr show eth0
Expected output:
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP inet6 2001:db8:1000::10/64 scope global valid_lft forever preferred_lft forever inet6 fe80::250:56ff:fe00:1/64 scope link valid_lft forever preferred_lft forever
You should see your Global Unicast Address with scope global. The link-local address (scope link) will also be present.
4.2 Verify the default gateway
ip -6 route show
Expected output:
2001:db8:1000::/64 dev eth0 proto kernel metric 100 default via 2001:db8:1000::1 dev eth0 proto static metric 100
The default via line confirms your IPv6 default gateway is correctly configured.
4.3 Test IPv6 connectivity
To test IPv6 connectivity to a known public host, use ping6 (or ping -6 on newer systems):
ping6 -c 4 2606:4700:4700::1111
Expected output:
PING 2606:4700:4700::1111(2606:4700:4700::1111) 56 data bytes 64 bytes from 2606:4700:4700::1111: icmp_seq=1 ttl=57 time=1.23 ms 64 bytes from 2606:4700:4700::1111: icmp_seq=2 ttl=57 time=1.19 ms 64 bytes from 2606:4700:4700::1111: icmp_seq=3 ttl=57 time=1.21 ms 64 bytes from 2606:4700:4700::1111: icmp_seq=4 ttl=57 time=1.20 ms
If ping6 fails but the address is assigned, the problem is almost always one of three things: the default gateway is wrong, your provider's firewall blocks ICMPv6, or the IPv6 allocation has not been activated on their side.
You can also test connectivity from the outside using a public tool such as https://ipv6-test.com. Enter your server's IPv6 address and run a reachability check.
4.4 Verify DNS resolution over IPv6
First, ensure you have the dig utility installed.
On AlmaLinux 10, dig is not included in the base installation:
sudo dnf install -y bind-utils
On minimal Debian images, the package may also be missing:
sudo apt install -y dnsutils
Check that your server can resolve hostnames using the IPv6 DNS server:
dig AAAA google.com @2001:4860:4860::8888
A successful response will include an ANSWER SECTION with one or more AAAA records.
Step 5: Adjust the firewall for IPv6
If your server runs a software firewall, you must explicitly allow IPv6 traffic. By default, many firewall configurations only cover IPv4.
At INTROSERV, all ports are open by default at the network level for VPS and dedicated servers, with a small set of exceptions (email ports 25, 465, 587, 2525 and LDAP port 389 are filtered to protect IP reputation). This means you do not need to open ports in a provider-side firewall for standard web traffic or SSH. You are still responsible for the OS-level firewall running on your server. See the Network Security & Port Filtering guide for details.
Ubuntu/Debian (UFW)
On Debian, UFW is not included in the base installation. Install it first if necessary:
sudo apt install -y ufw
UFW applies rules to both IPv4 and IPv6 when IPV6=yes is set in its configuration. Verify:
grep IPV6 /etc/default/ufw
Expected output:
IPV6=yes
If it reads IPV6=no, open the file and change it:
sudo nano /etc/default/ufw
Then reload UFW:
sudo ufw reload
If UFW has not been activated yet, ufw reload will return Firewall not enabled. This is fine; the rules will be applied automatically when you eventually enable the firewall with sudo ufw enable.
Your existing ufw allow rules (SSH, HTTP, HTTPS) will now apply to IPv6 as well.
AlmaLinux / RHEL (firewalld)
firewalld handles IPv6 natively through its zone model. If your interface is in the correct zone, IPv6 traffic is managed automatically. Verify:
sudo firewall-cmd --get-active-zones
For services like SSH and HTTPS:
sudo firewall-cmd --permanent --add-service=ssh sudo firewall-cmd --permanent --add-service=https sudo firewall-cmd --reload
If a service is already allowed in the zone, firewall-cmd will output Warning: ALREADY_ENABLED. This is normal and not an error. On AlmaLinux, ssh and dhcpv6-client are allowed in the public zone by default.
ICMPv6 is required for IPv6 to function correctly. It handles neighbor discovery, path MTU discovery, and router advertisements - the IPv6 equivalents of ARP. Do not block ICMPv6 entirely. Most firewall tools allow it by default; if you are writing raw nftables or ip6tables rules, explicitly permit icmpv6.
Rollback
Ubuntu (Netplan)
Restore the backup and apply (replace 50-cloud-init.yaml with your actual filename):
sudo cp /etc/netplan/50-cloud-init.yaml.bak /etc/netplan/50-cloud-init.yaml sudo netplan apply
Debian (/etc/network/interfaces)
Restore the backup:
sudo cp /etc/network/interfaces.bak /etc/network/interfaces sudo ifdown eth0 && sudo ifup eth0
AlmaLinux (nmcli)
Remove the IPv6 settings from the connection:
sudo nmcli connection modify eth0 ipv6.method auto sudo nmcli connection modify eth0 ipv6.addresses "" ipv6.gateway "" sudo nmcli connection modify eth0 ipv6.method ignore sudo nmcli device reapply eth0
NetworkManager does not allow setting ipv6.method ignore while static ipv6.addresses exist. Setting the method to auto first allows for proper clearing of the addresses.
Disable IPv6 system-wide (emergency)
If you need to shut off IPv6 entirely across all interfaces:
sudo sysctl -w net.ipv6.conf.all.disable_ipv6=1 sudo sysctl -w net.ipv6.conf.default.disable_ipv6=1
To make it persistent, add the following to /etc/sysctl.d/99-disable-ipv6.conf:
net.ipv6.conf.all.disable_ipv6 = 1 net.ipv6.conf.default.disable_ipv6 = 1
Then run sudo sysctl -p /etc/sysctl.d/99-disable-ipv6.conf.
Troubleshooting
Ping6 fails immediately with "Network unreachable"
The default gateway (IPv6) is missing or wrong. Run ip -6 route show and confirm the default via entry exists and matches the gateway from your provider's panel.
Address appears but scope is link only, not global
The address was added to the wrong interface, or the configuration file has a typo in the address or prefix. Re-read your provider's allocation carefully.
Netplan apply returns a parsing error
YAML indentation is off. Run cat -A /etc/netplan/50-cloud-init.yaml (or your actual filename) to reveal tab characters (shown as ^I) - replace them with spaces.
SSH drops after ifdown on Debian
Use the provider's web console or VNC/IPMI access to recover. Restore /etc/network/interfaces from backup and run ifup eth0.
UFW still blocks IPv6 after setting IPV6=yes
Rules added before the change were saved for IPv4 only. Run sudo ufw reset, then re-add your rules - they will now apply to both families.
The sudo ufw reset command is destructive. It resets all firewall rules to their defaults. Ensure you know which ports to re-allow (like SSH) before running it, so you do not lock yourself out.
Conclusion
That's it. Your INTROSERV server now has a working IPv6 address, a correctly configured default gateway, and a firewall that covers both protocol families. Next steps: request a PTR record through the INTROSERV Client Area, and update your Nginx or Apache virtual hosts to listen on the new IPv6 address.
Document Version: 1.0
Last Updated: May 2026
Owner: Technical Documentation Team