| `string` | `"vpn"` | no |
-| [public\_rule](#input\_public\_rule) | public rule for run connect vpn | list(object({
port = number
protocol = string
health_check_port = number
health_check_protocol = string
})) | [
{
"health_check_port": 443,
"health_check_protocol": "TCP",
"port": 12383,
"protocol": "UDP"
}
]
| no |
-| [public\_subnet\_ids](#input\_public\_subnet\_ids) | The List of the subnet ID to deploy Public Loadbalancer relate to VPC | `list(string)` | n/a | yes |
-| [route53\_zone\_name](#input\_route53\_zone\_name) | This is the name of the hosted zone | `string` | `""` | no |
-| [security\_group\_ingress\_rules](#input\_security\_group\_ingress\_rules) | Map of ingress and any specific/overriding attributes to be created | `any` | {
"allow_to_connect_vpn": {
"cidr_blocks": [
"0.0.0.0/0"
],
"port": "12383",
"protocol": "udp"
}
} | no |
-| [tags](#input\_tags) | Tags to add more; default tags contian {terraform=true, environment=var.environment} | `map(string)` | `{}` | no |
-| [vpc\_id](#input\_vpc\_id) | The ID of the VPC | `string` | n/a | yes |
+| Name | Description | Type | Default | Required |
+|------|-------------|------|---------|:--------:|
+| [additional\_sg\_attacment\_ids](#input\_additional\_sg\_attacment\_ids) | (Optional) The ID of the security group. | `list(string)` | `[]` | no |
+| [ami](#input\_ami) | (Optional) AMI to use for the instance. Required unless launch\_template is specified and the Launch Template specifes an AMI. If an AMI is specified in the Launch Template, setting ami will override the AMI specified in the Launch Template | `string` | `""` | no |
+| [custom\_https\_allow\_cidr](#input\_custom\_https\_allow\_cidr) | cidr block for config pritunl vpn | `list(string)` | `null` | no |
+| [efs\_backup\_policy\_enabled](#input\_efs\_backup\_policy\_enabled) | If `true`, it will turn on automatic backups. | `bool` | `true` | no |
+| [enable\_ec2\_monitoring](#input\_enable\_ec2\_monitoring) | Enables/disables detailed monitoring | `bool` | `false` | no |
+| [enabled\_backup](#input\_enabled\_backup) | Enable Backup EFS | `bool` | `true` | no |
+| [environment](#input\_environment) | Environment Variable used as a prefix | `string` | n/a | yes |
+| [host\_id](#input\_host\_id) | Override PritunlVPN host id with this option, Use with migration only | `string` | `""` | no |
+| [instance\_type](#input\_instance\_type) | (Optional) The instance type to use for the instance. Updates to this field will trigger a stop/start of the EC2 instance. | `string` | `"t2.medium"` | no |
+| [is\_create\_private\_lb](#input\_is\_create\_private\_lb) | if true this module will not create private lb for cost optimization | `bool` | `true` | no |
+| [is\_create\_route53\_reccord](#input\_is\_create\_route53\_reccord) | if true will create route53 reccord for vpn, vpn console | `bool` | `false` | no |
+| [is\_create\_security\_group](#input\_is\_create\_security\_group) | Flag to toggle security group creation | `bool` | `true` | no |
+| [is\_enabled\_https\_public](#input\_is\_enabled\_https\_public) | if true will enable https to public loadbalancer else enable to private loadbalancer | `bool` | `true` | no |
+| [key\_name](#input\_key\_name) | Key name of the Key Pair to use for the vpn instance; which can be managed using | `string` | `null` | no |
+| [prefix](#input\_prefix) | The prefix name of customer to be displayed in AWS console and resource | `string` | n/a | yes |
+| [private\_lb\_vpn\_domain](#input\_private\_lb\_vpn\_domain) | domain of vpn console output will be . | `string` | `"vpn-console"` | no |
+| [private\_rule](#input\_private\_rule) | private rule for run connect vpn | list(object({
port = number
protocol = string
health_check_port = number
health_check_protocol = string
})) | `[]` | no |
+| [private\_subnet\_ids](#input\_private\_subnet\_ids) | The List of the private subnet ID to deploy instance and private lb for vpn relate to VPC | `list(string)` | n/a | yes |
+| [public\_lb\_vpn\_domain](#input\_public\_lb\_vpn\_domain) | domain of vpn output will be . | `string` | `"vpn"` | no |
+| [public\_rule](#input\_public\_rule) | public rule for run connect vpn | list(object({
port = number
protocol = string
health_check_port = number
health_check_protocol = string
})) | [
{
"health_check_port": 443,
"health_check_protocol": "TCP",
"port": 12383,
"protocol": "UDP"
}
]
| no |
+| [public\_subnet\_ids](#input\_public\_subnet\_ids) | The List of the subnet ID to deploy Public Loadbalancer relate to VPC | `list(string)` | n/a | yes |
+| [route53\_zone\_name](#input\_route53\_zone\_name) | This is the name of the hosted zone | `string` | `""` | no |
+| [security\_group\_ingress\_rules](#input\_security\_group\_ingress\_rules) | Map of ingress and any specific/overriding attributes to be created | `any` | {
"allow_to_connect_vpn": {
"cidr_blocks": [
"0.0.0.0/0"
],
"port": "12383",
"protocol": "udp"
}
} | no |
+| [tags](#input\_tags) | Tags to add more; default tags contian {terraform=true, environment=var.environment} | `map(string)` | `{}` | no |
+| [vpc\_id](#input\_vpc\_id) | The ID of the VPC | `string` | n/a | yes |
## Outputs
-| Name | Description |
-|------------------------------------------------------------------------------------------------|--------------------------------------------------------|
-| [efs\_dns\_name](#output\_efs\_dns\_name) | The DNS name for the filesystem |
-| [efs\_id](#output\_efs\_id) | The ID that identifies the file system for pritunl vpn |
-| [lb\_private\_dns](#output\_lb\_private\_dns) | The DNS name of the private load balancer. |
-| [lb\_public\_dns](#output\_lb\_public\_dns) | The DNS name of the public load balancer. |
-| [security\_group\_arn](#output\_security\_group\_arn) | ARN of the security group associated to this ec2 |
-| [security\_group\_id](#output\_security\_group\_id) | ID of the security group associated to this ec2 |
-| [vpn\_private\_dns](#output\_vpn\_private\_dns) | private dns for connect vpn server |
-| [vpn\_public\_dns](#output\_vpn\_public\_dns) | public dns for connect vpn server |
+| Name | Description |
+|------|-------------|
+| [efs\_dns\_name](#output\_efs\_dns\_name) | The DNS name for the filesystem |
+| [efs\_id](#output\_efs\_id) | The ID that identifies the file system for pritunl vpn |
+| [lb\_private\_dns](#output\_lb\_private\_dns) | The DNS name of the private load balancer. |
+| [lb\_public\_dns](#output\_lb\_public\_dns) | The DNS name of the public load balancer. |
+| [security\_group\_arn](#output\_security\_group\_arn) | ARN of the security group associated to this ec2 |
+| [security\_group\_id](#output\_security\_group\_id) | ID of the security group associated to this ec2 |
+| [vpn\_private\_dns](#output\_vpn\_private\_dns) | private dns for connect vpn server |
+| [vpn\_public\_dns](#output\_vpn\_public\_dns) | public dns for connect vpn server |
diff --git a/autoscaling.tf b/autoscaling.tf
deleted file mode 100644
index e7dcc00..0000000
--- a/autoscaling.tf
+++ /dev/null
@@ -1,40 +0,0 @@
-# Auto Scaling Group
-resource "aws_autoscaling_group" "this" {
- name_prefix = local.name
- vpc_zone_identifier = var.private_subnet_ids
- desired_capacity = 1
- max_size = 1 #fix 1 to avoid race condition (if not move to document db for multi read/write)
- min_size = 1
-
- launch_template {
- id = module.launch_template.id
- version = "$Latest"
- }
-
- target_group_arns = concat(aws_lb_target_group.public.*.arn, aws_lb_target_group.private.*.arn)
- dynamic "tag" {
- for_each = merge(local.tags, { Name = local.name })
- content {
- key = tag.key
- value = tag.value
- propagate_at_launch = true
- }
- }
-
- lifecycle {
- create_before_destroy = true
- }
-}
-
-
-resource "aws_autoscaling_policy" "this" {
- name = "pritunl-vpn-auto-scaling-policy"
- policy_type = "TargetTrackingScaling"
- autoscaling_group_name = aws_autoscaling_group.this.name
- target_tracking_configuration {
- predefined_metric_specification {
- predefined_metric_type = "ASGAverageCPUUtilization"
- }
- target_value = 50.0
- }
-}
diff --git a/data.tf b/data.tf
deleted file mode 100644
index 341517a..0000000
--- a/data.tf
+++ /dev/null
@@ -1,17 +0,0 @@
-data "aws_ami" "amazon_linux" {
- most_recent = true
- filter {
- name = "name"
- values = ["amzn2-ami-kernel-5.10-hvm-*"]
- }
-
- filter {
- name = "virtualization-type"
- values = ["hvm"]
- }
- owners = ["137112412989"] # amazon
-}
-
-data "aws_vpc" "this" {
- id = var.vpc_id
-}
diff --git a/efs.tf b/efs.tf
deleted file mode 100644
index 4502a90..0000000
--- a/efs.tf
+++ /dev/null
@@ -1,30 +0,0 @@
-# EFS
-module "efs" {
- source = "oozou/efs/aws"
- version = "1.0.4"
-
- prefix = var.prefix
- environment = var.environment
- name = "pritunl-data"
- encrypted = true
- enabled_backup = var.enabled_backup
- efs_backup_policy_enabled = var.efs_backup_policy_enabled
- access_points = {
- "data" = {
- posix_user = {
- gid = "1001"
- uid = "5000"
- secondary_gids = "1002,1003"
- }
- creation_info = {
- gid = "1001"
- uid = "5000"
- permissions = "0755"
- }
- }
- }
- vpc_id = var.vpc_id
- subnets = var.private_subnet_ids
-
- additional_efs_resource_policies = []
-}
diff --git a/iam.tf b/iam.tf
deleted file mode 100644
index 9a431d4..0000000
--- a/iam.tf
+++ /dev/null
@@ -1,62 +0,0 @@
-data "aws_iam_policy_document" "this" {
- statement {
- sid = "IamPassRole"
- actions = ["iam:PassRole"]
- resources = ["*"]
- condition {
- test = "StringEquals"
- variable = "iam:PassedToService"
- values = ["ec2.amazonaws.com"]
- }
- }
- statement {
- sid = "ListEc2AndListInstanceProfiles"
- actions = [
- "iam:ListInstanceProfiles",
- "ec2:Describe*",
- "ec2:Search*",
- "ec2:Get*"
- ]
- resources = ["*"]
- condition {
- test = "StringEquals"
- variable = "iam:PassedToService"
- values = ["ec2.amazonaws.com"]
- }
- }
-}
-
-data "aws_iam_policy_document" "this_assume_role" {
- statement {
- actions = ["sts:AssumeRole"]
-
- principals {
- type = "Service"
- identifiers = ["ec2.amazonaws.com"]
- }
- }
-}
-
-resource "aws_iam_role" "this" {
- name = format("%s-role", local.name)
- path = "/"
- assume_role_policy = data.aws_iam_policy_document.this_assume_role.json
-}
-
-resource "aws_iam_role_policy" "this" {
- name = format("%s-policy", local.name)
- role = aws_iam_role.this.id
-
- policy = data.aws_iam_policy_document.this.json
-}
-
-resource "aws_iam_role_policy_attachment" "this" {
- count = length(local.profile_policy_arns)
- role = aws_iam_role.this.name
- policy_arn = local.profile_policy_arns[count.index]
-}
-
-resource "aws_iam_instance_profile" "this" {
- name = format("%s-profile", local.name)
- role = aws_iam_role.this.name
-}
diff --git a/launch-template.tf b/launch-template.tf
deleted file mode 100644
index 295bdeb..0000000
--- a/launch-template.tf
+++ /dev/null
@@ -1,19 +0,0 @@
-# Launch Configuration Template
-module "launch_template" {
- source = "oozou/launch-template/aws"
- version = "1.0.3"
- prefix = var.prefix
- environment = var.environment
- name = "pritunl-vpn"
- user_data = base64encode(templatefile("${path.module}/template/user_data.sh",
- {
- efs_id = module.efs.id
- }))
- iam_instance_profile = { arn : aws_iam_instance_profile.this.arn }
- ami_id = var.ami == "" ? data.aws_ami.amazon_linux.id : var.ami
- key_name = var.key_name
- instance_type = var.instance_type
- vpc_security_group_ids = local.security_group_ids
- enable_monitoring = var.enable_ec2_monitoring
- tags = local.tags
-}
diff --git a/locals.tf b/locals.tf
deleted file mode 100644
index 25f5557..0000000
--- a/locals.tf
+++ /dev/null
@@ -1,28 +0,0 @@
-locals {
- tags = merge(
- {
- "Environment" = var.environment,
- "Terraform" = "true"
- },
- var.tags
- )
- name = format("%s-%s-%s", var.prefix, var.environment, "vpn")
- profile_policy_arns = ["arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore", "arn:aws:iam::aws:policy/AmazonElasticFileSystemClientReadWriteAccess"]
- security_group_ids = concat([module.efs.security_group_client_id], var.additional_sg_attacment_ids, var.is_create_security_group ? [aws_security_group.this[0].id] : [])
-
- console_rule = [{
- port = 443,
- protocol = "TCP"
- health_check_protocol = "TCP"
- }]
- public_rule = concat(var.public_rule, var.is_enabled_https_public ? local.console_rule : [])
- private_rule = concat(var.private_rule, local.console_rule)
- default_https_allow_cidr = var.is_enabled_https_public ? ["0.0.0.0/0"] : [data.aws_vpc.this.cidr_block]
- security_group_ingress_rules = merge({
- allow_to_config_vpn = {
- port = "443"
- cidr_blocks = var.custom_https_allow_cidr != null ? var.custom_https_allow_cidr : local.default_https_allow_cidr
- }
- },
- var.security_group_ingress_rules)
-}
diff --git a/main.tf b/main.tf
index e69de29..739828c 100644
--- a/main.tf
+++ b/main.tf
@@ -0,0 +1,379 @@
+# #############################################################################
+# Additional Data
+# #############################################################################
+locals {
+ tags = merge(
+ {
+ "Environment" = var.environment,
+ "Terraform" = "true"
+ },
+ var.tags
+ )
+ name = format("%s-%s-%s", var.prefix, var.environment, "vpn")
+ profile_policy_arns = ["arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore", "arn:aws:iam::aws:policy/AmazonElasticFileSystemClientReadWriteAccess"]
+ security_group_ids = concat([module.efs.security_group_client_id], var.additional_sg_attacment_ids, var.is_create_security_group ? [aws_security_group.this[0].id] : [])
+
+ console_rule = [{
+ port = 443,
+ protocol = "TCP"
+ health_check_protocol = "TCP"
+ }]
+ public_rule = concat(var.public_rule, var.is_enabled_https_public ? local.console_rule : [])
+ private_rule = concat(var.private_rule, local.console_rule)
+ default_https_allow_cidr = var.is_enabled_https_public ? ["0.0.0.0/0"] : [data.aws_vpc.this.cidr_block]
+ security_group_ingress_rules = merge({
+ allow_to_config_vpn = {
+ port = "443"
+ cidr_blocks = var.custom_https_allow_cidr != null ? var.custom_https_allow_cidr : local.default_https_allow_cidr
+ }
+ },
+ var.security_group_ingress_rules)
+}
+
+resource "random_string" "host_id" {
+ count = length(var.host_id) > 0 ? 0 : 1
+
+ numeric = true
+ lower = true
+ upper = false
+ length = 32
+ special = false
+}
+
+data "aws_vpc" "this" {
+ id = var.vpc_id
+}
+
+# #############################################################################
+# AMI
+# #############################################################################
+data "aws_ami" "amazon_linux" {
+ most_recent = true
+
+ filter {
+ name = "name"
+ values = ["amzn2-ami-hvm-*-x86_64-gp2"]
+ }
+
+ filter {
+ name = "architecture"
+ values = ["x86_64"]
+ }
+
+ filter {
+ name = "root-device-type"
+ values = ["ebs"]
+ }
+
+ filter {
+ name = "block-device-mapping.volume-type"
+ values = ["gp2"]
+ }
+
+ filter {
+ name = "virtualization-type"
+ values = ["hvm"]
+ }
+
+ filter {
+ name = "owner-alias"
+ values = ["amazon"]
+ }
+
+ owners = [137112412989] # amazon account id
+}
+
+# #############################################################################
+# EFS Storage
+# #############################################################################
+data "aws_iam_policy_document" "allow_access_efs_policy" {
+ statement {
+ actions = [
+ "elasticfilesystem:ClientRootAccess",
+ "elasticfilesystem:ClientWrite"
+ ]
+ principals {
+ type = "AWS"
+ identifiers = ["*"]
+ }
+ resources = ["*"]
+ condition {
+ test = "Bool"
+ variable = "elasticfilesystem:AccessedViaMountTarget"
+
+ values = [
+ "true"
+ ]
+ }
+ }
+
+ statement {
+ effect = "Deny"
+ actions = ["*"]
+ principals {
+ type = "AWS"
+ identifiers = ["*"]
+ }
+ resources = ["*"]
+ condition {
+ test = "Bool"
+ variable = "aws:SecureTransport"
+
+ values = [
+ "false"
+ ]
+ }
+ }
+}
+
+module "efs" {
+ source = "oozou/efs/aws"
+ version = "1.0.5"
+
+ prefix = var.prefix
+ environment = var.environment
+ name = "pritunl-data"
+ encrypted = true
+ enabled_backup = var.enabled_backup
+ efs_backup_policy_enabled = var.efs_backup_policy_enabled
+ access_points = {
+ "data" = {
+ posix_user = {
+ gid = "1001"
+ uid = "5000"
+ secondary_gids = "1002,1003"
+ }
+ creation_info = {
+ gid = "1001"
+ uid = "5000"
+ permissions = "0755"
+ }
+ }
+ }
+ vpc_id = var.vpc_id
+ subnets = var.private_subnet_ids
+
+ additional_efs_resource_policies = [data.aws_iam_policy_document.allow_access_efs_policy.json]
+
+ tags = var.tags
+}
+
+# #############################################################################
+# Security Groups
+# #############################################################################
+resource "aws_security_group" "this" {
+ count = var.is_create_security_group ? 1 : 0
+
+ name_prefix = format("%s-ec2-sg", local.name)
+ vpc_id = var.vpc_id
+ description = "Pritunl VPN egress rule for outbound"
+
+ egress {
+ from_port = 0
+ to_port = 0
+ protocol = "-1"
+ cidr_blocks = ["0.0.0.0/0"]
+ ipv6_cidr_blocks = ["::/0"]
+ }
+
+ tags = merge(
+ local.tags,
+ { "Name" = format("%s-ec2-sg", local.name) },
+ )
+}
+
+resource "aws_security_group_rule" "ingress" {
+ for_each = var.is_create_security_group ? local.security_group_ingress_rules : null
+
+ type = "ingress"
+ from_port = lookup(each.value, "from_port", lookup(each.value, "port", null))
+ to_port = lookup(each.value, "to_port", lookup(each.value, "port", null))
+ protocol = lookup(each.value, "protocol", "tcp")
+ security_group_id = aws_security_group.this[0].id
+
+ cidr_blocks = lookup(each.value, "cidr_blocks", null)
+ description = lookup(each.value, "description", null)
+ ipv6_cidr_blocks = lookup(each.value, "ipv6_cidr_blocks", null)
+ prefix_list_ids = lookup(each.value, "prefix_list_ids", null)
+ source_security_group_id = lookup(each.value, "source_security_group_id", null)
+}
+
+# #############################################################################
+# IAM Roles
+# #############################################################################
+data "aws_iam_policy_document" "this" {
+ statement {
+ sid = "IamPassRole"
+ actions = ["iam:PassRole"]
+ resources = ["*"]
+ condition {
+ test = "StringEquals"
+ variable = "iam:PassedToService"
+ values = ["ec2.amazonaws.com"]
+ }
+ }
+ statement {
+ sid = "ListEc2AndListInstanceProfiles"
+ actions = [
+ "iam:ListInstanceProfiles",
+ "ec2:Describe*",
+ "ec2:Search*",
+ "ec2:Get*"
+ ]
+ resources = ["*"]
+ condition {
+ test = "StringEquals"
+ variable = "iam:PassedToService"
+ values = ["ec2.amazonaws.com"]
+ }
+ }
+}
+
+data "aws_iam_policy_document" "this_assume_role" {
+ statement {
+ actions = ["sts:AssumeRole"]
+
+ principals {
+ type = "Service"
+ identifiers = ["ec2.amazonaws.com"]
+ }
+ }
+}
+
+resource "aws_iam_role" "this" {
+ name = format("%s-role", local.name)
+ path = "/"
+ assume_role_policy = data.aws_iam_policy_document.this_assume_role.json
+}
+
+resource "aws_iam_role_policy" "this" {
+ name = format("%s-policy", local.name)
+ role = aws_iam_role.this.id
+
+ policy = data.aws_iam_policy_document.this.json
+}
+
+resource "aws_iam_role_policy_attachment" "this" {
+ count = length(local.profile_policy_arns)
+ role = aws_iam_role.this.name
+ policy_arn = local.profile_policy_arns[count.index]
+}
+
+resource "aws_iam_instance_profile" "this" {
+ name = format("%s-profile", local.name)
+ role = aws_iam_role.this.name
+}
+
+resource "aws_iam_role_policy_attachment" "cloudwatch_agent" {
+ role = aws_iam_role.this.name
+ policy_arn = "arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"
+}
+
+# #############################################################################
+# Laucn Template
+# #############################################################################
+module "launch_template" {
+ source = "oozou/launch-template/aws"
+ version = "1.0.3"
+ prefix = var.prefix
+ environment = var.environment
+ name = "pritunl-vpn"
+ user_data = base64encode(templatefile("${path.module}/templates/user_data.sh",
+ {
+ cloudwatch_agent_config_file = templatefile("${path.module}/templates/cloudwatch-agent-conf.json", {
+ cloudwatch_metric_namespace = "EC2/pritunl-vpn"
+ }),
+ efs_id = module.efs.id,
+ mongodb_repo_list_file = file("${path.module}/templates/mongodb-repo.list"),
+ pritunl_repo_list_file = file("${path.module}/templates/pritunl-repo.list"),
+ mongodb_drop_in_service_file = file("${path.module}/templates/systemd-drop-in-on-failure.conf"),
+ pritunl_drop_in_service_file = file("${path.module}/templates/systemd-drop-in-on-failure.conf"),
+ pritunl_host_id = length(var.host_id) > 0 ? var.host_id : random_string.host_id[0].result
+ }))
+ iam_instance_profile = { arn : aws_iam_instance_profile.this.arn }
+ ami_id = var.ami == "" ? data.aws_ami.amazon_linux.id : var.ami
+ key_name = var.key_name
+ instance_type = var.instance_type
+ vpc_security_group_ids = local.security_group_ids
+ enable_monitoring = var.enable_ec2_monitoring
+ tags = local.tags
+}
+
+# #############################################################################
+# AutoScaling Group
+# #############################################################################
+resource "aws_autoscaling_group" "this" {
+ name_prefix = local.name
+ vpc_zone_identifier = var.private_subnet_ids
+ desired_capacity = 1
+ max_size = 1 #fix 1 to avoid race condition (if not move to document db for multi read/write)
+ min_size = 1
+
+ launch_template {
+ id = module.launch_template.id
+ version = "$Latest"
+ }
+
+ target_group_arns = concat(aws_lb_target_group.public[*].arn, aws_lb_target_group.private[*].arn)
+ dynamic "tag" {
+ for_each = merge(local.tags, { Name = local.name })
+ content {
+ key = tag.key
+ value = tag.value
+ propagate_at_launch = true
+ }
+ }
+
+ lifecycle {
+ create_before_destroy = true
+ }
+}
+
+resource "aws_autoscaling_policy" "this" {
+ name = "pritunl-vpn-auto-scaling-policy"
+ policy_type = "TargetTrackingScaling"
+ autoscaling_group_name = aws_autoscaling_group.this.name
+ target_tracking_configuration {
+ predefined_metric_specification {
+ predefined_metric_type = "ASGAverageCPUUtilization"
+ }
+ target_value = 50.0
+ }
+}
+
+# #############################################################################
+# Load Balancer
+# #############################################################################
+
+
+# #############################################################################
+# DNS Records
+# #############################################################################
+data "aws_route53_zone" "this" {
+ count = var.is_create_route53_reccord ? 1 : 0
+ name = var.route53_zone_name
+}
+
+resource "aws_route53_record" "public" {
+ count = var.is_create_route53_reccord ? 1 : 0
+ zone_id = data.aws_route53_zone.this[0].zone_id
+ name = format("%s.%s", var.public_lb_vpn_domain, var.route53_zone_name)
+ type = "A"
+ alias {
+ name = aws_lb.public.dns_name
+ zone_id = aws_lb.public.zone_id
+ evaluate_target_health = true
+ }
+}
+
+resource "aws_route53_record" "private" {
+ count = var.is_create_private_lb && var.is_create_route53_reccord ? 1 : 0
+ zone_id = data.aws_route53_zone.this[0].zone_id
+ name = format("%s.%s", var.private_lb_vpn_domain, var.route53_zone_name)
+ type = "A"
+ alias {
+ name = aws_lb.private[0].dns_name
+ zone_id = aws_lb.private[0].zone_id
+ evaluate_target_health = true
+ }
+}
diff --git a/route53.tf b/route53.tf
deleted file mode 100644
index c2cc8f4..0000000
--- a/route53.tf
+++ /dev/null
@@ -1,28 +0,0 @@
-data "aws_route53_zone" "this" {
- count = var.is_create_route53_reccord ? 1 : 0
- name = var.route53_zone_name
-}
-
-resource "aws_route53_record" "public" {
- count = var.is_create_route53_reccord ? 1 : 0
- zone_id = data.aws_route53_zone.this[0].zone_id
- name = format("%s.%s", var.public_lb_vpn_domain, var.route53_zone_name)
- type = "A"
- alias {
- name = aws_lb.public.dns_name
- zone_id = aws_lb.public.zone_id
- evaluate_target_health = true
- }
-}
-
-resource "aws_route53_record" "private" {
- count = var.is_create_private_lb && var.is_create_route53_reccord ? 1 : 0
- zone_id = data.aws_route53_zone.this[0].zone_id
- name = format("%s.%s", var.private_lb_vpn_domain, var.route53_zone_name)
- type = "A"
- alias {
- name = aws_lb.private[0].dns_name
- zone_id = aws_lb.private[0].zone_id
- evaluate_target_health = true
- }
-}
diff --git a/sg.tf b/sg.tf
deleted file mode 100644
index 1739694..0000000
--- a/sg.tf
+++ /dev/null
@@ -1,37 +0,0 @@
-# Security Group
-resource "aws_security_group" "this" {
- count = var.is_create_security_group ? 1 : 0
-
- name_prefix = format("%s-ec2-sg", local.name)
- vpc_id = var.vpc_id
- description = "Pritunl VPN egress rule for outbound"
-
- egress {
- from_port = 0
- to_port = 0
- protocol = "-1"
- cidr_blocks = ["0.0.0.0/0"]
- ipv6_cidr_blocks = ["::/0"]
- }
-
- tags = merge(
- local.tags,
- { "Name" = format("%s-ec2-sg", local.name) },
- )
-}
-
-resource "aws_security_group_rule" "ingress" {
- for_each = var.is_create_security_group ? local.security_group_ingress_rules : null
-
- type = "ingress"
- from_port = lookup(each.value, "from_port", lookup(each.value, "port", null))
- to_port = lookup(each.value, "to_port", lookup(each.value, "port", null))
- protocol = lookup(each.value, "protocol", "tcp")
- security_group_id = aws_security_group.this[0].id
-
- cidr_blocks = lookup(each.value, "cidr_blocks", null)
- description = lookup(each.value, "description", null)
- ipv6_cidr_blocks = lookup(each.value, "ipv6_cidr_blocks", null)
- prefix_list_ids = lookup(each.value, "prefix_list_ids", null)
- source_security_group_id = lookup(each.value, "source_security_group_id", null)
-}
diff --git a/template/user_data.sh b/template/user_data.sh
deleted file mode 100644
index e33ded8..0000000
--- a/template/user_data.sh
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/bin/bash -x
-
-sudo yum update -y
-sudo yum -y install wget
-if [[ "$(python3 -V 2>&1)" =~ ^(Python 3.6.*) ]]; then
- sudo wget https://bootstrap.pypa.io/pip/3.6/get-pip.py -O /tmp/get-pip.py
-elif [[ "$(python3 -V 2>&1)" =~ ^(Python 3.5.*) ]]; then
- sudo wget https://bootstrap.pypa.io/pip/3.5/get-pip.py -O /tmp/get-pip.py
-elif [[ "$(python3 -V 2>&1)" =~ ^(Python 3.4.*) ]]; then
- sudo wget https://bootstrap.pypa.io/pip/3.4/get-pip.py -O /tmp/get-pip.py
-else
- sudo wget https://bootstrap.pypa.io/get-pip.py -O /tmp/get-pip.py
-fi
-sudo python3 /tmp/get-pip.py
-sudo /usr/local/bin/pip3 install botocore
-sudo yum install -y amazon-efs-utils
-sudo mkdir /mnt/efs
-echo "${efs_id}:/ /mnt/efs efs _netdev,noresvport,tls,iam 0 0" | sudo tee -a /etc/fstab
-sudo mount -a
-sudo tee /etc/yum.repos.d/mongodb-org-5.0.repo << EOF
-[mongodb-org-5.0]
-name=MongoDB Repository
-baseurl=https://repo.mongodb.org/yum/amazon/2/mongodb-org/5.0/x86_64/
-gpgcheck=1
-enabled=1
-gpgkey=https://www.mongodb.org/static/pgp/server-5.0.asc
-EOF
-sudo tee /etc/yum.repos.d/pritunl.repo << EOF
-[pritunl]
-name=Pritunl Repository
-baseurl=https://repo.pritunl.com/stable/yum/amazonlinux/2/
-gpgcheck=1
-enabled=1
-EOF
-sudo rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
-gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys 7568D9BB55FF9E5287D586017AE645C0CF8E292A
-gpg --armor --export 7568D9BB55FF9E5287D586017AE645C0CF8E292A > key.tmp;
-sudo rpm --import key.tmp; rm -f key.tmp
-sudo yum -y install pritunl mongodb-org-5.0.9-1.amzn2
-
-sudo sed -i.bak "s/\/var\/lib\/mongo/\/mnt\/efs/g" /etc/mongod.conf
-sudo chown -R mongod:mongod /mnt/efs/
-
-sudo systemctl start mongod pritunl
-sudo systemctl enable mongod pritunl
-sudo pritunl set-mongodb mongodb://localhost:27017/pritunl
-sudo pritunl set app.redirect_server false
-sudo pritunl set app.server_ssl true
-sudo pritunl set app.server_port 443
-sudo pritunl set app.www_path /usr/share/pritunl/www
-sudo systemctl restart pritunl
diff --git a/templates/cloudwatch-agent-conf.json b/templates/cloudwatch-agent-conf.json
new file mode 100644
index 0000000..484e321
--- /dev/null
+++ b/templates/cloudwatch-agent-conf.json
@@ -0,0 +1,111 @@
+{
+ "agent": {
+ "metrics_collection_interval": 10
+ },
+ "logs": {
+ "logs_collected": {
+ "files": {
+ "collect_list": [
+ {
+ "file_path": "/var/log/messages",
+ "log_group_name": "/aws/ec2/pritunl-vpn",
+ "log_stream_name": "syslog",
+ "timestamp_format": "%H: %M: %S%y%b%-d"
+ },
+ {
+ "file_path": "/var/log/pritunl.log",
+ "log_group_name": "/aws/ec2/pritunl-vpn",
+ "log_stream_name": "pritunl",
+ "timestamp_format": "%H: %M: %S%y%b%-d"
+ },
+ {
+ "file_path": "/var/log/mongodb/mongod.log",
+ "log_group_name": "/aws/ec2/pritunl-vpn",
+ "log_stream_name": "mongod",
+ "timestamp_format": "%H: %M: %S%y%b%-d"
+ }
+ ]
+ }
+ }
+ },
+ "metrics": {
+ "namespace": "${cloudwatch_metric_namespace}",
+ "append_dimensions": {
+ "AutoScalingGroupName": "$${aws:AutoScalingGroupName}",
+ "ImageId": "$${aws:ImageId}",
+ "InstanceId": "$${aws:InstanceId}",
+ "InstanceType": "$${aws:InstanceType}",
+ "InstanceRole": "gitlab-runner"
+ },
+ "aggregation_dimensions": [
+ [
+ "InstanceType",
+ "AutoScalingGroupName"
+ ],
+ [
+ "InstanceId",
+ "InstanceType"
+ ],
+ [
+ "InstanceId"
+ ],
+ [
+ "InstanceRole"
+ ]
+ ],
+ "metrics_collected": {
+ "cpu": {
+ "measurement": [
+ "usage_idle",
+ "usage_iowait",
+ "usage_user",
+ "usage_system"
+ ]
+ },
+ "disk": {
+ "resources": [
+ "/",
+ "/tmp"
+ ],
+ "measurement": [
+ "used_percent",
+ "inodes_free"
+ ],
+ "ignore_file_system_types": [
+ "sysfs",
+ "devtmpfs"
+ ]
+ },
+ "diskio": {
+ "measurement": [
+ "io_time",
+ "write_bytes",
+ "read_bytes",
+ "writes",
+ "reads"
+ ]
+ },
+ "mem": {
+ "measurement": [
+ "available",
+ "available_percent",
+ "used",
+ "used_percent"
+ ]
+ },
+ "netstat": {
+ "measurement": [
+ "tcp_established",
+ "tcp_time_wait"
+ ]
+ },
+ "swap": {
+ "measurement": [
+ "used",
+ "free",
+ "used_percent"
+ ]
+ }
+ }
+ }
+}
diff --git a/templates/mongodb-repo.list b/templates/mongodb-repo.list
new file mode 100644
index 0000000..d46ceb5
--- /dev/null
+++ b/templates/mongodb-repo.list
@@ -0,0 +1,6 @@
+[mongodb-org-5.0]
+name=MongoDB Repository
+baseurl=https://repo.mongodb.org/yum/amazon/2/mongodb-org/5.0/x86_64/
+gpgcheck=1
+enabled=1
+gpgkey=https://www.mongodb.org/static/pgp/server-5.0.asc
diff --git a/templates/pritunl-repo.list b/templates/pritunl-repo.list
new file mode 100644
index 0000000..c106252
--- /dev/null
+++ b/templates/pritunl-repo.list
@@ -0,0 +1,5 @@
+[pritunl]
+name=Pritunl Repository
+baseurl=https://repo.pritunl.com/stable/yum/amazonlinux/2/
+gpgcheck=1
+enabled=1
diff --git a/templates/systemd-drop-in-on-failure.conf b/templates/systemd-drop-in-on-failure.conf
new file mode 100644
index 0000000..ae58d81
--- /dev/null
+++ b/templates/systemd-drop-in-on-failure.conf
@@ -0,0 +1,3 @@
+[Service]
+Restart=on-failure
+RestartSec=30s
diff --git a/templates/user_data.sh b/templates/user_data.sh
new file mode 100644
index 0000000..1cd76bc
--- /dev/null
+++ b/templates/user_data.sh
@@ -0,0 +1,104 @@
+#!/bin/bash -xe
+
+# # Redirect stdout from user_data to console log
+# # https://aws.amazon.com/premiumsupport/knowledge-center/ec2-linux-log-user-data/
+# exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1
+
+echo "###################################################################
+# Script Name : amazon-linux-pritunl-install.sh
+# Description : Bootstrap Script to install PritunlVPN on Amazon Linux
+# Args :
+# Author : DevOps@OOZOU
+# Email : devops@oozou.com
+###################################################################"
+
+echo ">>> Installing SSM Agent ..."
+sudo yum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm
+echo ">>> Enabling SSM Agent ..."
+sudo systemctl start amazon-ssm-agent
+
+echo ">>> Installing CloudWatch Agent ..."
+sudo yum install -y amazon-cloudwatch-agent
+echo '${cloudwatch_agent_config_file}' | sudo tee /tmp/cloudwatch-agent-config.json
+echo ">>> Reconfiguring CloudWatch Agent ..."
+sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \
+-a fetch-config \
+-m ec2 \
+-c file:///tmp/cloudwatch-agent-config.json -s
+echo ">>> Restarting amazon-cloudwatch-agent service..."
+sudo systemctl restart amazon-cloudwatch-agent
+sudo systemctl enable amazon-cloudwatch-agent
+
+echo ">>> Preparing OS to install PritunlVPN ..."
+sudo yum update -y
+sudo yum -y install wget
+if [[ "$(python3 -V 2>&1)" =~ ^(Python 3.6.*) ]]; then
+ sudo wget https://bootstrap.pypa.io/pip/3.6/get-pip.py -O /tmp/get-pip.py
+elif [[ "$(python3 -V 2>&1)" =~ ^(Python 3.5.*) ]]; then
+ sudo wget https://bootstrap.pypa.io/pip/3.5/get-pip.py -O /tmp/get-pip.py
+elif [[ "$(python3 -V 2>&1)" =~ ^(Python 3.4.*) ]]; then
+ sudo wget https://bootstrap.pypa.io/pip/3.4/get-pip.py -O /tmp/get-pip.py
+else
+ sudo wget https://bootstrap.pypa.io/get-pip.py -O /tmp/get-pip.py
+fi
+sudo python3 /tmp/get-pip.py
+sudo /usr/local/bin/pip3 install botocore
+
+echo ">>> Installing EFS client for PritunlVPN data ..."
+sudo yum install -y amazon-efs-utils
+echo ">>> Mounting EFS volume to instance ..."
+sudo mkdir /mnt/efs
+echo "${efs_id}:/ /mnt/efs efs _netdev,noresvport,tls,iam 0 0" | sudo tee -a /etc/fstab
+sudo mount -a
+
+echo ">>> Adding MongoDB Repository to package manager ..."
+echo '${mongodb_repo_list_file}' | sudo tee /etc/yum.repos.d/mongodb-org-5.0.repo
+echo ">>> Adding MongoDB Repository to package manager ..."
+echo '${pritunl_repo_list_file}' | sudo tee /etc/yum.repos.d/pritunl.repo
+
+echo ">>> Adding Keys for package manager ..."
+sudo rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
+gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys 7568D9BB55FF9E5287D586017AE645C0CF8E292A
+gpg --armor --export 7568D9BB55FF9E5287D586017AE645C0CF8E292A > key.tmp;
+sudo rpm --import key.tmp; rm -f key.tmp
+echo ">>> Installing PritunlVPN and MongoDB ..."
+sudo yum -y install pritunl mongodb-org
+
+echo ">>> Setting up data volume for MongoDB ..."
+sudo sed -i.bak "s/\/var\/lib\/mongo/\/mnt\/efs/g" /etc/mongod.conf
+sudo chown -R mongod:mongod /mnt/efs/
+
+echo ">>> Setting up drop-in service for MongoDB and Pritunl"
+# Auto Restart MongoDB to prevent it faile to start on the first time.
+sudo mkdir -p /etc/systemd/system/mongod.d
+sudo mkdir -p /etc/systemd/system/pritunl.d
+echo "${mongodb_drop_in_service_file}" | sudo tee /etc/systemd/system/mongod.d/10-auto-restart-on-failure.conf
+echo "${pritunl_drop_in_service_file}" | sudo tee /etc/systemd/system/pritunl.d/10-auto-restart-on-failure.conf
+sudo systemctl daemon-reload
+
+echo ">>> Starting MongoDB service ..."
+sudo systemctl start mongod pritunl
+sudo systemctl enable mongod pritunl
+
+# Prevent MongoDB's crashed by db lock
+echo ">>> Delaying for MongoDB startup (1m) ..."
+sleep 60
+
+echo ">>> Starting PritunlVPN service ..."
+sudo systemctl start pritunl
+sudo systemctl enable pritunl
+
+# Prevent Pritunl Failed to start when MongoDB's failed to start
+echo ">>> Delaying for PritunlVPN startup (1m) ..."
+sleep 60
+
+echo ">>> Reconfiguring PritunlVPN ..."
+sudo pritunl set-host-id "${pritunl_host_id}"
+sudo pritunl set-mongodb mongodb://localhost:27017/pritunl
+sudo pritunl set app.redirect_server false
+sudo pritunl set app.server_ssl true
+sudo pritunl set app.server_port 443
+sudo pritunl set app.www_path /usr/share/pritunl/www
+
+echo ">>> Reload PritunlVPN configuration ..."
+sudo systemctl restart pritunl
diff --git a/variables.tf b/variables.tf
index f7b9ed0..e957373 100644
--- a/variables.tf
+++ b/variables.tf
@@ -159,3 +159,9 @@ variable "is_create_private_lb" {
type = bool
default = true
}
+
+variable "host_id" {
+ description = "Override PritunlVPN host id with this option, Use with migration only (https://docs.pritunl.com/docs/backup)"
+ type = string
+ default = ""
+}
diff --git a/versions.tf b/versions.tf
index 521a51d..ee129e0 100644
--- a/versions.tf
+++ b/versions.tf
@@ -6,5 +6,9 @@ terraform {
source = "hashicorp/aws"
version = ">= 4.0.0"
}
+ random = {
+ source = "hashicorp/random"
+ version = ">= 3.0.0"
+ }
}
}