IPv6 adoption in the Asia-Pacific region is among the highest globally — China, Japan, India, and several ASEAN countries have IPv6 penetration rates exceeding 50% on mobile networks. Enabling IPv6 on your Hong Kong VPS gives you a dual-stack server that serves users on both protocols, future-proofs your infrastructure, and allows access to the growing number of IPv6-only endpoints and services.
Why IPv6 Matters for Asia-Pacific VPS
- China mobile networks — China Mobile, China Unicom, and China Telecom have deployed IPv6 extensively on mobile networks. Many Chinese mobile users are assigned IPv6 addresses by default
- IPv4 exhaustion — APNIC (Asia-Pacific NIC) ran out of IPv4 addresses years ago; new networks in ASEAN increasingly deploy IPv6-first
- Google ranks IPv6-accessible sites slightly higher — minor factor but consistent with Google’s preference for modern infrastructure
- Security benefit — each VPS receives a unique /64 or /48 IPv6 prefix; no NAT traversal issues for peer-to-peer or VoIP applications
Step 1: Verify IPv6 Assignment
<code"># Check if your VPS already has IPv6 assigned ip -6 addr show # Look for an inet6 address that is NOT fe80:: (link-local) # Example: 2401:0000:1234:5678::1/64 — this is a public IPv6 address # Test external IPv6 connectivity ping6 ipv6.google.com # Or curl -6 https://ipv6.icanhazip.com
If your VPS has no public IPv6 address, contact Server.HK support to request IPv6 allocation for your instance — most plans support it.
Step 2: Enable IPv6 in sysctl
<code"># If you disabled IPv6 in the security hardening guide, re-enable it: sed -i 's/net.ipv6.conf.all.disable_ipv6 = 1/net.ipv6.conf.all.disable_ipv6 = 0/' \ /etc/sysctl.d/99-security.conf sed -i 's/net.ipv6.conf.default.disable_ipv6 = 1/net.ipv6.conf.default.disable_ipv6 = 0/' \ /etc/sysctl.d/99-security.conf sed -i 's/net.ipv6.conf.lo.disable_ipv6 = 1/net.ipv6.conf.lo.disable_ipv6 = 0/' \ /etc/sysctl.d/99-security.conf # IPv6 security settings to keep cat >> /etc/sysctl.d/99-ipv6.conf << 'EOF' # Accept router advertisements (required for SLAAC addressing) net.ipv6.conf.all.accept_ra = 1 net.ipv6.conf.default.accept_ra = 1 # Disable IPv6 forwarding (unless running WireGuard/VPN) net.ipv6.conf.all.forwarding = 0 # Disable accept_redirects net.ipv6.conf.all.accept_redirects = 0 net.ipv6.conf.default.accept_redirects = 0 EOF sysctl -p /etc/sysctl.d/99-ipv6.conf sysctl -p /etc/sysctl.d/99-security.conf
Step 3: Configure Static IPv6 Address (If Not Auto-Assigned)
<code"># If your provider assigns IPv6 via SLAAC, it may already work.
# For manual/static configuration:
# Find your network interface name
ip link show | grep -v lo
# Ubuntu 22.04+ uses Netplan
cat >> /etc/netplan/01-netcfg.yaml << 'EOF'
ethernets:
eth0: # Replace with your actual interface name
addresses:
- YOUR_IPV6_ADDRESS/64 # e.g., 2401:xxxx:xxxx::1/64
gateway6: YOUR_IPV6_GATEWAY # e.g., 2401:xxxx:xxxx::
nameservers:
addresses:
- 2606:4700:4700::1111 # Cloudflare IPv6 DNS
- 2001:4860:4860::8888 # Google IPv6 DNS
EOF
netplan apply
# Verify
ip -6 addr show eth0
ping6 -c 3 ipv6.google.comStep 4: Add IPv6 DNS Records
In your DNS provider, add AAAA records pointing to your IPv6 address:
| Record Type | Name | Value |
|---|---|---|
| AAAA | yourdomain.com | 2401:xxxx:xxxx::1 |
| AAAA | www.yourdomain.com | 2401:xxxx:xxxx::1 |
| AAAA | api.yourdomain.com | 2401:xxxx:xxxx::1 |
<code"># Verify DNS propagation dig AAAA yourdomain.com +short # Should return your IPv6 address # Test IPv6 web access curl -6 https://yourdomain.com
Step 5: Configure Nginx for Dual-Stack
<code"># Update Nginx server blocks to listen on both IPv4 and IPv6
cat > /etc/nginx/sites-available/yourdomain.com << 'EOF'
server {
listen 80;
listen [::]:80; # IPv6
server_name yourdomain.com www.yourdomain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2; # IPv6
server_name yourdomain.com www.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
# Log real client IP (works for both IPv4 and IPv6)
real_ip_header X-Forwarded-For;
set_real_ip_from 0.0.0.0/0;
set_real_ip_from ::/0;
location / {
# Your existing configuration
}
}
EOF
nginx -t && systemctl reload nginx
# Verify IPv6 serving
curl -6 -sI https://yourdomain.com | head -3Step 6: Configure UFW for IPv6
<code"># Verify UFW is configured for IPv6
grep "IPV6=yes" /etc/default/ufw || {
sed -i 's/IPV6=no/IPV6=yes/' /etc/default/ufw
echo "IPV6=yes added to UFW config"
}
ufw disable && ufw enable
# UFW rules automatically apply to both IPv4 and IPv6
# Verify IPv6 rules
ufw status verbose | grep v6ip6tables Manual Rules (if not using UFW)
<code"># If managing iptables directly, add matching ip6tables rules: ip6tables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT ip6tables -A INPUT -p icmpv6 -j ACCEPT # Essential — don't block ICMPv6 ip6tables -A INPUT -p tcp --dport 22222 -j ACCEPT ip6tables -A INPUT -p tcp --dport 80 -j ACCEPT ip6tables -A INPUT -p tcp --dport 443 -j ACCEPT ip6tables -A INPUT -j DROP # Persist rules apt install -y iptables-persistent netfilter-persistent save
Critical: Never block ICMPv6 traffic. IPv6 depends on ICMPv6 for neighbor discovery (the IPv6 equivalent of ARP) — blocking it breaks IPv6 connectivity entirely.
Step 7: Configure SSH for IPv6
<code"># In /etc/ssh/sshd_config — listen on both protocols: ListenAddress 0.0.0.0 # IPv4 ListenAddress :: # IPv6 (add this line) systemctl reload sshd # Test SSH over IPv6 ssh -6 user@YOUR_IPV6_ADDRESS -p 22222
Step 8: Application Configuration
Node.js — Listen on IPv6
<code"># Express.js — bind to all interfaces (IPv4 + IPv6)
app.listen(3000, '::', () => {
console.log('Listening on IPv4 and IPv6 port 3000');
});
// Or explicitly bind to :: (IPv6 wildcard, which also accepts IPv4 on Linux)
const server = http.createServer(app);
server.listen(3000, '::');PostgreSQL — Accept IPv6 Connections
<code"># In /etc/postgresql/16/main/postgresql.conf: listen_addresses = 'localhost, ::1' # Add IPv6 loopback # In pg_hba.conf — add IPv6 localhost entry: host all all ::1/128 scram-sha-256
Redis — Bind to IPv6 Loopback
<code"># In /etc/redis/redis.conf: bind 127.0.0.1 ::1 # Both IPv4 and IPv6 loopback
Step 9: Test Dual-Stack Functionality
<code"># Comprehensive dual-stack test echo "=== IPv6 Configuration Test ===" echo "Public IPv6 address:" curl -6 -s https://ipv6.icanhazip.com echo "IPv6 DNS resolution:" dig AAAA yourdomain.com +short echo "IPv6 HTTPS access:" curl -6 -sI https://yourdomain.com | grep HTTP echo "IPv4 HTTPS access (should still work):" curl -4 -sI https://yourdomain.com | grep HTTP echo "IPv6 ping:" ping6 -c 3 yourdomain.com | tail -3 echo "" echo "Dual-stack test complete"
Troubleshooting Common IPv6 Issues
| Problem | Likely Cause | Fix |
|---|---|---|
| ping6 works, HTTPS fails | Nginx not listening on IPv6 | Add listen [::]:443 to Nginx config |
| IPv6 address disappears on reboot | Not persisted in Netplan/interfaces | Add static IPv6 to Netplan config |
| IPv6 connectivity but no DNS | IPv6 DNS not configured | Add AAAA records to your DNS zone |
| Certbot fails for IPv6 domain | HTTP-01 challenge only reaches IPv4 | Use DNS-01 challenge or ensure both stack reach port 80 |
| Application won’t bind to IPv6 | App bound to 0.0.0.0 not :: | Change bind address to :: in app config |
Conclusion
Enabling IPv6 on your Hong Kong VPS takes under an hour and prepares your infrastructure for Asia-Pacific networks that are increasingly IPv6-first. The AAAA DNS records, dual-stack Nginx configuration, and UFW IPv6 rules together ensure users on IPv6-only mobile networks — a growing segment in China, Japan, and India — can reach your applications without fallback latency penalties.
Enable IPv6 on your VPS: Browse Server.HK Hong Kong VPS plans — contact support to request IPv6 allocation for your existing or new VPS instance.