locals { ############################ AWS configuration ############################ # The AWS region where the Defguard infrastructure will be deployed. region = "eu-north-1" ############################ Core configuration ########################### # The URL for the Defguard Core. This is the URL under which the Defguard Core should be accessible. core_url = "https://defguard.example.com" # The gRPC port for the Defguard Core. This is the port that the core will use to communicate with Defguard Gateways. core_grpc_port = 50055 # The HTTP port for the Defguard Core web UI. This is the port that the core will listen on for incoming HTTP requests. core_http_port = 8000 # Whether to allow insecure cookies for the Defguard Core web UI. Set to true if you # are using HTTP to access the Defguard Core web UI. core_cookie_insecure = false # The initial password for the "admin" user. Use it to login to the Defguard Core web UI for the first time. default_admin_password = "pass123" # The deb package version of the Defguard Core that will be installed on the instance. # Must be a valid, released version of Defguard Core. core_package_version = "1.4.1" # The architecture of the Defguard Core server instance. # Supported values: "x86_64", "aarch64" core_arch = "x86_64" # The instance type for the Defguard Core server. core_instance_type = "t3.micro" ########################### Proxy configuration ########################### # The URL for the Defguard Proxy. This is the URL under which the Defguard Proxy should be accessible. proxy_url = "https://proxy.example.com" # The gRPC port for the Defguard Proxy. This is the port that the proxy will use to communicate with the Defguard Core. proxy_grpc_port = 50051 # The HTTP port for the Defguard Proxy. This is the port that the proxy will listen on for incoming HTTP requests. proxy_http_port = 8000 # The deb package version of the proxy that will be installed on the instance. # Must be a valid, released version of Defguard Proxy. proxy_package_version = "1.4.0" # The architecture of the Defguard Proxy server instance. # Supported values: "x86_64", "aarch64" proxy_arch = "x86_64" # The instance type for the Defguard Proxy server. proxy_instance_type = "t3.micro" ###################### VPN and Gateway configuration ###################### # List of VPN networks to be created. A gateway will be created for each network. vpn_networks = [ { # The ID of the VPN network. Must start with 1 and be incremented for each new network. # Used for modifying the network configuration later. id = 1 # The name of the VPN network. Displayed to the users. name = "vpn1" # The CIDR address of the VPN network. Clients will be assigned IP addresses from this range. address = "10.10.10.1/24" # The UDP port for the WireGuard VPN. Gateways will listen on this port for incoming VPN connections. port = 51820 # Whether to enable NAT for the VPN network. If true, the gateway will perform NAT (masquerade) for the VPN clients. # This is useful if you want the VPN clients to access the internet through the gateway or to access other resources in the VPC. nat = true } ] # The gateway deb package version that will be installed on the instance. # Must be a valid, released version of Defguard Gateway. gateway_package_version = "1.4.0" # The architecture of the Defguard Gateway server instance. # Supported values: "x86_64", "aarch64" gateway_arch = "x86_64" # The instance type for the Defguard Gateway server. gateway_instance_type = "t3.micro" ########################## Database configuration ######################### # The name of the database that will be created for the Defguard Core. db_name = "defguard" # The username for the database that will be created for the Defguard Core. db_username = "defguard" # The port on which the database will listen for incoming connections. db_port = 5432 # The password for the database user. This will be used by the Defguard Core to connect to the database. db_password = "defguard" # The amount of storage allocated for the database in GB. The minimum amount for this example required by AWS is 20 GB. db_storage = 20 # GB # The instance class for the database. This defines the performance characteristics of the database instance. db_instance_class = "db.t3.micro" ############################ VPC configuration ############################ # The name of the VPC that will be created for the Defguard infrastructure. vpc_name = "defguard-vpc" # The CIDR block for the VPC. This defines the IP address range for the VPC and its subnets. vpc_cidr = "10.0.0.0/16" # The tags to be applied to the Defguard VPC. vpc_tags = { Name = local.vpc_name } # The private subnets for the VPC. These subnets are used for the database instance. # Note: 2 subnets are required for high availability of the database instance. vpc_private_subnets = ["10.0.2.0/24", "10.0.3.0/24"] # The subnets for the VPC that will be used for the Defguard Core, proxy, and gateways. vpc_public_subnets = ["10.0.1.0/24"] # The availability zones for the VPC. This is used mainly for the database instance to ensure high availability. azs = ["eu-north-1a", "eu-north-1b"] } variable "aws_access_key" { description = "AWS access key" type = string } variable "aws_secret_key" { description = "AWS secret key" type = string } terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 6.0" } } } data "aws_ami" "ubuntu" { most_recent = true owners = ["099720109477"] filter { name = "name" values = ["ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-amd64-server-*"] } } provider "aws" { region = local.region access_key = var.aws_access_key secret_key = var.aws_secret_key } resource "random_password" "gateway_secret" { length = 64 special = false } module "defguard_core" { # source = "../../modules/core" source = "github.com/DefGuard/deployment//terraform/modules/core?ref=main" instance_type = local.core_instance_type package_version = local.core_package_version arch = local.core_arch ami = data.aws_ami.ubuntu.id core_url = local.core_url proxy_grpc_port = local.proxy_grpc_port proxy_url = local.proxy_url grpc_port = local.core_grpc_port http_port = local.core_http_port cookie_insecure = local.core_cookie_insecure vpn_networks = [for network in local.vpn_networks : { id = network.id name = network.name address = network.address port = network.port endpoint = aws_eip.defguard_gateway_endpoint[network.id - 1].public_ip }] db_details = { name = local.db_name username = local.db_username password = local.db_password port = local.db_port address = aws_db_instance.defguard_core_db.address } proxy_address = module.defguard_proxy.proxy_private_address gateway_secret = random_password.gateway_secret.result network_interface_id = aws_network_interface.defguard_core_network_interface.id # log_level = "info" } module "defguard_proxy" { # source = "../../modules/proxy" source = "github.com/DefGuard/deployment//terraform/modules/proxy?ref=main" instance_type = local.proxy_instance_type package_version = local.proxy_package_version arch = local.proxy_arch grpc_port = local.proxy_grpc_port http_port = local.proxy_http_port proxy_url = local.proxy_url # log_level = "info" ami = data.aws_ami.ubuntu.id network_interface_id = aws_network_interface.defguard_proxy_network_interface.id } module "defguard_gateway" { count = length(local.vpn_networks) # source = "../../modules/gateway" source = "github.com/DefGuard/deployment//terraform/modules/gateway?ref=main" ami = data.aws_ami.ubuntu.id instance_type = local.gateway_instance_type package_version = local.gateway_package_version arch = local.gateway_arch core_grpc_port = local.core_grpc_port nat = local.vpn_networks[count.index].nat network_id = local.vpn_networks[count.index].id gateway_secret = random_password.gateway_secret.result network_interface_id = aws_network_interface.defguard_gateway_network_interface[count.index].id core_address = aws_network_interface.defguard_core_network_interface.private_ip # log_level = "info" depends_on = [module.defguard_core] } module "vpc" { source = "terraform-aws-modules/vpc/aws" name = local.vpc_name cidr = local.vpc_cidr azs = local.azs private_subnets = local.vpc_private_subnets public_subnets = local.vpc_public_subnets enable_dns_hostnames = true tags = local.vpc_tags } ########################################################################### ####################### Core database configuration ####################### ########################################################################### resource "aws_db_instance" "defguard_core_db" { engine = "postgres" instance_class = local.db_instance_class username = local.db_username password = local.db_password db_name = local.db_name port = local.db_port skip_final_snapshot = true allocated_storage = local.db_storage db_subnet_group_name = aws_db_subnet_group.defguard.name vpc_security_group_ids = [aws_security_group.defguard_db_sg.id] parameter_group_name = aws_db_parameter_group.defguard_db_parameter_group.name } resource "aws_db_parameter_group" "defguard_db_parameter_group" { name = "defguard-db-parameter-group" family = "postgres17" parameter { name = "rds.force_ssl" value = "0" } } resource "aws_db_subnet_group" "defguard" { name = "defguard-db-subnet-group" subnet_ids = module.vpc.private_subnets } ########################################################################### ######################## Core network configuration ####################### ########################################################################### # Public IP address for the Defguard Core instance # Remove this if you want to use a private IP only # or you are running Defguard behind a reverse proxy. resource "aws_eip" "defguard_core_endpoint" { domain = "vpc" } resource "aws_eip_association" "defguard_core_endpoint_association" { network_interface_id = aws_network_interface.defguard_core_network_interface.id allocation_id = aws_eip.defguard_core_endpoint.id } resource "aws_security_group" "defguard_core_sg" { name = "defguard-core-sg" description = "Core access" vpc_id = module.vpc.vpc_id ########################### General access rules ########################## # (optional) SSH access to the Defguard Core server instance # ingress { # from_port = 22 # to_port = 22 # protocol = "tcp" # cidr_blocks = ["0.0.0.0/0"] # } # HTTP access to the Defguard Core web UI from connected VPN clients # Remove this rule if you want to run core only behind a reverse proxy # Note that the core access should be limited to the VPN clients and internal networks only. ingress { from_port = local.core_http_port to_port = local.core_http_port protocol = "tcp" cidr_blocks = [ for eip in aws_eip.defguard_gateway_endpoint : "${eip.public_ip}/32" ] } # Example access from a reverse proxy # ingress { # from_port = local.core_http_port # to_port = local.core_http_port # protocol = "tcp" # security_groups = [ ] # } ########## Security group rules essential for Defguard operation ########## # gRPC communication with Defguard Gateways ingress { from_port = local.core_grpc_port to_port = local.core_grpc_port protocol = "tcp" security_groups = [ for sg in aws_security_group.defguard_gateway_sg : sg.id ] } # General egress egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } } resource "aws_network_interface" "defguard_core_network_interface" { subnet_id = module.vpc.public_subnets[0] security_groups = [aws_security_group.defguard_core_sg.id] tags = { Name = "defguard-core-network-interface" } } ########################################################################### ###################### Gateway network configuration ###################### ########################################################################### # Public IP addresses for the Defguard Gateway instances # Gateways must be accessible externally to allow VPN clients to connect. resource "aws_eip" "defguard_gateway_endpoint" { count = length(local.vpn_networks) domain = "vpc" } resource "aws_eip_association" "defguard_gateway_endpoint_association" { count = length(local.vpn_networks) network_interface_id = aws_network_interface.defguard_gateway_network_interface[count.index].id allocation_id = aws_eip.defguard_gateway_endpoint[count.index].id } resource "aws_security_group" "defguard_gateway_sg" { count = length(local.vpn_networks) name = "defguard-gateway-sg-${count.index}" description = "Gateway access" vpc_id = module.vpc.vpc_id ########################### General access rules ########################## # (optional) SSH access to the Defguard Gateway server instance # ingress { # from_port = 22 # to_port = 22 # protocol = "tcp" # cidr_blocks = ["0.0.0.0/0"] # } ########## Security group rules essential for Defguard operation ########## # VPN traffic coming from connected clients ingress { from_port = local.vpn_networks[count.index].port to_port = local.vpn_networks[count.index].port protocol = "udp" cidr_blocks = ["0.0.0.0/0"] } # General egress egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } } resource "aws_network_interface" "defguard_gateway_network_interface" { count = length(local.vpn_networks) subnet_id = module.vpc.public_subnets[0] security_groups = [aws_security_group.defguard_gateway_sg[count.index].id] tags = { Name = "defguard-gateway-network-interface-${count.index}" } } ########################################################################### ####################### Proxy network configuration ####################### ########################################################################### # Public IP address for the Defguard Proxy instance # Remove this if you want to run proxy behind a reverse proxy resource "aws_eip" "defguard_proxy_endpoint" { domain = "vpc" } resource "aws_eip_association" "defguard_proxy_endpoint_association" { network_interface_id = aws_network_interface.defguard_proxy_network_interface.id allocation_id = aws_eip.defguard_proxy_endpoint.id } resource "aws_security_group" "defguard_proxy_sg" { name = "defguard-proxy-sg" description = "Proxy access" vpc_id = module.vpc.vpc_id ########################### General access rules ########################## # (optional) SSH access to the Defguard Proxy server instance # ingress { # from_port = 22 # to_port = 22 # protocol = "tcp" # cidr_blocks = ["0.0.0.0/0"] # } # HTTP access to the Defguard Proxy web UI from anywhere # Remove this rule if you want to run proxy behind a reverse proxy # Note that the proxy should be accessible externally to allow Defguard clients # to communicate through it and to allow the enrollment of new users. ingress { from_port = local.proxy_http_port to_port = local.proxy_http_port protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } # Example access from a reverse proxy # ingress { # from_port = local.proxy_http_port # to_port = local.proxy_http_port # protocol = "tcp" # security_groups = [ ] # } ########## Security group rules essential for Defguard operation ########## # Internal communication with Defguard Core ingress { from_port = local.proxy_grpc_port to_port = local.proxy_grpc_port protocol = "tcp" security_groups = [aws_security_group.defguard_core_sg.id] } # General egress egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } } resource "aws_network_interface" "defguard_proxy_network_interface" { subnet_id = module.vpc.public_subnets[0] security_groups = [aws_security_group.defguard_proxy_sg.id] tags = { Name = "defguard-proxy-network-interface" } } ########################################################################### ###################### Database network configuration ##################### ########################################################################### resource "aws_security_group" "defguard_db_sg" { name = "defguard-db-sg" description = "Access to the database" vpc_id = module.vpc.vpc_id # Allows access to the database from the Defguard Core instance ingress { from_port = local.db_port to_port = local.db_port protocol = "tcp" security_groups = [aws_security_group.defguard_core_sg.id] } tags = { Name = "defguard-db-sg" } } ########################################################################### ################################# Outputs ################################# ########################################################################### output "defguard_core_private_address" { description = "IP address of Defguard Core instance in the internal network" value = aws_network_interface.defguard_core_network_interface.private_ip } output "defguard_core_public_address" { description = "Public IP address of Defguard Core instance" value = aws_eip.defguard_core_endpoint.public_ip } output "defguard_proxy_public_address" { description = "Public IP address of Defguard Proxy instance" value = aws_eip.defguard_proxy_endpoint.public_ip } output "defguard_proxy_private_address" { description = "Private IP address of Defguard Proxy instance" value = aws_network_interface.defguard_proxy_network_interface.private_ip } output "defguard_gateway_public_addresses" { description = "Public IP addresses of Defguard Gateway instances" value = [for gw in aws_eip.defguard_gateway_endpoint : gw.public_ip] } output "defguard_gateway_private_addresses" { description = "Private IP addresses of Defguard Gateway instances" value = [for gw in aws_network_interface.defguard_gateway_network_interface : gw.private_ip] }