WireGuard® is an extremely simple yet fast and modern VPN that utilizes state-of-the-art cryptography. It aims to be faster, simpler, leaner, and more useful than IPsec, while avoiding the massive headache. It intends to be considerably more performant than OpenVPN.
This repository contains Terraform code to provision Wireguard server in a highly-available, scalable and secure manner, utilizing benefits of AWS infrastructure. The solution is built on top of such services as EC2, NLB, S3, SQS, Lambda, SSM, CloudWatch, SNS and more.
Above diagram demonstrates highly-available Wireguard setup in a single AWS region. Reference code is located under examples/multi-az
folder.
Multiple EC2 instances are spread across several availability zones within a region. Clients connections get distributed to the instances through highly-available Network Load Balancer with Route53 DNS record attached (optional).
Wireguard configuration file is being generated by Terraform and stored in S3 bucket with enabled versioning and access logs. Every S3 bucket content change triggers Lambda function through SQS queue. Lambda function executes predefined SSM document on all Wireguard EC2 instances. SSM document is configured to upload the latest configuration file to the instances and reload Wireguard interface. Also, Wireguard instances have PreUp hook enabled which additionally ensures that they use the latest configuration file available in S3.
- Terraform 0.15+
- Terragrunt 0.28.7+ (optional but recommended)
- Configured CLI access to target AWS account
There are multiple examples under examples
folder. Please, choose the one that fits your needs best. Every example comes with its own README.md
file.
Example code snippets for simplicity reasons don't define all variables which module exposes. So if you want to get a better understanding of all available options, please review the table below.
Name | Version |
---|---|
terraform | >= 0.15.0 |
terraform | >= 0.15.0 |
aws | >= 2.70.0 |
random | ~> 3.1.0 |
Name | Version |
---|---|
archive | 2.2.0 |
aws | 3.45.0 |
No modules.
Name | Description | Type | Default | Required |
---|---|---|---|---|
cloudwatch_alerts_emails | Email addresses to get monitoring alerts from CloudWatch. Email alert configuration must be manually approved by clicking on the button in confirmation email. Ignored when cloudwatch_monitoring_enable = false |
list(string) |
[] |
no |
cloudwatch_alerts_phone_numbers | Phone numbers to get monitoring alerts from CloudWatch. Ignored when cloudwatch_monitoring_enable = false |
list(string) |
[] |
no |
cloudwatch_log_retention_days | For how long CloudWatch will store log files (days) | number |
180 |
no |
cloudwatch_monitoring_enable | Enable CloudWatch monitoring of Wireguard resources. Disable if you don't plan to use CloudWatch monitoring solution | bool |
true |
no |
dns_zone_name | Route53 DNS zone name for Wireguard server endpoint. If not set, AWS LB DNS record is used | string |
"" |
no |
ec2_iam_policy_names | Additional IAM policies to assign to EC2 instances through instance profiles if needed | list(string) |
[] |
no |
ec2_instance_main_interface_name | EC2 instance primary network interface name | string |
"eth0" |
no |
ec2_instance_type | EC2 instance type | string |
"t3.micro" |
no |
enable_termination_protection | Enable termination protection for resources | bool |
true |
no |
name_suffix | Suffix to be added to all resources to uniquely identify this setup | string |
n/a | yes |
private_subnet_cidrs | VPC private subnets CIDR to create EC2 instances in. AZs of public & private subnets must match | list(string) |
n/a | yes |
prometheus_exporters_enable | Run Prometheus Exporters (Node Exporter & Wireguard Exporter) on EC2 instances. Disable if you don't plan to use Prometheus monitoring solution | bool |
true |
no |
public_subnet_cidrs | VPC public subnets CIDR to create NLB in. Multiple subnets are used for HA. AZs of public & private subnets must match | list(string) |
n/a | yes |
s3_bucket_name_prefix | Prefix to be added to S3 bucket name | string |
n/a | yes |
ssh_keypair_name | EC2 SSH key pair name | string |
n/a | yes |
tags | Tags to assign to all resources | map(string) |
{} |
no |
vpc_id | AWS VPC ID for EC2 instances and all other resources | string |
n/a | yes |
wg_allow_connections_from_subnets | Allow inbound connections to Wireguard server from these networks. To allow all networks set to 0.0.0.0/0 |
list(string) |
n/a | yes |
wg_cidr | Wireguard network subnet CIDR | string |
"10.0.44.0/24" |
no |
wg_dns_server | DNS server for Wireguard network | string |
"8.8.8.8" |
no |
wg_ha_instance_desired_count | Desired number of Wireguard EC2 instances (HA configuration) | number |
2 |
no |
wg_ha_instance_max_count | Maximum number of Wireguard EC2 instances (HA configuration) | number |
2 |
no |
wg_ha_instance_min_count | Minimum number of Wireguard EC2 instances (HA configuration) | number |
2 |
no |
wg_listen_ports | Wireguard listen ports. These ports will be opened for inbound Wireguard client connections | list(string) |
[ |
no |
wg_mtu | MTU value for Wireguard network | number |
"1420" |
no |
wg_peers | Wireguard clients (peers) configuration. Public_key is optional — will be automatically generated if empty. Peer_ip — desired client IP-address or subnet in CIDR notation within Wireguard network (must be within wg_cidr range). Allowed_subnets — controls what subnets peer will be able to access through Wireguard network (for bounce server mode set to 0.0.0.0/0 ). Isolated — if true peer won't be able to access other Wireguard peers. |
map(object({ public_key = string, peer_ip = string, allowed_subnets = list(string), isolated = bool })) |
{} |
no |
wg_private_key | WireGuard server private key | string |
n/a | yes |
wg_public_key | WireGuard server public key | string |
n/a | yes |
wg_restart_lambda_max_errors_count | Lambda which restarts Wireguard instances when configuration changes detected will stop execution if number of errors exceed this value | number |
0 |
no |
wg_restart_lambda_timeout_sec | Timeout for Lambda which restarts Wireguard instances when configuration changes occurred | number |
300 |
no |
Name | Description |
---|---|
autoscaling_group_arn | EC2 autoscaling group ARN |
autoscaling_group_name | EC2 autoscaling group name |
iam_instance_profile_arn | ARN of IAM instance profile to access S3 bucket |
iam_instance_profile_id | ID of IAM instance profile to access S3 bucket |
iam_role_arn | ARN of IAM role to access S3 bucket |
iam_role_name | Name of IAM role to access S3 bucket |
launch_template_arn | EC2 launch template ARN |
launch_template_id | EC2 launch template ID |
lb_arn | Load balancer ARN |
lb_dns_name | Load balancer DNS name |
lb_zone_id | Load balancer DNS zone ID |
s3_bucket_access_logs_arn | Load balancer access logs S3 bucket ARN |
s3_bucket_access_logs_name | Load balancer access logs S3 bucket name |
s3_bucket_arn | Wireguard configuration S3 bucket ARN |
s3_bucket_name | Wireguard configuration S3 bucket name |
sqs_queue_arn | SQS queue for S3 notifications ARN |
sqs_queue_dead_letter_arn | SQS dead letter queue for S3 notifications ARN |
sqs_queue_dead_letter_id | SQS dead letter queue for S3 notifications ID |
sqs_queue_id | SQS queue for S3 notifications ID |
wireguard_client_configs | Example configuration files for Wireguard clients |
wireguard_server_endpoints | Wireguard server endpoints |
wireguard_server_host | Wireguard server host |
wireguard_server_name | Wireguard server name |
wireguard_server_ports | Wireguard server ports |
Any reasonable pull requests are always welcomed. All PRs are subject to automated checks, so please make sure that your changes pass all configured pre-commit hooks. If you found a bug or need support of any kind, please start a new conversation in Issues section.
The code is licensed under GNU GPL license.