diff --git a/deployment/terraform/aws/main.tf b/deployment/terraform/aws/main.tf
new file mode 100644
index 000000000..75a8f7212
--- /dev/null
+++ b/deployment/terraform/aws/main.tf
@@ -0,0 +1,93 @@
+provider "aws" {
+ alias = "region_1"
+ region = var.region_1
+}
+
+provider "aws" {
+ alias = "region_2"
+ region = var.region_2
+}
+
+# Validator
+module "validator" {
+ source = "./validator"
+ providers = {
+ aws = aws.region_1
+ }
+}
+
+# Private Sentries
+module "private_sentries" {
+ source = "./private-sentries"
+
+ providers = {
+ aws = aws.region_1
+ aws.peer = aws.region_1
+ }
+
+ peer_vpc = module.validator.vpc
+}
+
+# Public Sentries region 1
+module "public_sentries_1" {
+ source = "./public-sentries"
+ nodes_count = 1
+
+ # enable_ipv6 = false
+
+ providers = {
+ aws = aws.region_1
+ aws.peer = aws.region_1
+ }
+
+ region_index = 1
+ peer_vpc = module.private_sentries.vpc
+}
+
+# Public Sentries region 2
+module "public_sentries_2" {
+ source = "./public-sentries"
+ nodes_count = 1
+
+ # enable_ipv6 = false
+
+ providers = {
+ aws = aws.region_2
+ aws.peer = aws.region_1
+ }
+
+ region_index = 2
+ peer_vpc = module.private_sentries.vpc
+}
+
+# Observers region 1
+module "observers_1" {
+ source = "./observers"
+
+ providers = {
+ aws = aws.region_1
+ aws.peer = aws.region_1
+ }
+
+ root_domain_name = var.root_domain_name
+ enable_tls = var.enable_tls
+
+ region_index = 1
+ peer_vpc = module.private_sentries.vpc
+}
+
+# Observers region 2
+module "observers_2" {
+ source = "./observers"
+
+ providers = {
+ aws = aws.region_2
+ aws.peer = aws.region_1
+ }
+
+ root_domain_name = var.root_domain_name
+ enable_tls = var.enable_tls
+
+ region_index = 2
+ peer_vpc = module.private_sentries.vpc
+}
\ No newline at end of file
diff --git a/deployment/terraform/aws/observers/acm.tf b/deployment/terraform/aws/observers/acm.tf
new file mode 100644
index 000000000..179243db0
--- /dev/null
+++ b/deployment/terraform/aws/observers/acm.tf
@@ -0,0 +1,25 @@
+resource "aws_acm_certificate" "this_acm_cert" {
+ count = local.enable_tls ? 1 : 0
+
+ domain_name = "on.${data.aws_route53_zone.this_zone[0].name}"
+ validation_method = "DNS"
+}
+
+resource "aws_route53_record" "this_acm_val_records" {
+ count = local.enable_tls ? length(aws_acm_certificate.this_acm_cert[0].domain_validation_options) : 0
+
+ name = tolist(aws_acm_certificate.this_acm_cert[0].domain_validation_options)[count.index].resource_record_name
+ records = [tolist(aws_acm_certificate.this_acm_cert[0].domain_validation_options)[count.index].resource_record_value]
+ type = tolist(aws_acm_certificate.this_acm_cert[0].domain_validation_options)[count.index].resource_record_type
+
+ allow_overwrite = true
+ ttl = 60
+ zone_id = data.aws_route53_zone.this_zone[0].zone_id
+}
+
+resource "aws_acm_certificate_validation" "this_acm_cert_validation" {
+ count = local.enable_tls ? 1 : 0
+
+ certificate_arn = aws_acm_certificate.this_acm_cert[0].arn
+ validation_record_fqdns = aws_route53_record.this_acm_val_records[*].fqdn
+}
diff --git a/deployment/terraform/aws/observers/elb.tf b/deployment/terraform/aws/observers/elb.tf
new file mode 100644
index 000000000..a6e6d7265
--- /dev/null
+++ b/deployment/terraform/aws/observers/elb.tf
@@ -0,0 +1,162 @@
+resource "aws_lb" "this_nlb" {
+ name = "observers-network-lb"
+ internal = false
+ load_balancer_type = "network"
+ subnets = module.this_vpc.public_subnets
+
+ enable_cross_zone_load_balancing = true
+ # enable_deletion_protection = true
+
+ tags = {
+ Name = "Observers NLB"
+ }
+}
+
+locals {
+ tls_cert_arn = var.enable_tls ? aws_acm_certificate_validation.this_acm_cert_validation[0].certificate_arn : ""
+ ssl_policy = "ELBSecurityPolicy-TLS13-1-2-2021-06" # TLS 1.3 (recommended)
+}
+
+resource "aws_lb_listener" "rest" {
+ count = local.enable_tls ? 0 : 1
+
+ load_balancer_arn = aws_lb.this_nlb.arn
+ port = "80"
+ protocol = "TCP"
+
+ default_action {
+ type = "forward"
+ target_group_arn = aws_lb_target_group.rest.arn
+ }
+}
+
+resource "aws_lb_listener" "grpc" {
+ count = local.enable_tls ? 0 : 1
+
+ load_balancer_arn = aws_lb.this_nlb.arn
+ port = "9090"
+ protocol = "TCP"
+
+ default_action {
+ type = "forward"
+ target_group_arn = aws_lb_target_group.grpc.arn
+ }
+}
+
+resource "aws_lb_listener" "rpc" {
+ count = local.enable_tls ? 0 : 1
+
+ load_balancer_arn = aws_lb.this_nlb.arn
+ port = "8080"
+ protocol = "TCP"
+
+ default_action {
+ type = "forward"
+ target_group_arn = aws_lb_target_group.rpc.arn
+ }
+}
+
+resource "aws_lb_listener" "tls_rest" {
+ count = local.enable_tls ? 1 : 0
+
+ load_balancer_arn = aws_lb.this_nlb.arn
+ port = "443"
+ protocol = "TLS"
+ certificate_arn = local.tls_cert_arn
+ ssl_policy = local.ssl_policy
+
+ default_action {
+ type = "forward"
+ target_group_arn = aws_lb_target_group.rest.arn
+ }
+
+ depends_on = [
+ aws_acm_certificate_validation.this_acm_cert_validation[0]
+ ]
+}
+
+resource "aws_lb_listener" "tls_grpc" {
+ count = local.enable_tls ? 1 : 0
+
+ load_balancer_arn = aws_lb.this_nlb.arn
+ port = "8443"
+ protocol = "TLS"
+ certificate_arn = local.tls_cert_arn
+ ssl_policy = local.ssl_policy
+
+ default_action {
+ type = "forward"
+ target_group_arn = aws_lb_target_group.grpc.arn
+ }
+
+ depends_on = [
+ aws_acm_certificate_validation.this_acm_cert_validation[0]
+ ]
+}
+
+resource "aws_lb_listener" "tls_rpc" {
+ count = local.enable_tls ? 1 : 0
+
+ load_balancer_arn = aws_lb.this_nlb.arn
+ port = "26657"
+ protocol = "TLS"
+ certificate_arn = local.tls_cert_arn
+ ssl_policy = local.ssl_policy
+
+ default_action {
+ type = "forward"
+ target_group_arn = aws_lb_target_group.rpc.arn
+ }
+
+ depends_on = [
+ aws_acm_certificate_validation.this_acm_cert_validation[0]
+ ]
+}
+
+resource "aws_lb_target_group" "rest" {
+ name = "observers-rest-target-group"
+ port = 1317
+ protocol = "TCP"
+ vpc_id = module.this_vpc.vpc_id
+ preserve_client_ip = false
+}
+
+resource "aws_lb_target_group" "grpc" {
+ name = "observers-grpc-target-group"
+ port = 9090
+ protocol = "TCP"
+ vpc_id = module.this_vpc.vpc_id
+ preserve_client_ip = false
+}
+
+resource "aws_lb_target_group" "rpc" {
+ name = "observers-rpc-target-group"
+ port = 26657
+ protocol = "TCP"
+ vpc_id = module.this_vpc.vpc_id
+ preserve_client_ip = false
+}
+
+resource "aws_lb_target_group_attachment" "rest_targets" {
+ count = length(aws_instance.this_nodes)
+
+ target_group_arn = aws_lb_target_group.rest.arn
+ target_id = aws_instance.this_nodes[count.index].id
+ port = 80
+}
+
+resource "aws_lb_target_group_attachment" "grpc_targets" {
+ count = length(aws_instance.this_nodes)
+
+ target_group_arn = aws_lb_target_group.grpc.arn
+ target_id = aws_instance.this_nodes[count.index].id
+ port = 9090
+}
+
+resource "aws_lb_target_group_attachment" "rpc_targets" {
+ count = length(aws_instance.this_nodes)
+
+ target_group_arn = aws_lb_target_group.rpc.arn
+ target_id = aws_instance.this_nodes[count.index].id
+ port = 26657
+}
\ No newline at end of file
diff --git a/deployment/terraform/aws/observers/locals.tf b/deployment/terraform/aws/observers/locals.tf
new file mode 100644
index 000000000..02dd04920
--- /dev/null
+++ b/deployment/terraform/aws/observers/locals.tf
@@ -0,0 +1,3 @@
+locals {
+ enable_tls = var.enable_tls && var.root_domain_name != ""
+}
\ No newline at end of file
diff --git a/deployment/terraform/aws/observers/main.tf b/deployment/terraform/aws/observers/main.tf
new file mode 100644
index 000000000..81e33786d
--- /dev/null
+++ b/deployment/terraform/aws/observers/main.tf
@@ -0,0 +1,43 @@
+data "aws_ami" "ubuntu" {
+ most_recent = true
+ owners = ["099720109477"]
+
+ filter {
+ name = "name"
+ values = ["ubuntu-minimal/images/hvm-ssd/ubuntu-focal-20.04-amd64-minimal-*"]
+ }
+
+ filter {
+ name = "virtualization-type"
+ values = ["hvm"]
+ }
+}
+
+resource "aws_key_pair" "key_pair" {
+ public_key = file(var.ssh_public_key_path)
+}
+
+resource "aws_instance" "this_nodes" {
+ count = var.nodes_count
+
+ ami = data.aws_ami.ubuntu.id
+ instance_type = "t3.medium"
+
+ subnet_id = element(module.this_vpc.public_subnets, count.index % length(module.this_vpc.public_subnets))
+ vpc_security_group_ids = [
+ module.this_dev_sg.security_group_id,
+ module.this_private_sg.security_group_id
+ ]
+
+ key_name = aws_key_pair.key_pair.id
+ monitoring = true
+
+ tags = {
+ Name = "Observer Node [${count.index}]"
+ }
+
+ root_block_device {
+ encrypted = true
+ volume_size = 30
+ }
+}
\ No newline at end of file
diff --git a/deployment/terraform/aws/observers/outputs.tf b/deployment/terraform/aws/observers/outputs.tf
new file mode 100644
index 000000000..e69de29bb
diff --git a/deployment/terraform/aws/observers/provider.tf b/deployment/terraform/aws/observers/provider.tf
new file mode 100644
index 000000000..9abe0ebfd
--- /dev/null
+++ b/deployment/terraform/aws/observers/provider.tf
@@ -0,0 +1,9 @@
+terraform {
+ required_providers {
+ aws = {
+ source = "hashicorp/aws"
+ version = ">= 3.72"
+ configuration_aliases = [aws, aws.peer]
+ }
+ }
+}
\ No newline at end of file
diff --git a/deployment/terraform/aws/observers/route53.tf b/deployment/terraform/aws/observers/route53.tf
new file mode 100644
index 000000000..cbe1d5398
--- /dev/null
+++ b/deployment/terraform/aws/observers/route53.tf
@@ -0,0 +1,26 @@
+locals {
+ enable_routing = var.root_domain_name == "" ? 0 : 1
+}
+
+data "aws_route53_zone" "this_zone" {
+ count = local.enable_routing
+ name = var.root_domain_name
+}
+
+data "aws_region" "current" {}
+
+resource "aws_route53_record" "on" {
+ count = local.enable_routing
+
+ zone_id = data.aws_route53_zone.this_zone[0].zone_id
+ name = "on.${data.aws_route53_zone.this_zone[0].name}"
+ type = "CNAME"
+ ttl = "300"
+
+ latency_routing_policy {
+ region = data.aws_region.current.name
+ }
+
+ set_identifier = "Observers NLB [${var.region_index}]"
+ records = ["${aws_lb.this_nlb.dns_name}"]
+}
\ No newline at end of file
diff --git a/deployment/terraform/aws/observers/security.tf b/deployment/terraform/aws/observers/security.tf
new file mode 100644
index 000000000..a5e993e1e
--- /dev/null
+++ b/deployment/terraform/aws/observers/security.tf
@@ -0,0 +1,55 @@
+module "this_dev_sg" {
+ source = "terraform-aws-modules/security-group/aws"
+ version = "~> 4.0"
+
+ name = "observer-dev-security-group"
+ description = "Observer nodes security group for development"
+
+ vpc_id = module.this_vpc.vpc_id
+
+ ingress_cidr_blocks = ["0.0.0.0/0"]
+ ingress_rules = ["all-icmp", "ssh-tcp"]
+ egress_rules = ["all-all"]
+}
+
+module "this_private_sg" {
+ source = "terraform-aws-modules/security-group/aws"
+ version = "~> 4.0"
+
+ name = "observer-private-security-group"
+ description = "Observer nodes security group for internal connections"
+
+ vpc_id = module.this_vpc.vpc_id
+
+ egress_rules = ["all-all"]
+ ingress_with_cidr_blocks = [
+ {
+ from_port = 26656
+ to_port = 26656
+ protocol = "tcp"
+ description = "Allow p2p from internal IPs"
+ cidr_blocks = "10.0.0.0/8"
+ },
+ {
+ from_port = 26657
+ to_port = 26657
+ protocol = "tcp"
+ description = "Allow RPC from internal IPs"
+ cidr_blocks = "10.0.0.0/8"
+ },
+ {
+ from_port = 9090
+ to_port = 9090
+ protocol = "tcp"
+ description = "Allow gRPC from internal IPs"
+ cidr_blocks = "10.0.0.0/8"
+ },
+ {
+ from_port = 1317
+ to_port = 1317
+ protocol = "tcp"
+ description = "Allow REST from internal IPs"
+ cidr_blocks = "10.0.0.0/8"
+ },
+ ]
+}
\ No newline at end of file
diff --git a/deployment/terraform/aws/observers/variables.tf b/deployment/terraform/aws/observers/variables.tf
new file mode 100644
index 000000000..ceb1eb93c
--- /dev/null
+++ b/deployment/terraform/aws/observers/variables.tf
@@ -0,0 +1,38 @@
+variable "ssh_public_key_path" {
+ description = "SSH public key file path"
+ default = "~/.ssh/id_rsa.pub"
+}
+
+variable "ssh_private_key_path" {
+ description = "SSH private key file path"
+ default = "~/.ssh/id_rsa"
+}
+
+variable "ssh_username" {
+ description = "SSH username"
+ default = "ubuntu"
+}
+
+variable "nodes_count" {
+ description = "Number of Observer nodes"
+ default = 5
+}
+
+variable "region_index" {
+ description = "Observer Region Index"
+ default = 0
+}
+
+variable "enable_tls" {
+ description = "Enable TLS on LB listeners"
+ default = false
+}
+
+variable "root_domain_name" {
+ description = "Root domain name"
+ default = ""
+}
+
+variable "peer_vpc" {
+ description = "Peer VPC"
+}
diff --git a/deployment/terraform/aws/observers/vpc.tf b/deployment/terraform/aws/observers/vpc.tf
new file mode 100644
index 000000000..c15b48a0a
--- /dev/null
+++ b/deployment/terraform/aws/observers/vpc.tf
@@ -0,0 +1,22 @@
+data "aws_availability_zones" "available" {
+ state = "available"
+}
+
+locals {
+ vpc_network_prefix = "10.${30 + var.region_index}"
+}
+
+module "this_vpc" {
+ source = "terraform-aws-modules/vpc/aws"
+ version = "3.14.0"
+
+ name = "observers-vpc-1"
+ cidr = "${local.vpc_network_prefix}.0.0/16"
+
+ azs = [data.aws_availability_zones.available.names[0], data.aws_availability_zones.available.names[1]]
+
+ public_subnets = ["${local.vpc_network_prefix}.1.0/24", "${local.vpc_network_prefix}.2.0/24"]
+
+ enable_nat_gateway = true
+ enable_dns_hostnames = true
+}
diff --git a/deployment/terraform/aws/observers/vpc_peering.tf b/deployment/terraform/aws/observers/vpc_peering.tf
new file mode 100644
index 000000000..afc910b27
--- /dev/null
+++ b/deployment/terraform/aws/observers/vpc_peering.tf
@@ -0,0 +1,21 @@
+module "this_vpc_peerings" {
+ source = "grem11n/vpc-peering/aws"
+ version = "4.1.0"
+
+ providers = {
+ aws.this = aws
+ aws.peer = aws.peer
+ }
+
+ this_vpc_id = module.this_vpc.vpc_id
+ peer_vpc_id = var.peer_vpc.vpc_id
+
+ this_rts_ids = module.this_vpc.public_route_table_ids
+ peer_rts_ids = [element(var.peer_vpc.public_route_table_ids, 0)]
+
+ auto_accept_peering = true
+
+ tags = {
+ Name = "Observers to Private Sentries peering"
+ }
+}
\ No newline at end of file
diff --git a/deployment/terraform/aws/private-sentries/main.tf b/deployment/terraform/aws/private-sentries/main.tf
new file mode 100644
index 000000000..98a97396a
--- /dev/null
+++ b/deployment/terraform/aws/private-sentries/main.tf
@@ -0,0 +1,54 @@
+data "aws_ami" "ubuntu" {
+ most_recent = true
+ owners = ["099720109477"]
+
+ filter {
+ name = "name"
+ values = ["ubuntu-minimal/images/hvm-ssd/ubuntu-focal-20.04-amd64-minimal-*"]
+ }
+
+ filter {
+ name = "virtualization-type"
+ values = ["hvm"]
+ }
+}
+
+resource "aws_key_pair" "key_pair" {
+ public_key = file(var.ssh_public_key_path)
+}
+
+resource "aws_instance" "this_nodes" {
+ count = var.nodes_count
+
+ ami = data.aws_ami.ubuntu.id
+ instance_type = "t3.medium"
+
+ subnet_id = element(module.this_vpc.public_subnets, 0)
+ vpc_security_group_ids = [
+ module.this_dev_sg.security_group_id,
+ module.this_private_sg.security_group_id,
+ module.this_public_sg.security_group_id
+ ]
+
+ key_name = aws_key_pair.key_pair.id
+ monitoring = true
+
+ tags = {
+ Name = "Private Sentry Node ${count.index}"
+ }
+
+ root_block_device {
+ encrypted = true
+ volume_size = 30
+ }
+}
+
+resource "aws_eip" "this_eip" {
+ count = length(aws_instance.this_nodes) > 0 ? 1 : 0
+ instance = aws_instance.this_nodes[0].id
+ vpc = true
+
+ tags = {
+ Name = "Private Sentry Node ${count.index} Elastic IP"
+ }
+}
\ No newline at end of file
diff --git a/deployment/terraform/aws/private-sentries/outputs.tf b/deployment/terraform/aws/private-sentries/outputs.tf
new file mode 100644
index 000000000..12bcae675
--- /dev/null
+++ b/deployment/terraform/aws/private-sentries/outputs.tf
@@ -0,0 +1,3 @@
+output "vpc" {
+ value = module.this_vpc
+}
\ No newline at end of file
diff --git a/deployment/terraform/aws/private-sentries/provider.tf b/deployment/terraform/aws/private-sentries/provider.tf
new file mode 100644
index 000000000..9abe0ebfd
--- /dev/null
+++ b/deployment/terraform/aws/private-sentries/provider.tf
@@ -0,0 +1,9 @@
+terraform {
+ required_providers {
+ aws = {
+ source = "hashicorp/aws"
+ version = ">= 3.72"
+ configuration_aliases = [aws, aws.peer]
+ }
+ }
+}
\ No newline at end of file
diff --git a/deployment/terraform/aws/private-sentries/security.tf b/deployment/terraform/aws/private-sentries/security.tf
new file mode 100644
index 000000000..60269d6a3
--- /dev/null
+++ b/deployment/terraform/aws/private-sentries/security.tf
@@ -0,0 +1,62 @@
+module "this_dev_sg" {
+ source = "terraform-aws-modules/security-group/aws"
+ version = "~> 4.0"
+
+ name = "private-sentry-dev-security-group"
+ description = "Private Sentry nodes security group for development"
+ vpc_id = module.this_vpc.vpc_id
+
+ ingress_cidr_blocks = ["0.0.0.0/0"]
+ ingress_rules = ["all-icmp", "ssh-tcp"]
+ egress_rules = ["all-all"]
+}
+
+module "this_private_sg" {
+ source = "terraform-aws-modules/security-group/aws"
+ version = "~> 4.0"
+
+ name = "private-sentry-private-security-group"
+ description = "Private Sentry nodes security group for internal connections"
+ vpc_id = module.this_vpc.vpc_id
+
+ egress_rules = ["all-all"]
+ ingress_with_cidr_blocks = [
+ {
+ from_port = 26656
+ to_port = 26656
+ protocol = "tcp"
+ description = "Allow p2p from internal IPs"
+ cidr_blocks = "10.0.0.0/8"
+ },
+ {
+ from_port = 26657
+ to_port = 26657
+ protocol = "tcp"
+ description = "Allow RPC from internal IPs"
+ cidr_blocks = "10.0.0.0/8"
+ },
+ ]
+}
+
+module "this_public_sg" {
+ source = "terraform-aws-modules/security-group/aws"
+ version = "~> 4.0"
+
+ name = "private-sentry-public-security-group"
+ description = "Private Sentry nodes security group for external connections"
+ vpc_id = module.this_vpc.vpc_id
+
+ # ingress_cidr_blocks = ["10.0.0.0/8"]
+ egress_rules = ["all-all"]
+
+
+ ingress_with_cidr_blocks = [
+ {
+ from_port = 26656
+ to_port = 26656
+ protocol = "tcp"
+ description = "Allow P2P from Some Organization"
+ cidr_blocks = "10.1.1.1/32" # whitelist IP
+ },
+ ]
+}
\ No newline at end of file
diff --git a/deployment/terraform/aws/private-sentries/variables.tf b/deployment/terraform/aws/private-sentries/variables.tf
new file mode 100644
index 000000000..a29d22eb9
--- /dev/null
+++ b/deployment/terraform/aws/private-sentries/variables.tf
@@ -0,0 +1,23 @@
+variable "ssh_public_key_path" {
+ description = "SSH public key file path"
+ default = "~/.ssh/id_rsa.pub"
+}
+
+variable "ssh_private_key_path" {
+ description = "SSH private key file path"
+ default = "~/.ssh/id_rsa"
+}
+
+variable "ssh_username" {
+ description = "SSH username"
+ default = "ubuntu"
+}
+
+variable "peer_vpc" {
+ description = "Peer VPC"
+}
+
+variable "nodes_count" {
+ description = "Number of Private Sentry nodes"
+ default = 2
+}
\ No newline at end of file
diff --git a/deployment/terraform/aws/private-sentries/vpc.tf b/deployment/terraform/aws/private-sentries/vpc.tf
new file mode 100644
index 000000000..56412bda2
--- /dev/null
+++ b/deployment/terraform/aws/private-sentries/vpc.tf
@@ -0,0 +1,22 @@
+data "aws_availability_zones" "available" {
+ state = "available"
+}
+
+locals {
+ vpc_network_prefix = "10.10"
+}
+
+module "this_vpc" {
+ source = "terraform-aws-modules/vpc/aws"
+ version = "3.14.0"
+
+ name = "private-sentries-vpc"
+ cidr = "${local.vpc_network_prefix}.0.0/16"
+
+ azs = [data.aws_availability_zones.available.names[0]]
+
+ public_subnets = ["${local.vpc_network_prefix}.1.0/24"]
+
+ enable_nat_gateway = true
+ enable_dns_hostnames = true
+}
diff --git a/deployment/terraform/aws/private-sentries/vpc_peering.tf b/deployment/terraform/aws/private-sentries/vpc_peering.tf
new file mode 100644
index 000000000..f8aa45dcc
--- /dev/null
+++ b/deployment/terraform/aws/private-sentries/vpc_peering.tf
@@ -0,0 +1,21 @@
+module "this_vpc_peering" {
+ source = "grem11n/vpc-peering/aws"
+ version = "4.1.0"
+
+ providers = {
+ aws.this = aws
+ aws.peer = aws.peer
+ }
+
+ this_vpc_id = module.this_vpc.vpc_id
+ peer_vpc_id = var.peer_vpc.vpc_id
+
+ this_rts_ids = [element(module.this_vpc.public_route_table_ids, 0)]
+ peer_rts_ids = [element(var.peer_vpc.public_route_table_ids, 0)]
+
+ auto_accept_peering = true
+
+ tags = {
+ Name = "Private Sentries to Validator VPC peering"
+ }
+}
\ No newline at end of file
diff --git a/deployment/terraform/aws/public-sentries/main.tf b/deployment/terraform/aws/public-sentries/main.tf
new file mode 100644
index 000000000..ea06eba57
--- /dev/null
+++ b/deployment/terraform/aws/public-sentries/main.tf
@@ -0,0 +1,92 @@
+data "aws_ami" "ubuntu" {
+ most_recent = true
+ owners = ["099720109477"]
+
+ filter {
+ name = "name"
+ values = ["ubuntu-minimal/images/hvm-ssd/ubuntu-focal-20.04-amd64-minimal-*"]
+ }
+
+ filter {
+ name = "virtualization-type"
+ values = ["hvm"]
+ }
+}
+
+resource "aws_key_pair" "key_pair" {
+ public_key = file(var.ssh_public_key_path)
+}
+
+resource "aws_instance" "this_nodes" {
+ count = var.nodes_count
+
+ ami = data.aws_ami.ubuntu.id
+ instance_type = "t3.medium"
+
+ subnet_id = element(module.this_vpc.public_subnets, 0)
+ ipv6_address_count = var.enable_ipv6 ? 1 : 0
+
+ vpc_security_group_ids = [
+ module.this_dev_sg.security_group_id,
+ module.this_public_sg.security_group_id
+ ]
+
+ key_name = aws_key_pair.key_pair.id
+ monitoring = true
+
+ tags = {
+ Name = "Public Sentry Node ${count.index}"
+ }
+
+ root_block_device {
+ encrypted = true
+ volume_size = 30
+ }
+}
+
+resource "aws_instance" "this_seed_node" {
+ ami = data.aws_ami.ubuntu.id
+ instance_type = "t3.medium"
+
+ subnet_id = element(module.this_vpc.public_subnets, 0)
+ ipv6_address_count = var.enable_ipv6 ? 1 : 0
+
+ vpc_security_group_ids = [
+ module.this_dev_sg.security_group_id,
+ module.this_seed_sg.security_group_id
+ ]
+
+ key_name = aws_key_pair.key_pair.id
+ monitoring = true
+
+ tags = {
+ Name = "Public Sentries' Seed Node"
+ }
+
+ root_block_device {
+ encrypted = true
+ volume_size = 30
+ }
+}
+
+resource "aws_eip" "this_nodes_eips" {
+ count = var.enable_ipv6 ? 0 : length(aws_instance.this_nodes)
+
+ instance = aws_instance.this_nodes[count.index].id
+ vpc = true
+
+ tags = {
+ Name = "Public Sentry Node [${count.index}] Elastic IP"
+ }
+}
+
+resource "aws_eip" "this_seed_eip" {
+ count = var.enable_ipv6 ? 0 : 1
+
+ instance = aws_instance.this_seed_node.id
+ vpc = true
+
+ tags = {
+ Name = "Public Sentries' Seed Node Elastic IP"
+ }
+}
\ No newline at end of file
diff --git a/deployment/terraform/aws/public-sentries/outputs.tf b/deployment/terraform/aws/public-sentries/outputs.tf
new file mode 100644
index 000000000..e69de29bb
diff --git a/deployment/terraform/aws/public-sentries/provider.tf b/deployment/terraform/aws/public-sentries/provider.tf
new file mode 100644
index 000000000..9abe0ebfd
--- /dev/null
+++ b/deployment/terraform/aws/public-sentries/provider.tf
@@ -0,0 +1,9 @@
+terraform {
+ required_providers {
+ aws = {
+ source = "hashicorp/aws"
+ version = ">= 3.72"
+ configuration_aliases = [aws, aws.peer]
+ }
+ }
+}
\ No newline at end of file
diff --git a/deployment/terraform/aws/public-sentries/security.tf b/deployment/terraform/aws/public-sentries/security.tf
new file mode 100644
index 000000000..aca46045d
--- /dev/null
+++ b/deployment/terraform/aws/public-sentries/security.tf
@@ -0,0 +1,80 @@
+module "this_dev_sg" {
+ source = "terraform-aws-modules/security-group/aws"
+ version = "~> 4.0"
+
+ name = "public-sentry-dev-security-group"
+ description = "Public Sentry nodes security group for development"
+ vpc_id = module.this_vpc.vpc_id
+
+ ingress_cidr_blocks = ["0.0.0.0/0"]
+ ingress_ipv6_cidr_blocks = ["::/0"]
+ ingress_rules = ["all-icmp", "ssh-tcp"]
+ egress_rules = ["all-all"]
+}
+
+module "this_public_sg" {
+ source = "terraform-aws-modules/security-group/aws"
+ version = "~> 4.0"
+
+ name = "public-sentry-public-security-group"
+ description = "Public Sentry nodes security group for external connections"
+ vpc_id = module.this_vpc.vpc_id
+
+ egress_rules = ["all-all"]
+ ingress_with_cidr_blocks = [
+ {
+ from_port = 26656
+ to_port = 26656
+ protocol = "tcp"
+ description = "Allow p2p from all external IPs"
+ cidr_blocks = "0.0.0.0/0"
+ },
+ {
+ from_port = 26657
+ to_port = 26657
+ protocol = "tcp"
+ description = "Allow RPC from all external IPs"
+ cidr_blocks = "0.0.0.0/0"
+ },
+ ]
+
+ ingress_with_ipv6_cidr_blocks = [
+ {
+ from_port = 26656
+ to_port = 26656
+ protocol = "tcp"
+ description = "Allow p2p from all external IPs"
+ ipv6_cidr_blocks = "::/0"
+ },
+ {
+ from_port = 26657
+ to_port = 26657
+ protocol = "tcp"
+ description = "Allow RPC from all external IPs"
+ ipv6_cidr_blocks = "::/0"
+ },
+ ]
+}
+
+module "this_seed_sg" {
+ source = "terraform-aws-modules/security-group/aws"
+ version = "~> 4.0"
+
+ name = "public-sentries-seed-security-group"
+ description = "Public Sentries Seed node security group for external connections"
+ vpc_id = module.this_vpc.vpc_id
+
+ # ingress_cidr_blocks = ["10.0.0.0/8"]
+ egress_rules = ["all-all"]
+
+
+ ingress_with_cidr_blocks = [
+ {
+ from_port = 26656
+ to_port = 26656
+ protocol = "tcp"
+ description = "Allow P2P from all"
+ cidr_blocks = "0.0.0.0/0"
+ },
+ ]
+}
\ No newline at end of file
diff --git a/deployment/terraform/aws/public-sentries/variables.tf b/deployment/terraform/aws/public-sentries/variables.tf
new file mode 100644
index 000000000..70e82e716
--- /dev/null
+++ b/deployment/terraform/aws/public-sentries/variables.tf
@@ -0,0 +1,33 @@
+variable "ssh_public_key_path" {
+ description = "SSH public key file path"
+ default = "~/.ssh/id_rsa.pub"
+}
+
+variable "ssh_private_key_path" {
+ description = "SSH private key file path"
+ default = "~/.ssh/id_rsa"
+}
+
+variable "ssh_username" {
+ description = "SSH username"
+ default = "ubuntu"
+}
+
+variable "nodes_count" {
+ description = "Number of Public Sentry nodes"
+ default = 2
+}
+
+variable "region_index" {
+ description = "Public Sentries Region Index"
+ default = 0
+}
+
+variable "enable_ipv6" {
+ description = "Enable public IPv6 addresses"
+ default = true
+}
+
+variable "peer_vpc" {
+ description = "Peer VPC"
+}
\ No newline at end of file
diff --git a/deployment/terraform/aws/public-sentries/vpc.tf b/deployment/terraform/aws/public-sentries/vpc.tf
new file mode 100644
index 000000000..4db3769bc
--- /dev/null
+++ b/deployment/terraform/aws/public-sentries/vpc.tf
@@ -0,0 +1,26 @@
+data "aws_availability_zones" "available" {
+ state = "available"
+}
+
+locals {
+ vpc_network_prefix = "10.${20 + var.region_index}"
+}
+
+module "this_vpc" {
+ source = "terraform-aws-modules/vpc/aws"
+ version = "3.14.0"
+
+ name = "public-sentries-vpc"
+ cidr = "${local.vpc_network_prefix}.0.0/16"
+
+ enable_ipv6 = var.enable_ipv6
+ public_subnet_assign_ipv6_address_on_creation = var.enable_ipv6
+ public_subnet_ipv6_prefixes = var.enable_ipv6 ? [1] : []
+
+ azs = [data.aws_availability_zones.available.names[0]]
+
+ public_subnets = ["${local.vpc_network_prefix}.1.0/24"]
+
+ enable_nat_gateway = true
+ enable_dns_hostnames = true
+}
diff --git a/deployment/terraform/aws/public-sentries/vpc_peering.tf b/deployment/terraform/aws/public-sentries/vpc_peering.tf
new file mode 100644
index 000000000..7b6d904f1
--- /dev/null
+++ b/deployment/terraform/aws/public-sentries/vpc_peering.tf
@@ -0,0 +1,21 @@
+module "this_vpc_peering" {
+ source = "grem11n/vpc-peering/aws"
+ version = "4.1.0"
+
+ providers = {
+ aws.this = aws
+ aws.peer = aws.peer
+ }
+
+ this_vpc_id = module.this_vpc.vpc_id
+ peer_vpc_id = var.peer_vpc.vpc_id
+
+ this_rts_ids = [element(module.this_vpc.public_route_table_ids, 0)]
+ peer_rts_ids = [element(var.peer_vpc.public_route_table_ids, 0)]
+
+ auto_accept_peering = true
+
+ tags = {
+ Name = "Public Sentries to Private Sentries VPC peering"
+ }
+}
\ No newline at end of file
diff --git a/deployment/terraform/aws/validator/main.tf b/deployment/terraform/aws/validator/main.tf
new file mode 100644
index 000000000..71252462d
--- /dev/null
+++ b/deployment/terraform/aws/validator/main.tf
@@ -0,0 +1,41 @@
+data "aws_ami" "ubuntu" {
+ most_recent = true
+ owners = ["099720109477"]
+
+ filter {
+ name = "name"
+ values = ["ubuntu-minimal/images/hvm-ssd/ubuntu-focal-20.04-amd64-minimal-*"]
+ }
+
+ filter {
+ name = "virtualization-type"
+ values = ["hvm"]
+ }
+}
+
+resource "aws_key_pair" "key_pair" {
+ public_key = file(var.ssh_public_key_path)
+}
+
+resource "aws_instance" "this_node" {
+ ami = data.aws_ami.ubuntu.id
+ instance_type = "t3.medium"
+
+ subnet_id = element(module.this_vpc.public_subnets, 0)
+ vpc_security_group_ids = [
+ module.this_dev_sg.security_group_id,
+ module.this_private_sg.security_group_id
+ ]
+
+ key_name = aws_key_pair.key_pair.id
+ monitoring = true
+
+ tags = {
+ Name = "Validator Node"
+ }
+
+ root_block_device {
+ encrypted = true
+ volume_size = 30
+ }
+}
\ No newline at end of file
diff --git a/deployment/terraform/aws/validator/outputs.tf b/deployment/terraform/aws/validator/outputs.tf
new file mode 100644
index 000000000..12bcae675
--- /dev/null
+++ b/deployment/terraform/aws/validator/outputs.tf
@@ -0,0 +1,3 @@
+output "vpc" {
+ value = module.this_vpc
+}
\ No newline at end of file
diff --git a/deployment/terraform/aws/validator/provider.tf b/deployment/terraform/aws/validator/provider.tf
new file mode 100644
index 000000000..95016b08a
--- /dev/null
+++ b/deployment/terraform/aws/validator/provider.tf
@@ -0,0 +1,8 @@
+terraform {
+ required_providers {
+ aws = {
+ source = "hashicorp/aws"
+ version = ">= 3.72"
+ }
+ }
+}
\ No newline at end of file
diff --git a/deployment/terraform/aws/validator/security.tf b/deployment/terraform/aws/validator/security.tf
new file mode 100644
index 000000000..fd5eac6bc
--- /dev/null
+++ b/deployment/terraform/aws/validator/security.tf
@@ -0,0 +1,38 @@
+module "this_dev_sg" {
+ source = "terraform-aws-modules/security-group/aws"
+ version = "~> 4.0"
+
+ name = "validator-dev-security-group"
+ description = "Validator security group for development"
+ vpc_id = module.this_vpc.vpc_id
+
+ ingress_cidr_blocks = ["0.0.0.0/0"]
+ ingress_rules = ["all-icmp", "ssh-tcp"]
+ egress_rules = ["all-all"]
+}
+module "this_private_sg" {
+ source = "terraform-aws-modules/security-group/aws"
+ version = "~> 4.0"
+
+ name = "validator-private-security-group"
+ description = "Validator node security group for internal connections"
+ vpc_id = module.this_vpc.vpc_id
+
+ egress_rules = ["all-all"]
+ ingress_with_cidr_blocks = [
+ {
+ from_port = 26656
+ to_port = 26656
+ protocol = "tcp"
+ description = "Allow p2p from internal IPs"
+ cidr_blocks = "10.0.0.0/8"
+ },
+ {
+ from_port = 26657
+ to_port = 26657
+ protocol = "tcp"
+ description = "Allow RPC from internal IPs"
+ cidr_blocks = "10.0.0.0/8"
+ },
+ ]
+}
\ No newline at end of file
diff --git a/deployment/terraform/aws/validator/variables.tf b/deployment/terraform/aws/validator/variables.tf
new file mode 100644
index 000000000..552f80a43
--- /dev/null
+++ b/deployment/terraform/aws/validator/variables.tf
@@ -0,0 +1,14 @@
+variable "ssh_public_key_path" {
+ description = "SSH public key file path"
+ default = "~/.ssh/id_rsa.pub"
+}
+
+variable "ssh_private_key_path" {
+ description = "SSH private key file path"
+ default = "~/.ssh/id_rsa"
+}
+
+variable "ssh_username" {
+ description = "SSH username"
+ default = "ubuntu"
+}
\ No newline at end of file
diff --git a/deployment/terraform/aws/validator/vpc.tf b/deployment/terraform/aws/validator/vpc.tf
new file mode 100644
index 000000000..628cc1fdf
--- /dev/null
+++ b/deployment/terraform/aws/validator/vpc.tf
@@ -0,0 +1,22 @@
+data "aws_availability_zones" "available" {
+ state = "available"
+}
+
+locals {
+ vpc_network_prefix = "10.0"
+}
+
+module "this_vpc" {
+ source = "terraform-aws-modules/vpc/aws"
+ version = "3.14.0"
+
+ name = "validator-vpc"
+ cidr = "${local.vpc_network_prefix}.0.0/16"
+
+ azs = [data.aws_availability_zones.available.names[0]]
+
+ public_subnets = ["${local.vpc_network_prefix}.1.0/24"]
+
+ enable_nat_gateway = true
+ enable_dns_hostnames = true
+}
\ No newline at end of file
diff --git a/deployment/terraform/aws/variables.tf b/deployment/terraform/aws/variables.tf
new file mode 100644
index 000000000..9d43acb89
--- /dev/null
+++ b/deployment/terraform/aws/variables.tf
@@ -0,0 +1,19 @@
+variable "region_1" {
+ description = "AWS Region 1"
+ default = "us-west-1"
+}
+
+variable "region_2" {
+ description = "AWS Region 2"
+ default = "us-east-2"
+}
+
+variable "root_domain_name" {
+ description = "Root domain name for dcl observer endpoints"
+ default = ""
+}
+
+variable "enable_tls" {
+ description = "Enable tls for observer endpoints"
+ default = false
+}
\ No newline at end of file
diff --git a/docs/deployment-aws.png b/docs/deployment-aws.png
index 102869644..1dcd8e954 100644
Binary files a/docs/deployment-aws.png and b/docs/deployment-aws.png differ
diff --git a/docs/deployment-design-aws.md b/docs/deployment-design-aws.md
index b5c0f70bc..de5d85344 100644
--- a/docs/deployment-design-aws.md
+++ b/docs/deployment-design-aws.md
@@ -29,28 +29,32 @@
- Tendermint:
-`config.toml` file:
+ `config.toml` file:
-```toml
-[p2p]
-pex = false
-persistent_peers = # `Private Sentry` nodes with private IPs
-addr_book_strict = false
+ ```toml
+ [p2p]
+ pex = false
+ persistent_peers = # `Private Sentry` nodes with private IPs
+ addr_book_strict = false
-[statesync] # only for `Non-genesis Validator` nodes
-enable = true
-rpc_servers = # existing `Genesis Validator` / `Sentry` nodes' RPC endpoints
-trust_height = "trust-height"
-trust_hash = "trust-hash"
-```
+ [statesync] # only for `Non-genesis Validator` nodes
+ enable = true
+ rpc_servers = # existing `Genesis Validator` / `Sentry` nodes' RPC endpoints
+ trust_height = "trust-height"
+ trust_hash = "trust-hash"
-`app.toml` file:
+ [consensus]
+ create_empty_blocks = false
+ create_empty_blocks_interval = "600s" # 10 mins
+ ```
-```toml
-[state-sync]
-snapshot-interval = "snapshot-interval"
-snapshot-keep-recent = "snapshot-keep-recent"
-```
+ `app.toml` file:
+
+ ```toml
+ [state-sync]
+ snapshot-interval = "snapshot-interval"
+ snapshot-keep-recent = "snapshot-keep-recent"
+ ```
- AWS:
- Instance type = EC2 instance
@@ -68,30 +72,30 @@ snapshot-keep-recent = "snapshot-keep-recent"
- Tendermint:
-`config.toml` file:
+ `config.toml` file:
-```toml
-[p2p]
-pex = true
-persistent_peers = # `Validator` node with private IP + other orgs' validator/sentry nodes with public IPs
-private_peer_ids = # `Validator` node id
-unconditional_peers = # `Validator` node id
-addr_book_strict = false
+ ```toml
+ [p2p]
+ pex = true
+ persistent_peers = # `Validator` node with private IP + other orgs' validator/sentry nodes with public IPs
+ private_peer_ids = # `Validator` node id
+ unconditional_peers = # `Validator` node id
+ addr_book_strict = false
-[statesync]
-enable = true
-rpc_servers = # `Validator` node's RPC endpoint
-trust_height = "trust-height"
-trust_hash = "trust-hash"
-```
+ [statesync]
+ enable = true
+ rpc_servers = # `Validator` node's RPC endpoint
+ trust_height = "trust-height"
+ trust_hash = "trust-hash"
+ ```
-`app.toml` file:
+ `app.toml` file:
-```toml
-[state-sync]
-snapshot-interval = "snapshot-interval"
-snapshot-keep-recent = "snapshot-keep-recent"
-```
+ ```toml
+ [state-sync]
+ snapshot-interval = "snapshot-interval"
+ snapshot-keep-recent = "snapshot-keep-recent"
+ ```
- AWS:
- Instance type = EC2 instance
@@ -110,27 +114,27 @@ snapshot-keep-recent = "snapshot-keep-recent"
- Tendermint:
-`config.toml` file:
+ `config.toml` file:
-```toml
-[p2p]
-pex = true
-persistent_peers = # `Private Sentry` nodes with private IPs
-addr_book_strict = false
+ ```toml
+ [p2p]
+ pex = true
+ persistent_peers = # `Private Sentry` nodes with private IPs
+ addr_book_strict = false
-[statesync]
-enable = true
-rpc_servers = # `Private Sentry` nodes' RPC endpoints
-trust_height = "trust-height"
-trust_hash = "trust-hash"
-```
+ [statesync]
+ enable = true
+ rpc_servers = # `Private Sentry` nodes' RPC endpoints
+ trust_height = "trust-height"
+ trust_hash = "trust-hash"
+ ```
-`app.toml` file:
+ `app.toml` file:
-```toml
-[api]
-enable = true
-```
+ ```toml
+ [api]
+ enable = true
+ ```
- AWS:
- Instance type = EC2 instance
@@ -147,27 +151,27 @@ enable = true
- Tendermint:
-`config.toml` file:
+ `config.toml` file:
-```toml
-[p2p]
-pex = true
-persistent_peers = # `Private Sentry` nodes with private IPs
+ ```toml
+ [p2p]
+ pex = true
+ persistent_peers = # `Private Sentry` nodes with private IPs
-[statesync]
-enable = true
-rpc_servers = # `Private Sentry` nodes' RPC endpoints
-trust_height = "trust-height"
-trust_hash = "trust-hash"
-```
+ [statesync]
+ enable = true
+ rpc_servers = # `Private Sentry` nodes' RPC endpoints
+ trust_height = "trust-height"
+ trust_hash = "trust-hash"
+ ```
-`app.toml` file:
+ `app.toml` file:
-```toml
-[state-sync]
-snapshot-interval = "snapshot-interval"
-snapshot-keep-recent = "snapshot-keep-recent"
-```
+ ```toml
+ [state-sync]
+ snapshot-interval = "snapshot-interval"
+ snapshot-keep-recent = "snapshot-keep-recent"
+ ```
- AWS:
- Instance type = EC2 instance
@@ -185,20 +189,20 @@ snapshot-keep-recent = "snapshot-keep-recent"
- Tendermint:
-`config.toml` file:
+ `config.toml` file:
-```toml
-[p2p]
-pex = true
-seed_mode = true
-persistent_peers = # `Public Sentry` nodes with public IP
+ ```toml
+ [p2p]
+ pex = true
+ seed_mode = true
+ persistent_peers = # `Public Sentry` nodes with public IP
-[statesync]
-enable = true
-rpc_servers = # `Private Sentry` nodes' RPC endpoints
-trust_height = "trust-height"
-trust_hash = "trust-hash"
-```
+ [statesync]
+ enable = true
+ rpc_servers = # `Private Sentry` nodes' RPC endpoints
+ trust_height = "trust-height"
+ trust_hash = "trust-hash"
+ ```
- AWS:
- Instance type = EC2 instance
diff --git a/docs/design/deployment-aws.drawio b/docs/design/deployment-aws.drawio
index a39809421..06432b2f9 100644
--- a/docs/design/deployment-aws.drawio
+++ b/docs/design/deployment-aws.drawio
@@ -1 +1 @@
-7V1bc6M4Fv41qd19SEoS90fnNrtbPT2pZGe6al9c2FZsprHxAM5lf/1KgDC6YDsON8eqTlUbGQvQ+c5Fn44OF8bN8u2X2F8vfo1mOLxAYPZ2YdxeIGQA1yD/0Zb3vAVC18pb5nEwK9q2DU/B/3DRCIrWTTDDCXdiGkVhGqz5xmm0WuFpyrX5cRy98qc9RyF/1bU/x1LD09QP5dYfwSxdsMewve0X/8TBfFFc2kVO/sXSZycXT5Is/Fn0Wmky7i6MmziK0vzT8u0Gh3T02Ljkv7uv+ba8sRiv0kN+8NePxPnl33+Oxw+T5PffJ+Dlr1dwCYu7ffHDTfHEox9PpOEmjDaz4sbTdzYa6yhYpdmIWtfkj1zwBlxY5JsbenSFLKFBPHb4Bigf0T74BvHY4Rug2D0Urg/FG6w0SEdc90C4PqjcIPkzrqNNGgYrfFNiD5DGeezPAiKTmyiMYtK2ilZk9K4X6TIkR5B8fF0EKX5a+1M6qq9EcUjbc7RKC/RDxI6Lgae9EnynPrlWXBxnksDx3QvOBZKfE4b+Ogkm5a9iPN3ESfCCH3GSd05bCRLX9PPybU619sp/TcyreRxt1tnt/4tcS/ntmHwcTykwxn6Y0o7SOPqJ2YNeIIP8u6fou34OwlAYgBccpwFRrFEYzGn/aUQv5xdHIX7OeiSjEqzm37KjWwMUI6G6xMxPFnhWPFKBYnIJ/FarH7DUOmKvcLTEafxOTmHGqtDowlKh4vC1ovXAKXpdVDQeWqzVL2zNvOx7q47kQ6GRH9FO5ErqOX98IJ0B2jECj3dP/9ke0C/sTDCTmHya0083IcWipMgMAptlOJqmdGxL+XzzJzh8iJIgDTIcTKI0jZa1AqzgWqkOOUaY7UTNyAoazD8U0nIs78qSBGYDhbjYL1uQlidJSxp4vJqNqFsiR9PQT5Jgmo2RH6dyc2VoifqtZiXa5TGt6htREjjxIUYqDQXAvhvdl1LAM8n9CTIgdx9t4ine9eCw8PLkMeY43Q9oWa4VoVkKobG2GId+SswZ7+YVgiyu8ECtZAU20OBh40KL7yN/1uJnVWcq9iQCUOopHwuppwxZ5YN/AmymDLbb70/ZGCVRuMmUF4GJnxDUIJAdrOPoLVgG6buMSgKDTO951DHjPMXU1yhMwDKYzWgfxNEQ/+JvHQ8fKNzu0voicit+vI2XqkjcpW+1RgJcQdf1GgEOuRYnbTL8fBfR83OC2xE080uCuFhwEMXpIppHKz+827YK9mJ7zreIGu1MuH/iNH0vQg5/k0a86GUTU29KasxX1nwfhKzLOhvVpCUybDUkPil/ZPLaDk1X8CKtq7scCTxsJiEZaHIP0ylOki+i1MZupb4kAbjN5ljHSrUPLYaS/H5LF2T8Efgtnv8t0VOuQU+5YO9Trq823TJtizeptgOkAL60u9VgsGxsPoLP3QevpZMExy+Zon6PKBUlTaV+4nS6YJ5WBc+6Ia2BreAnb02iBo4k/uJkTixHTuEkj1BRnH1K4ifr/EGfgzd6H5KWwDr0BysSIKymlNw7DE+7DGstzDzjiseZJ6OM+dYqyFhb8xgzkfYE2hNoT7AN6UqdZGQO7N8TmIakpU/kebL7LvwA+Hu0pgbWD/+hncKwnEJuY+udgi3M5nr3CaaEtj+IAGY+pWZzwGmINQyxg6no4yDGmzSrd4RZEsJkwqATbhpbRN+AhCvyzTUCAGydSjOMUJ2cumGcLyESgCASRwczzs6ejmoYKCI6/71yWhFF7rjjmgtt4Zd32TC/Jc+87oMYv/rZb7OgLQySlIQoF8j2l9R8rCbJugTLyfNeuYLu4r3YxKGQi9EIQJENuV4vHb6HFikxS6bEejJJ3S6XWQXUh75a5nouDzjPvfKOXi9zhRjfOcx8NYc2edo9AAI9jlK/CJZ2zqaOtyvW7slXg4tkYgKFAJU2LYk8WTsLSwLBiZgST9B+z/SuPM8CyHYMx7OFqPdgo2I6vEuEBjSvDA84pmvbBgRdr8lbchAzABvThlEx9hgVy+LDCtQIjC4NfuJuoK5MDHuAimQf8TzPsRhJQtVM7RCY2t7SJOMcGQonQCzW3fWoVZq2vETJ0MBmaFqHd+/ssOJAXJUHscV5amOcBos3dnr9LjJlDsp+adLtmwd6fVRjpg82w5/knCT5/EFTVLWxHKCx7G1Z62U9VS5oma5LANSmpRyNrp1rt4UFLSjMhKDlSrYSAdV6FmjNVioi0zh48VNMlXEzWWE5R1wr5lkrZkK7C9L38fbkp0xLubnwvuCGtN/Z9+jebTPCOVhvd/ip+kQlfuqqWCssOX5unwFqS5dlVdZrhYNeK6xLSmYAQ0KK0rahAjLDkjFmWC1BzJCzjc8ktHZPIrRW5Ato+fAjVBOidSMfy9Ti4Afks+I4ai3bBHwgbvFbpFtaygZaF/kTvZq1h3aFbwiZF26xPbNl4Vta+MKIfNZTHiV9JKw4QWR0oftIG35xREAv4hdmbSzdoG4pcc/5LaFFjrI1Qap5mPMjSMvdtD0SpHIhnHLpXvOjWi8b4EeVGkv5Ue/euLObU9vyOk3xozXhO4uzBfJKxY8quKv2+FHWsXKtQ9zEo4nSAe3byY1wPVHK5xSxNa2+9lQgOeswC9/AGuM4S1TvGFzmLXJGo68HLjaejcQeCHgC3W64roJvtzwZSqyteT4XSVA6j3mkcWgqS798rqFTWXREeI4zNdMZ3EyNRQHa7Z6S2xX3/5QJ4lWXq4jerLaiN8WG2NGLH4T+JAizEnngv1SACMhmXqHH9ckwXBquWryiyOryXZrQZ0vQZ1ZGcG+pBbst31oW5PzqsY556GYd67NF7D6nGDs2sWgmTMc958GE7TajFrSFSSRLLeiR9zJlClsXLxs032XuSQwcFt/Fdtl+eT99WklNRhdJTYrys5oA0YHA+REgA9jLo6j8rgN0rZdnFqDvcFP1JJQj7rToPWhnW6Z10H4yQfvuAvVDC9o1W/4F2HJDUbW6U7Ycwl4Smxuc1R1edQ32krAOARLmdV4H+xUUFYu+4/Q1in+Sxm+RPyP/EYWiVjPWpqIhU7HKR3gckvEdT9joNmI4XGHTi2HLhsNRGA6nLcPhypOVsnCSXLpTz1POep5yFoWTXEUKhbpyEvth894cnPg2pZ2mZm8owIKpoe5ds4Awh7A6YHg9eSKqGV5tob8Cw7vDWtRP4wEfSJmqd5J0y/tC9hLKM7Xa6GCr3Wv+DLtPTc9ro6rp+Q/ZXJmfV7w3BaKyPBJH0Rtt2V1P3uejKfpBU/S5CT4Vit6TKXp1JrLMlww6E/kY0Vxaogm4VO046DZD2dO7f7QX11OjuqmR23tGDHsrjQ65tbLqkFvhu04pI8bT7+A+tXB796vrBhZuF6S+TolpHV0fTIk5JhYxxKUS1nFviTJAZ1ScWEbFMbhzRKMGZNx1mmcBIZTQdE6LA0WIMvjFAXmPnprrkV8qdnpczz7bLZYEkFVITfSIrw5tTolYpDtIJeJfPtmJWkHoHKpX/dR5hcLri4Uqvx89v6U6r1DWek0gak7iXAlE9irmMrVCrr6GoKL8GhLf59pg9CTvb9UMotZWzSCW3qtWm5FYTxGVnGKVRLQVkVzZ2IJC79gkq2vADphMhHvKDVsODzbFm7JMGWmsrYUpg8z3PGE8u2BvYrNDqraTmHyap+XIaLg1BjfUKtxsU7BurgJwUAG41sqlKcpba/r6ROlryN5gz6pL9L3NEx3KT51YVcSj8hwEiteRhYMM1TSltTeeezVVeLTqn9Jmbhf0reXsBgZJc17sJzUP3fPtHVpdvJ831FkiMLp5Q513HsJnZZIGXm7VOrQO8Yll/36sDjFUkgadVyKWM0Meideko68ofqid63HONaZDOraMcYyTKHxpqvSB5/HW1HEsBaQ6XpTvZT2xQSNaprN0UDblc0Xx5Fnxl1hY3435kub8uBm1jpilkMM4itJqQELV+tdohukZ/wc=
\ No newline at end of file
+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
\ No newline at end of file