Introduction
Running services on an IPv6-only VPS offers significant advantages including reduced costs, improved performance, and future-proofing your infrastructure. However, exposing these services to the broader internet—where many users still rely on IPv4—presents a unique challenge.
This tutorial demonstrates how to securely expose web services from an IPv6-only Ubuntu 24.04 VPS using Cloudflare Tunnel for IPv4 accessibility and Caddy as a reverse proxy. You’ll learn to create a robust, production-ready setup that handles SSL termination, automatic certificate management, and seamless IPv4/IPv6 dual-stack connectivity.
Prerequisites
Before starting this tutorial, ensure you have:
- An IPv6-only Ubuntu 24.04 VPS with at least 1GB RAM and 1 vCPU
- Root or sudo access to your VPS
- A domain name with DNS management access
- A Cloudflare account (free tier sufficient)
- Basic familiarity with command line operations
- A web service to expose (we’ll use a simple HTTP server as an example)
Note: This tutorial assumes your VPS already has IPv6 connectivity configured. If you need help setting up an IPv6-only VPS, refer to our comprehensive guide on deploying IPv6-only Ubuntu VPS.
Step-by-Step Tutorial
Step 1: Update System and Install Dependencies
First, update your Ubuntu 24.04 system and install necessary packages:
sudo apt update && sudo apt upgrade -y
sudo apt install curl wget gnupg2 software-properties-common -y
Step 2: Install Caddy Web Server
Install Caddy using the official repository:
# Add Caddy repository
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
# Install Caddy
sudo apt update
sudo apt install caddy -y
Verify the installation:
caddy version
Step 3: Set Up a Sample Web Service
Create a simple HTTP service that we’ll expose through our tunnel:
# Create a simple HTML file
sudo mkdir -p /var/www/html
echo '<!DOCTYPE html>
<html>
<head><title>IPv6 Service Demo</title></head>
<body>
<h1>Hello from IPv6-only VPS!</h1>
<p>This service is running on an IPv6-only server.</p>
</body>
</html>' | sudo tee /var/www/html/index.html
# Start a simple HTTP server on port 8080
sudo python3 -m http.server 8080 --directory /var/www/html &
Step 4: Configure Caddy Reverse Proxy
Create a Caddyfile configuration:
sudo nano /etc/caddy/Caddyfile
Add the following configuration (replace yourdomain.com with your actual domain):
yourdomain.com {
reverse_proxy localhost:8080
# Security headers
header {
# Enable HSTS
Strict-Transport-Security max-age=31536000;
# Prevent clickjacking
X-Frame-Options DENY
# Content type sniffing protection
X-Content-Type-Options nosniff
}
# Logging
log {
output file /var/log/caddy/access.log {
roll_size 100mb
roll_keep 3
}
}
}
Create the log directory and start Caddy:
sudo mkdir -p /var/log/caddy
sudo systemctl enable caddy
sudo systemctl start caddy
sudo systemctl status caddy
Step 5: Install Cloudflare Tunnel (cloudflared)
Download and install the latest version of cloudflared:
# Download cloudflared for ARM64 or AMD64 (adjust URL based on your architecture)
wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
# Install the package
sudo dpkg -i cloudflared-linux-amd64.deb
# Verify installation
cloudflared version
Step 6: Authenticate with Cloudflare
Authenticate cloudflared with your Cloudflare account:
cloudflared tunnel login
This command will open a browser window. Select the domain you want to use for the tunnel.
Step 7: Create and Configure the Tunnel
Create a new tunnel:
# Create tunnel (replace 'my-ipv6-tunnel' with your preferred name)
cloudflared tunnel create my-ipv6-tunnel
# Note the tunnel UUID from the output
Create a configuration file for the tunnel:
sudo nano ~/.cloudflared/config.yml
Add the following configuration (replace values with your tunnel UUID and domain):
tunnel: YOUR_TUNNEL_UUID
credentials-file: /root/.cloudflared/YOUR_TUNNEL_UUID.json
ingress:
- hostname: yourdomain.com
service: http://localhost:80
- service: http_status:404
Step 8: Configure DNS and Route Traffic
Create a CNAME record pointing to your tunnel:
cloudflared tunnel route dns my-ipv6-tunnel yourdomain.com
Step 9: Run the Tunnel as a System Service
Install the tunnel as a system service:
sudo cloudflared service install
sudo systemctl enable cloudflared
sudo systemctl start cloudflared
sudo systemctl status cloudflared
Step 10: Test Your Setup
Test both IPv4 and IPv6 connectivity:
# Test from IPv4-only network
curl -4 https://yourdomain.com
# Test from IPv6 network
curl -6 https://yourdomain.com
# Check tunnel status
cloudflared tunnel info my-ipv6-tunnel
Best Practices
Security Considerations
- Firewall Configuration: Since your services are exposed through Cloudflare Tunnel, configure your firewall to only allow essential connections. Consider deploying CrowdSec for enhanced protection.
- SSL/TLS: Always use HTTPS. Caddy automatically manages Let’s Encrypt certificates, but ensure your tunnel configuration uses HTTPS endpoints.
- Access Control: Implement Cloudflare Access policies for sensitive applications.
- Regular Updates: Keep both Caddy and cloudflared updated to the latest versions.
Performance Optimization
- Caching: Configure appropriate caching headers in your Caddy configuration for static content.
- Compression: Enable gzip compression in Caddy for better performance over slower connections.
- Monitoring: Set up monitoring for both your tunnel and web services to ensure high availability.
- Resource Management: Monitor CPU and memory usage, especially if running multiple services. Consider our guide on VPS memory management.
Scaling Considerations
For production environments, consider:
- Running multiple tunnel instances for redundancy
- Using load balancing features in Cloudflare
- Implementing health checks for your backend services
- Setting up automated backups for your configuration files
Conclusion
You’ve successfully set up a robust solution for exposing services from an IPv6-only VPS using Cloudflare Tunnel and Caddy. This configuration provides several key benefits:
- Universal accessibility through IPv4/IPv6 dual-stack support
- Automatic SSL certificate management with Caddy
- Enhanced security through Cloudflare’s edge network
- Cost efficiency of IPv6-only infrastructure
This setup scales well for multiple services and provides a solid foundation for modern web applications. Whether you’re running microservices, APIs, or web applications, this tunnel configuration ensures reliable global connectivity.
Looking to deploy your own IPv6-only infrastructure? Explore our high-performance VPS solutions with native IPv6 support in Singapore, Sydney, and Amsterdam, featuring EPYC Milan processors and enterprise-grade NVMe storage.




