AMIs and AWS CloudFormation
This feature is still under development. The documentation may be incomplete or refer to resources that are not yet available.
AMIs (Amazon Machine Images)
We provide an AMI for each Defguard component (Core, Gateway and Proxy) which can be used to launch instances in AWS. The AMIs are available in the following regions:
us-east-1
(N. Virginia)eu-west-1
(Ireland)ap-northeast-1
(Tokyo)
We recommend using the AMIs either with a CloudFormation template or with our Terraform module, as they will automatically configure the instances with the necessary settings.
CloudFormation Templates
You can import the CloudFormation template from the AWS Marketplace or from our GitHub deployment repository.
The template consists of the following components:
Defguard Core
Defguard Gateway - The template has only one Gateway instance, but Defguard supports running multiple Gateways if you need more VPN locations.
Defguard Proxy
PostgreSQL Database
We recommend reading the Architecture documentation to understand how these components interact.
The template has the following configurable parameters:
Core Instance
CoreCookieInsecure
(optional): If set totrue
, Defguard Core will use insecure cookies. This is not recommended for production environments. Set it totrue
if you are using HTTP instead of HTTPS.CoreGrpcPort
(optional): The gRPC port, default is50051
. This is used for communication between Defguard components.CoreHttpPort
(optional): The HTTP port on which Defguard Core should listen, default is8000
. This is where the Defguard web UI will be accessible.CoreInstanceType
(optional): The instance type (e.g.,t3.medium
,m5.large
), default ist3.micro
.CoreLogLevel
(optional): The log level of Defguard Core, default isinfo
.CoreUrl
(required): The URL where Defguard Core will be accessible (e.g.,https://defguard.example.com
). This should be the URL that users will use to access the Defguard web interface.CoreDefaultAdminPassword
(optional): The default password for theadmin
user, default ispass123
. This should be changed to a more secure password in production environments.
Database
DbInstanceClass
(optional): The instance class for the PostgreSQL database, default isdb.t3.micro
.DbName
(optional): The name of the PostgreSQL database, default isdefguard
.DbPassword
(optional): The password for the PostgreSQL database, default isdefguard
. This should be changed to a more secure password in production environments.DbPort
(optional): The port on which the PostgreSQL database will listen, default is5432
.DbStorage
(optional): The storage size for the PostgreSQL database, default is20
. This is the size in GB.DbUsername
(optional): The username for the PostgreSQL database, default isdefguard
.
Gateway Instance
GatewayInstanceType
(optional): The instance type for the Gateway, default ist3.micro
.GatewayLogLevel
(optional): The log level for the Gateway, default isinfo
.GatewaySecret
(required): The secret used to authenticate the Gateway with Defguard Core. This should be a strong, random string, 64 characters long.
Proxy Instance
ProxyGrpcPort
(optional): The gRPC port for the Proxy, default is50051
.ProxyHttpPort
(optional): The HTTP port for the Proxy, default is8000
. This is where the Defguard Proxy web UI will be accessible. The proxy UI is used for user enrollment.ProxyInstanceType
(optional): The instance type for the Proxy, default ist3.micro
.ProxyLogLevel
(optional): The log level for the Proxy, default isinfo
.ProxyUrl
(required): The URL where the Defguard Proxy will be accessible (e.g.,https://proxy.defguard.example.com
). This should be the URL that users will use to access the Defguard Proxy web UI.
Network configuration
VpcCidr
(optional): The CIDR block for the VPC in which Defguard will be deployed, default is10.0.0.0/16
.VpcName
(optional): The name of the VPC, default isdefguard-vpc
.
VPN Network (Location) configuration
VpnNetworkAddress
(optional): The CIDR address for the VPN network, default is10.10.10.1/24
. The VPN clients will receive IP addresses from this range. The gateway will have the first address in the range.VpnNetworkName
(optional): The name of the VPN network (location). This is displayed both to the clients and in the Defguard web UI, default isvpn1
.VpnNetworkNat
(optional): If set totrue
, the VPN will have masquerading enabled, allowing clients to access other networks through the VPN (e.g., the internet). Default istrue
.VpnNetworkPort
(optional): The UDP port on which the VPN will listen for incoming VPN connections, default is51820
.
Customizing the deployment
By default, the CloudFormation template will deploy Defguard with the settings accroding to the recommended architecture, that is:
Core
8000 (HTTP)
Gateways
Core
50055 (gRPC)
Gateways
Proxy
50051 (gRPC)
Core
Proxy
8000 (HTTP)
Anywhere
Gateway
51820 (UDP)
Anywhere
You can customize the deployment by modifying the template or doing changes in the AWS Infrastructure Composer.
To modify an existing stack deployed from the template, you can use the AWS Console, navigate to the CloudFormation service, select your stack, click on "Update stack" and then choose "Create a change set".

Next, select how you want to update the stack. If you want to modify the parameters, select "Use existing template".

If you want to modify the template itself, the easiest way is to edit it in the Infrastructure Composer: select "Edit in Infrastructure Composer" and click the "Edit in Infrastructure Composer" button.

Granting SSH access to the instances
By default, the instances won't allow traffic on port 22. You can temporarily allow SSH access by modifying the security group of the instances. To do this, edit the template, and change the given component's security group to allow traffic on port 22 (ideally from your IP address).
For example, you can add the following rule to the security group of the Core instance:
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: !Ref CoreHttpPort
ToPort: !Ref CoreHttpPort
SourceSecurityGroupId: !Ref GatewaySecurityGroup
Description: HTTP access from gateways
- IpProtocol: tcp
FromPort: !Ref CoreGrpcPort
ToPort: !Ref CoreGrpcPort
SourceSecurityGroupId: !Ref GatewaySecurityGroup
Description: gRPC communication with gateways
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: <YOUR_IP_ADDRESS>/32
Description: SSH access from your IP address
Removing EIP
By default, every component has an Elastic IP (EIP) assigned to it. This makes it easier to access them while setting everything up, but you might want to remove the EIP if you don't need it, especially if you plan to use a Reverse Proxy in front of the Defguard Core and Proxy.
To remove the EIP, you can edit the template and remove the <COMPONENT>ElasticIp
, <COMPONENT>EipAssociation
resources and Defguard<COMPONENT>PublicAddress
outputs from the template, where <COMPONENT>
is one of Core
, Gateway
or Proxy
. We do not recommend removing the EIP from the Gateway, as it should be accessible from the internet for VPN clients to connect to it.
Adding a Reverse Proxy/Load Balancer
If you want to add a Reverse Proxy or Load Balancer in front of the Defguard Core and Proxy, you can do so by modifying the template. You can achieve this by adding two Application Load Balancers (ALBs) in front of the Core and Proxy components. One ALB (internal) will be used for the Core, and one (public) for the Proxy.
Adding a Load Balancer will require making a second public subnet:
PublicSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.4.0/24
AvailabilityZone: !Select
- 1
- !GetAZs ""
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: !Sub ${VpcName}-public-subnet-2
And adding a route table association:
PublicSubnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet2
RouteTableId: !Ref PublicRouteTable
Then, you can add the ALBs along with listeners and target groups:
ApplicationLoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: defguard-public-alb
Scheme: internet-facing
Type: application
IpAddressType: ipv4
Subnets:
- !Ref PublicSubnet
- !Ref PublicSubnet2
SecurityGroups:
- !Ref LoadBalancerSecurityGroup
Tags:
- Key: Name
Value: defguard-public-alb
InternalApplicationLoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: defguard-internal-alb
Scheme: internal
Type: application
IpAddressType: ipv4
Subnets:
- !Ref PrivateSubnet1
- !Ref PrivateSubnet2
SecurityGroups:
- !Ref InternalLoadBalancerSecurityGroup
Tags:
- Key: Name
Value: defguard-internal-alb
ALBListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref ProxyTargetGroup
LoadBalancerArn: !Ref ApplicationLoadBalancer
Port: 80
Protocol: HTTP
InternalALBListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref CoreTargetGroup
LoadBalancerArn: !Ref InternalApplicationLoadBalancer
Port: 80
Protocol: HTTP
CoreListenerRule:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Actions:
- Type: forward
TargetGroupArn: !Ref CoreTargetGroup
Conditions:
- Field: host-header
Values:
- !Select
- 2
- !Split
- /
- !Ref CoreUrl
ListenerArn: !Ref InternalALBListener
Priority: 100
CoreListenerRule:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Actions:
- Type: forward
TargetGroupArn: !Ref CoreTargetGroup
Conditions:
- Field: host-header
Values:
- !Select
- 2
- !Split
- /
- !Ref CoreUrl
ListenerArn: !Ref InternalALBListener
Priority: 100
CoreListenerRule404:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Actions:
- Type: fixed-response
FixedResponseConfig:
StatusCode: "404"
ContentType: text/plain
MessageBody: "Not Found"
Conditions:
- Field: host-header
HostHeaderConfig:
Values:
- "*"
ListenerArn: !Ref InternalALBListener
Priority: 200
ProxyListenerRule:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Actions:
- Type: forward
TargetGroupArn: !Ref ProxyTargetGroup
Conditions:
- Field: host-header
Values:
- !Select
- 2
- !Split
- /
- !Ref ProxyUrl
ListenerArn: !Ref ALBListener
Priority: 100
ProxyListenerRule404:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Actions:
- Type: fixed-response
FixedResponseConfig:
StatusCode: "404"
ContentType: text/plain
MessageBody: "Not Found"
Conditions:
- Field: host-header
HostHeaderConfig:
Values:
- "*"
ListenerArn: !Ref ALBListener
Priority: 200
Then, modify the Core and Proxy security groups to allow traffic from the ALBs:
# Add this to Core security group
- IpProtocol: tcp
FromPort: !Ref CoreHttpPort
ToPort: !Ref CoreHttpPort
SourceSecurityGroupId: !Ref InternalLoadBalancerSecurityGroup
Description: HTTP access from internal load balancer
# Add this to Proxy security group
- IpProtocol: tcp
FromPort: !Ref ProxyHttpPort
ToPort: !Ref ProxyHttpPort
SourceSecurityGroupId: !Ref LoadBalancerSecurityGroup
Description: HTTP access from load balancer
You should also remove the following rules to prevent direct access to the Core and Proxy components:
# Remove these rules from Core security group
- IpProtocol: tcp
FromPort: !Ref CoreHttpPort
ToPort: !Ref CoreHttpPort
SourceSecurityGroupId: !Ref GatewaySecurityGroup
Description: HTTP access from gateways
# Remove these rules from Proxy security group
- IpProtocol: tcp
FromPort: !Ref ProxyHttpPort
ToPort: !Ref ProxyHttpPort
CidrIp: 0.0.0.0/0
Description: HTTP access to proxy
Finally, configure the security groups of your ALBs:
LoadBalancerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: defguard-alb-sg
GroupDescription: Access to the Application Load Balancer
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
Description: HTTP access from internet
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
Description: HTTPS access from internet
SecurityGroupEgress:
- IpProtocol: "-1"
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: defguard-alb-sg
InternalLoadBalancerSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: defguard-internal-alb-sg
GroupDescription: Access to the Internal Application Load Balancer
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: !Ref VpcCidr
Description: HTTP access from internal VPC network
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: !Ref VpcCidr
Description: HTTPS access from internal VPC network
SecurityGroupEgress:
- IpProtocol: "-1"
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: defguard-internal-alb-sg
To easily inspect the ALB DNS names, you can add the following outputs to your template:
LoadBalancerDNS:
Condition: CreateLoadBalancer
Description: The DNS name of the Public Application Load Balancer
Value: !GetAtt ApplicationLoadBalancer.DNSName
Export:
Name: !Sub ${AWS::StackName}-alb-dns
InternalLoadBalancerDNS:
Condition: CreateInternalLoadBalancer
Description: The DNS name of the Internal Application Load Balancer
Value: !GetAtt InternalApplicationLoadBalancer.DNSName
Export:
Name: !Sub ${AWS::StackName}-internal-alb-dns
This setup will allow you to access the Defguard Core and Proxy through the Load Balancers, while keeping the components not directly accessible. Both ALBs act more as a reverse proxy, as they match requests based on the host-header
and no balancing is performed. By making the Core load balancer internal, you can ensure that only the Proxy is accessible from the internet, while the Core access is restricted to the internal VPC network.
To allow connected VPN clients access the Core web UI, you can enable the VpnNetworkNat
option in the CloudFormation template, so the traffic going through the VPN will be NATed and routed to the Core. You will also need to add an allowed IP of your VPC network (or one of its subnets) in your Location configuration in Defguard Core to let the clients know to route the traffic destined to the VPC through the VPN.
Last updated
Was this helpful?