AWSTemplateFormatVersion: '2010-09-09' Description: VyOS Networks CloudFormation template to deploy a VPC with public and private subnets, an Internet gateway, Route tables, ENIs, Elastic IP Address and a VyOS instance with subscription (Pay As You Go) and configures VyOS instance via user-data (cloud-init). Parameters: ExistingVPCId: Description: ID of an existing VPC Type: String Default: '' AllowedPattern: ^$|^vpc-[0-9a-fA-F]{8,17}$ ConstraintDescription: Must be a valid VPC ID or empty. ExistingPublicSubnetId: Description: ID of an existing public subnet Type: String Default: '' AllowedPattern: ^$|^subnet-[0-9a-fA-F]{8,17}$ ConstraintDescription: Must be a valid public subnet ID or empty. ExistingPrivateSubnetId: Description: ID of an existing private subnet Type: String Default: '' AllowedPattern: ^$|^subnet-[0-9a-fA-F]{8,17}$ ConstraintDescription: Must be a valid private subnet ID or empty. VPCName: Description: Name of the VPC Type: String Default: '' AllowedPattern: ^$|^.{1,128}$ MaxLength: 128 ConstraintDescription: Must be empty or between 1 and 128 characters. VPCCidrBlock: Description: CIDR block for the VPC Type: String Default: '' AllowedPattern: ^$|^(10\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/([1-9]|[1-2][0-9]|3[0-2]))$|^(172\.(1[6-9]|2[0-9]|3[01])\.[0-9]{1,3}\.[0-9]{1,3}\/([1-9]|[1-2][0-9]|3[0-2]))$|^(192\.168\.[0-9]{1,3}\.[0-9]{1,3}\/([1-9]|[1-2][0-9]|3[0-2]))$ ConstraintDescription: Must be a valid IPv4 CIDR notation within private IP ranges based on RFC 1918, with subnet sizes between /16 and /28, or can be empty if we deploy VyOS instance to the existig VPC. PublicSubnetCidr: Description: CIDR block for the Public Subnet Type: String Default: '' AllowedPattern: ^$|^(10\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/([1-9]|[1-2][0-9]|3[0-2]))$|^(172\.(1[6-9]|2[0-9]|3[01])\.[0-9]{1,3}\.[0-9]{1,3}\/([1-9]|[1-2][0-9]|3[0-2]))$|^(192\.168\.[0-9]{1,3}\.[0-9]{1,3}\/([1-9]|[1-2][0-9]|3[0-2]))$ ConstraintDescription: Must be a valid IPv4 CIDR notation within private IP ranges based on RFC 1918, with subnet sizes between /16 and /28. PrivateSubnetCidr: Description: CIDR block for the Private Subnet Type: String Default: '' AllowedPattern: ^$|^(10\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/([1-9]|[1-2][0-9]|3[0-2]))$|^(172\.(1[6-9]|2[0-9]|3[01])\.[0-9]{1,3}\.[0-9]{1,3}\/([1-9]|[1-2][0-9]|3[0-2]))$|^(192\.168\.[0-9]{1,3}\.[0-9]{1,3}\/([1-9]|[1-2][0-9]|3[0-2]))$ ConstraintDescription: Must be a valid IPv4 CIDR notation within private IP ranges based on RFC 1918, with subnet sizes between /16 and /28. InstanceType: Description: EC2 instance type for VyOS deployment Type: String Default: c5n.large AllowedValues: - t3.small - t3.medium - t3.large - t3.xlarge - t3.2xlarge - t3a.small - t3a.medium - t3a.large - t3a.xlarge - t3a.2xlarge - m4.large - m4.xlarge - m4.2xlarge - m4.4xlarge - m4.10xlarge - m4.16xlarge - m5.large - m5.xlarge - m5.2xlarge - m5.4xlarge - m5.8xlarge - m5a.large - m5a.xlarge - m5a.2xlarge - m5a.4xlarge - m5a.8xlarge - m5a.12xlarge - m5n.large - m5n.xlarge - m5n.2xlarge - m5n.4xlarge - m5n.8xlarge - m5n.12xlarge - m5zn.large - m5zn.xlarge - m5zn.2xlarge - m5zn.3xlarge - m5zn.6xlarge - m5zn.12xlarge - m6i.large - m6i.xlarge - m6i.2xlarge - m6i.4xlarge - m6i.8xlarge - m6i.12xlarge - m6i.16xlarge - c4.large - c4.xlarge - c4.2xlarge - c4.4xlarge - c4.8xlarge - c5.large - c5.xlarge - c5.2xlarge - c5.4xlarge - c5.9xlarge - c5d.large - c5d.xlarge - c5d.2xlarge - c5d.4xlarge - c5d.9xlarge - c5a.large - c5a.xlarge - c5a.2xlarge - c5a.4xlarge - c5a.8xlarge - c5n.large - c5n.xlarge - c5n.2xlarge - c5n.4xlarge - c5n.9xlarge - c6i.large - c6i.xlarge - c6i.2xlarge - c6i.4xlarge - c6i.8xlarge - c6i.12xlarge - c6i.16xlarge - c6i.24xlarge - m6a.large - m6a.xlarge - m6a.2xlarge - m6a.4xlarge - m6a.8xlarge - m6a.12xlarge - m6a.16xlarge - m6in.large - m6in.xlarge - m6in.2xlarge - m6in.4xlarge - m6in.8xlarge - m6in.12xlarge - m6in.16xlarge - m6in.24xlarge - m6in.32xlarge - m6in.metal - m7i.large - m7i.xlarge - m7i.2xlarge - m7i.4xlarge - m7i.8xlarge - m7i-flex.large - m7i-flex.xlarge - m7i-flex.2xlarge - m7i-flex.4xlarge - m7i-flex.8xlarge KeyName: Description: Name of an existing EC2 KeyPair to enable SSH access to the instances Type: AWS::EC2::KeyPair::KeyName ConstraintDescription: Must not be empty VyOSPublicENIip: Description: Private IP address for VyOS instance ENI Type: String AllowedPattern: ^(10\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])|172\.(?:1[6-9]|2[0-9]|3[01])\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])|192\.168\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]))$ ConstraintDescription: Must be a valid IP address in the Public Subnet CIDR block VyOSPrivENIip: Description: Private IP address for VyOS instance ENI Type: String AllowedPattern: ^(10\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])|172\.(?:1[6-9]|2[0-9]|3[01])\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])|192\.168\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]))$ ConstraintDescription: Must be a valid IP address in the Private Subnet CIDR block SSHAllowedIP: Description: The IP subnet allowed to SSH into the VyOS instance Type: String Default: 192.0.2.0/24 AllowedPattern: ^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(/(2[4-9]|3[0-2]))$ ConstraintDescription: Must be a valid IPv4 CIDR within range /24 to /32 # VyOS AMI Aliase. # If you set "latest" option CloudFormation will choose the latest version of the VyOS. # But if you want to deploy a more specific version you should change the latest to part of the alias like /aws/.../1.3.6, /aws/.../1.4.0. # After changing this please look at the Resources part "VyOSInstance"s User-Data field because there could be VyOS CLI commands changes. # Check VyOS official documentation for command reference. AmiAlias: Type: "AWS::SSM::Parameter::Value" Default: "/aws/service/marketplace/prod-ev235jujteaom/latest" Description: "AMI Alias of the VyOS instance" Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: 'Current VPC configuration. If you want deploy instance to your existing VPC please add VPC and Subnet IDs to regareded fields:' Parameters: - ExistingVPCId - ExistingPublicSubnetId - ExistingPrivateSubnetId - Label: default: 'New VPC and Subnet CIDRs configurations. If you want to deploy instance to new VPC please fill regarded fields:' Parameters: - VPCName - VPCCidrBlock - PublicSubnetCidr - PrivateSubnetCidr - Label: default: 'VyOS Instance Configuration:' Parameters: - InstanceType - KeyName - VyOSPublicENIip - VyOSPrivENIip - SSHAllowedIP ParameterLabels: ExistingVPCId: default: Existing VPC ID (optional if deploy existing VPC) ExistingPublicSubnetId: default: Existing Public Subnet ID (optional if deploy existing VPC) ExistingPrivateSubnetId: default: Existing Private Subnet ID (optional if deploy existing VPC) VPCName: default: VPC Name (required if you deploy new VPC) VPCCidrBlock: default: VPC CIDR Block (required if you deploy new VPC) PublicSubnetCidr: default: Public Subnet CIDR (required if you deploy new VPC) PrivateSubnetCidr: default: Private Subnet CIDR (required if you deploy new VPC) InstanceType: default: Instance Type (required) KeyName: default: EC2 KeyPair Name (required) VyOSPublicENIip: default: VyOS Public ENI IP (required) VyOSPrivENIip: default: VyOS Private ENI IP (required) OnPremPublicIPAddress: default: On-Premies Public IP Address (required) VyOSBGPASNumber: default: VyOS BGP ASN (required) OnPremBGPASNumber: default: On-Premies BGP ASN (required) SSHAllowedIP: default: SSH Allowed IP Subnet (required) Conditions: CreateVPC: !Equals - !Ref ExistingVPCId - '' CreatePublicSubnet: !Equals - !Ref ExistingPublicSubnetId - '' CreatePrivateSubnet: !Equals - !Ref ExistingPrivateSubnetId - '' Resources: # VPC VPC: Type: AWS::EC2::VPC Condition: CreateVPC Properties: CidrBlock: !Ref VPCCidrBlock EnableDnsSupport: 'true' EnableDnsHostnames: 'true' Tags: - Key: Name Value: !Ref VPCName # Subnets PublicSubnet: Type: AWS::EC2::Subnet Condition: CreatePublicSubnet DependsOn: VPC Properties: VpcId: !If - CreateVPC - !Ref VPC - !Ref ExistingVPCId CidrBlock: !Ref PublicSubnetCidr MapPublicIpOnLaunch: 'true' AvailabilityZone: !Select - 0 - !GetAZs '' Tags: - Key: Name Value: Public Subnet PrivateSubnet: Type: AWS::EC2::Subnet Condition: CreatePrivateSubnet DependsOn: VPC Properties: VpcId: !If - CreateVPC - !Ref VPC - !Ref ExistingVPCId CidrBlock: !Ref PrivateSubnetCidr MapPublicIpOnLaunch: 'false' AvailabilityZone: !Select - 0 - !GetAZs '' Tags: - Key: Name Value: Private Subnet # Internet Gateway InternetGateway: Type: AWS::EC2::InternetGateway Condition: CreateVPC Properties: Tags: - Key: Name Value: Internet Gateway - Key: Created by Value: CloudFormation AttachGateway: Type: AWS::EC2::VPCGatewayAttachment Condition: CreateVPC Properties: VpcId: !Ref VPC InternetGatewayId: !Ref InternetGateway # Route Tables PublicRouteTable: Type: AWS::EC2::RouteTable Condition: CreateVPC Properties: VpcId: !If - CreateVPC - !Ref VPC - !Ref ExistingVPCId Tags: - Key: Name Value: Public Route Table - Key: Created by Value: CloudFormation PublicRoute: Type: AWS::EC2::Route Condition: CreateVPC Properties: RouteTableId: !Ref PublicRouteTable DestinationCidrBlock: 0.0.0.0/0 GatewayId: !If - CreateVPC - !Ref InternetGateway - !Ref ExistingPublicSubnetId PublicSubnetRouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Condition: CreateVPC Properties: SubnetId: !Ref PublicSubnet RouteTableId: !Ref PublicRouteTable # Security Groups VyOSPublicSG: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Enable access from outside VpcId: !If - CreateVPC - !Ref VPC - !Ref ExistingVPCId SecurityGroupIngress: - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: !Ref SSHAllowedIP Description: Allow SSH access - IpProtocol: udp FromPort: 51820 ToPort: 51820 CidrIp: 0.0.0.0/0 Description: Allow WireGuard VPN access - IpProtocol: udp FromPort: 1194 ToPort: 1194 CidrIp: 0.0.0.0/0 Description: Allow OpenVPN access - IpProtocol: udp FromPort: 500 ToPort: 500 CidrIp: 0.0.0.0/0 Description: Allow IPSec VPN access (ISAKMP) - IpProtocol: udp FromPort: 1701 ToPort: 1701 CidrIp: 0.0.0.0/0 Description: Allow L2TP VPN access - IpProtocol: udp FromPort: 4500 ToPort: 4500 CidrIp: 0.0.0.0/0 Description: Allow IPSec NAT Traversal Tags: - Key: Name Value: PublicSG - Key: Created by Value: CloudFormation VyOSPrivateSG: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Enable access from inside VpcId: !If - CreateVPC - !Ref VPC - !Ref ExistingVPCId SecurityGroupIngress: - IpProtocol: -1 CidrIp: 0.0.0.0/0 Description: Allow all protocols and ports Tags: - Key: Name Value: PrivateSG - Key: Created by Value: CloudFormation # ENIs PublicENI: Type: AWS::EC2::NetworkInterface Properties: SubnetId: !If - CreatePublicSubnet - !Ref PublicSubnet - !Ref ExistingPublicSubnetId Description: Public Network Interface PrivateIpAddress: !Ref VyOSPublicENIip GroupSet: - !Ref VyOSPublicSG Tags: - Key: Name Value: PublicENI - Key: Created by Value: CloudFormation PrivateENI: Type: AWS::EC2::NetworkInterface Properties: SubnetId: !If - CreatePrivateSubnet - !Ref PrivateSubnet - !Ref ExistingPrivateSubnetId Description: Private Network Interface PrivateIpAddress: !Ref VyOSPrivENIip GroupSet: - !Ref VyOSPrivateSG Tags: - Key: Name Value: PrivateENI - Key: Created by Value: CloudFormation # VyOS Instance VyOSInstance: Type: AWS::EC2::Instance Properties: InstanceType: !Ref InstanceType KeyName: !Ref KeyName ImageId: !Ref AmiAlias NetworkInterfaces: - NetworkInterfaceId: !Ref PublicENI DeviceIndex: 0 - NetworkInterfaceId: !Ref PrivateENI DeviceIndex: 1 UserData: !Base64 Fn::Sub: | #cloud-config vyos_config_commands: # Basic VyOS Configuration - set system host-name 'VyOS-on-AWS' - set interfaces ethernet eth0 description 'OUTSIDE' - set interfaces ethernet eth1 description 'INSIDE' - set interfaces ethernet eth1 dhcp-options no-default-route - set system login banner pre-login 'Welcome to the VyOS on AWS' Tags: - Key: Name Value: VyOS-Instance - Key: Created by Value: CloudFormation # Elastic IP VyOSPublicIPAddress: Type: AWS::EC2::EIP Properties: Domain: vpc Tags: - Key: Name Value: VyOS-Instance-EIP - Key: Created by Value: CloudFormation # Elastic IP Association EIPAssociation: Type: AWS::EC2::EIPAssociation Properties: NetworkInterfaceId: !Ref PublicENI AllocationId: !GetAtt VyOSPublicIPAddress.AllocationId # Outputs Outputs: VPCId: Description: VPC Id Value: !If - CreateVPC - !Ref VPC - !Ref ExistingVPCId VPCPublicSubnetId: Description: Public Subnet Id Value: !If - CreatePublicSubnet - !Ref PublicSubnet - !Ref ExistingPublicSubnetId VPCPrivateSubnetId: Description: Private Subnet Id Value: !If - CreatePrivateSubnet - !Ref PrivateSubnet - !Ref ExistingPrivateSubnetId VyOSInstanceId: Description: Instance ID of the VyOS instance Value: !Ref VyOSInstance VyOSPublicIp: Description: Public IP address of the VyOS instance Value: !Ref VyOSPublicIPAddress VyOSMgmtUsername: Description: Username for SSH access to the VyOS instance Value: vyos VyOSMgmtKeyPair: Description: Name of the KeyPair used for SSH access Value: !Ref KeyName VyOSMgmtInfo: Description: VyOS managment information Value: !Join - "\n" - - "Management allowed via SSH protocol default port 22. " - "To access VyOS instance you need to have SSH client software (like Putty, MobaXterm etc). " - "SSH access example: ssh vyos@192.0.2.1 -i /tmp/test.pem"