
Hybrid cloud deployments often require secure, private connectivity across providers. Traditional VPNs rely on complex configurations and centralized gateways, which can introduce bottlenecks and single points of failure.
Headscale is an open-source, self-hosted control server for Tailscale, a mesh VPN built on the WireGuard protocol. Together, they enable peer-to-peer, encrypted tunnels between nodes without relying on a central gateway, giving you full control over authentication, device management, and network policies while maintaining low-latency, secure connectivity.
By deploying gateway nodes in each cloud and automating configuration with Terraform and Ansible, you can:
This guide walks you through setting up Headscale to establish a private connection between Vultr and AWS. The implementation leverages Terraform and Ansible to automate provisioning and configuration, minimizing manual effort and ensuring consistent deployments.
Before you begin, you need to:
Tailscale with Headscale allows you to self-host a mesh VPN connecting on-prem, site-to-site, or cloud-to-cloud environments. This guide provides instructions to establish a site-to-site mesh, where each site is a Gateway Node in either a Vultr region or an AWS region. The mesh connects to each cloud’s Virtual Private Cloud (VPC) to expose Client Nodes in each datacenter with the others over a private network.
tailnet peer or Tailscale client in each Vultr and AWS region to join the mesh network across multiple datacenters.tailnet routes from the gateway to Vultr client nodes, enabling cross-datacenter connectivity.This implementation is automated using Terraform, Ansible, and Cloud-Init, enabling consistent, repeatable deployments across Vultr and AWS with minimal manual configuration
This section provides steps to provision the required infrastructure using Terraform and configure instances post-deployment with the included Ansible playbooks. The following regions are used to demonstrate the peering setup:
You can add or remove regions as needed. The setup is flexible and allows multiple Vultr and AWS regions to be included in the mesh network.
Clone the GitHub repository.
Update the terraform.tfvars file with your credentials.
Populate your credentials and adjust regions if needed.
Populate the Vultr API Key and AWS Access Keys in the terraform.tfvars file to enable API access for provisioning resources.
Understanding how to adjust regions helps maintain network performance and allows scalable deployments.
vultr_regions and aws_regions maps to change deployment locations for gateway or client nodes.headscale_region to deploy the control server in a new region. The instance_plan and instance_os_id values are pre-selected to achieve maximum performance and ensure software compatibility.vultr_regions or aws_regions maps. Terraform automatically loops through all defined regions and provisions instances.ami_id for each AWS region to ensure the instances use the correct Ubuntu version. AWS provides different AMI IDs for the same OS in each region. This setup has been tested on Ubuntu 22.04, and using this version is recommended for consistency, security, and performance.Tips for Region Selection:
List available Vultr regions using the API to choose appropriate datacenter locations for your instances.
List all AWS regions with the AWS CLI to determine which regions to deploy your VPCs and instances.
Fetch the latest Ubuntu 22.04 AMI ID for a specific AWS region to ensure your instances use the up-to-date OS.
Initialize the Terraform working directory.
The command above sets up Terraform and downloads any required providers.
Review the execution plan.
Apply the Terraform manifests.
Your output should look similar to the one below:
When prompted, type yes to approve and apply the configuration. Provisioning may take up to 5 minutes depending on the number of regions.
Outputs:
These outputs provide important information about your deployed infrastructure:
Client and Gateway Summaries
client_summary: Contains details of all client nodes (Vultr and AWS), including Name, Private IP, Public IP, Provider, and Subnet. gateway_summary: Contains details of all gateway nodes with the same information.Headscale Control Server IP
headscale_control_server_ip: Shows the public IP of the Headscale control server, which coordinates the mesh network.Terraform generates a private key file, id_rsa, inside the terraform directory. You can use this key to SSH into the gateway and client nodes for verification or debugging.
Navigate to the Ansible directory:
Terraform automatically generates an inventory.yml file in this directory. Ansible uses this file to configure the mesh network, listing all Vultr and AWS gateway and client nodes.
Run the Ansible Playbook to configure the private network mesh.
This playbook uses the generated inventory.yml file to identify instances across Vultr and AWS and configures the Headscale and Tailscale nodes, creating a fully connected private mesh network.
To manually add more clients to the mesh network:
Vultr: During instance provisioning, select the vultr-x-aws-mesh-script startup script and choose the corresponding VPC under VPC Networks. The script automatically configures the instance and adds all OSPF-announced routes. This startup script currently supports only Debian and RHEL instances.
AWS: When provisioning, select the respective VPC. No additional installation is required because the VPC Route Table already contains the necessary routes.
After deployment, verify that all regions across Vultr and AWS are connected through the WireGuard-based mesh managed by Headscale. Use Ansible to benchmark both private and public paths, measuring latency, bandwidth, and overall mesh performance.
Run the provided Ansible playbook to execute iperf3 and ping tests between regions using both private and public IPs.
The network tests may take 5-10 minutes to complete, depending on the number of regions being tested.
After completion, the playbook creates a network_test_results/ directory which contains the following results files:
network_results.txt: Consolidated output of all tests, including latency and bandwidth for public and private paths.public_results_table.txt: Tabular summary of region-to-region performance over the public internet.private_results_table.txt: Tabular summary of private mesh performance via Headscale.Review the test results for the public internet performance between nodes.
Your output should be similar to the one below:
Review the Private IP test results to validate the performance over the Tailscale mesh.
Your output should be similar to the one below:
Public tests usually show higher speeds due to direct internet routing and optimized infrastructure. Private mesh tests use encrypted WireGuard tunnels, which add overhead and may reduce throughput.
You have successfully established a secure, multi-region private network between Vultr and AWS using Headscale and Tailscale. Terraform and Ansible automated provisioning and configuration, ensuring consistent deployments across all regions. Gateway and client nodes communicated over encrypted, low-latency tunnels, while FRRouting and VPC route tables provided seamless routes for cross-datacenter connectivity.
0 Comments
Be the first to comment and share your perspective with the community.