Skip to content
Open
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ hashicorp/
*.tfstate
*.tfvars
*.tfstate.backup

.DS_Store
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,12 @@ Disclaimer: Please use these modules only if you're comfortable configuring Terr
# Usage

Navigate to your desired cloud provider + deployment module for specific configuration options.

# How to deploy
1. Make sure you're on the `production` workspace.
2. Run `tf apply`

# How to upgrade
1. Check the latest version of Retool on https://docs.retool.com/changelog/tags/self-hosted
2. Change the version number in the `main.tf` file of the `ecs_retool_image` on line 23.
3. Deploy
107 changes: 107 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
data "aws_ssm_parameter" "retool_license_key" {
name = "/overwatch/${local.stage}/RETOOL_LICENSE_KEY"
}
data "aws_ssm_parameter" "magement_api_key" {
name = "/unify/${terraform.workspace == "production" ? "prod" : "staging"}/API_GATEWAY_API_KEY"
}

module "retool" {
source = "./modules/aws_ecs_fargate"

providers = {
aws = aws
aws.us_east_1 = aws.us_east_1
}

deployment_name = "overwatch"
aws_region = "eu-central-1"
vpc_id = module.platform_network.vpc_id
vpc_cidr_block = module.platform_network.vpc_cidr_block
private_subnet_ids = [for subnet in module.platform_network.main_private_subnets : subnet.id]
public_subnet_ids = [for subnet in module.platform_network.main_public_subnets : subnet.id]
# ssh_key_pair = "<your-key-pair>"
ecs_retool_image = "tryretool/backend:3.24.6"
domain_name = local.domain_name

retool_license_key = data.aws_ssm_parameter.retool_license_key.arn
log_retention_in_days = 7

management_api_key = data.aws_ssm_parameter.magement_api_key.arn

environment = local.environment
stage = local.stage
# ecs_insights_enabled = true
additional_env_vars = [{
name = "DOMAINS",
value = "overwatch.${local.domain_name}"
}, {
name = "BASE_DOMAIN",
value = "https://overwatch.${local.domain_name}"
}, {
name = "DISABLE_INTERCOM",
value = "true"
}, {
name = "DISABLE_USER_PASS_LOGIN",
value = "true"
}, {
name = "RESTRICTED_DOMAIN",
value = "apideck.com"
}, {
name = "HIDE_PROD_AND_STAGING_TOGGLES",
value = "true"
}, {
name = "DISABLE_GIT_SYNCING"
value = "true"
}, {
name = "TRIGGER_OAUTH_2_SSO_LOGIN_AUTOMATICALLY"
value = "true"
}, {
name = "CUSTOM_OAUTH2_SSO_CLIENT_ID"
value = var.client_id
}, {
name = "CUSTOM_OAUTH2_SSO_SCOPES"
value = "openid email profile https://www.googleapis.com/auth/userinfo.profile"
}, {
name = "CUSTOM_OAUTH2_SSO_AUTH_URL"
value = "https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&prompt=consent"
}, {
name = "CUSTOM_OAUTH2_SSO_TOKEN_URL"
value = "https://oauth2.googleapis.com/token"
}, {
name = "CUSTOM_OAUTH2_SSO_JWT_EMAIL_KEY"
value = "idToken.email"
}, {
name = "CUSTOM_OAUTH2_SSO_JWT_FIRST_NAME_KEY"
value = "idToken.given_name"
}, {
name = "CUSTOM_OAUTH2_SSO_JWT_LAST_NAME_KEY"
value = "idToken.family_name"
}, {
name = "CUSTOM_OAUTH2_SSO_ACCESS_TOKEN_LIFESPAN_MINUTES"
value = "45"
}, {
name = "DATABASE_MIGRATIONS_TIMEOUT_SECONDS"
value = "900"
}
]

alb_ingress_rules = [{

description = "Global HTTPS inbound"
from_port = "443"
to_port = "443"
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]

}]
}

module "platform_network" {
source = "./modules/platform_network"

prefix = local.prefix
project = local.project
environment = local.environment
stage = local.stage
}
2 changes: 2 additions & 0 deletions modules/aws_ecs/loadbalancers.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ resource "aws_lb" "this" {
name = "${var.deployment_name}-alb"
idle_timeout = var.alb_idle_timeout

drop_invalid_header_fields = true

security_groups = [aws_security_group.alb.id]
subnets = var.subnet_ids
}
Expand Down
7 changes: 3 additions & 4 deletions modules/aws_ecs_ec2/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ resource "aws_ecs_cluster" "this" {

data "aws_ami" "this" {
most_recent = true # get the latest version
name_regex = "^amzn2-ami-ecs-hvm-\\d\\.\\d\\.\\d{8}-x86_64-ebs$"
name_regex = "^amzn2-ami-ecs-hvm-\\d\\.\\d\\.\\d{8}-x86_64-ebs$"

filter {
name = "virtualization-type"
Expand Down Expand Up @@ -156,9 +156,8 @@ resource "aws_db_instance" "this" {
publicly_accessible = var.rds_publicly_accessible
vpc_security_group_ids = [aws_security_group.rds.id]
performance_insights_enabled = var.rds_performance_insights_enabled

skip_final_snapshot = true
apply_immediately = true
skip_final_snapshot = true
apply_immediately = true
}

resource "aws_ecs_service" "retool" {
Expand Down
16 changes: 8 additions & 8 deletions modules/aws_ecs_ec2/secrets.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ resource "random_string" "rds_password" {
}

resource "aws_secretsmanager_secret" "rds_password" {
name = "${var.deployment_name}-rds-password"
description = "This is the password for the Retool RDS instance"
name = "${var.deployment_name}-rds-password"
description = "This is the password for the Retool RDS instance"
recovery_window_in_days = 0
}

Expand All @@ -15,8 +15,8 @@ resource "aws_secretsmanager_secret_version" "rds_password" {
}

resource "aws_secretsmanager_secret" "rds_username" {
name = "${var.deployment_name}-rds-username"
description = "This is the username for the Retool RDS instance"
name = "${var.deployment_name}-rds-username"
description = "This is the username for the Retool RDS instance"
recovery_window_in_days = 0
}

Expand All @@ -31,8 +31,8 @@ resource "random_string" "jwt_secret" {
}

resource "aws_secretsmanager_secret" "jwt_secret" {
name = "${var.deployment_name}-jwt-secret"
description = "This is the secret for Retool JWTs"
name = "${var.deployment_name}-jwt-secret"
description = "This is the secret for Retool JWTs"
recovery_window_in_days = 0
}

Expand All @@ -48,8 +48,8 @@ resource "random_string" "encryption_key" {
}

resource "aws_secretsmanager_secret" "encryption_key" {
name = "${var.deployment_name}-encryption-key"
description = "This is the secret for encrypting credentials"
name = "${var.deployment_name}-encryption-key"
description = "This is the secret for encrypting credentials"
recovery_window_in_days = 0
}

Expand Down
113 changes: 113 additions & 0 deletions modules/aws_ecs_fargate/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# AWS ECS + EC2 Module

This module deploys an ECS cluster with autoscaling group of EC2 instances.

# Usage
1. Directly use our module in your existing Terraform configuration and provide the required variables

```
module "retool" {
source = "git@github.com:tryretool/retool-terraform.git//modules/aws/ecs-ec2"

aws_region = "<your-aws-region>"
vpc_id = "<your-vpc-id>"
subnet_ids = [
"<your-subnet-1>",
"<your-subnet-2>"
]
ssh_key_pair = "<your-key-pair>"
ecs_retool_image = "<desired-retool-version>"

# Additional configuration
...
}
```

2. Run `terraform init` to install all requirements for the module.

3. Replace `ecs_retool_image` with your desired [Retool Version](https://docs.retool.com/docs/updating-retool-on-premise#retool-release-versions). The format should be `tryretool/backend:X.Y.Z`, where `X.Y.Z` is your desired version number.

4. Ensure that the default security settings in `security.tf` matches your specifications. If you need to tighten down access, pass in custom ingress and egress rules into `ec2_egress_rules`, `ec2_ingress_rules`, `alb_egress_rules`, and `alb_ingress_rules`.

5. Check through `variables.tf` for any other input variables that may be required.

6. Run `terraform plan` to view all planned changes to your account.

7. Run `terraform apply` to apply the changes and deploy Retool.

8. You should now find a Load Balancer in your AWS EC2 Console associated with the deployment. The instance address should now be running Retool.

## Common Configuration

### Instances

**EC2 Instance Size**
To configure the EC instance size, set the `instance_type` input variable (e.g. `t2.large`).

**RDS Instance Class**
To configure the RDS instance class, set the `instance_class` input variable (e.g. `db.m4.large`).

## Advanced Configuration


### Security Groups
To customize the ingress and egress rules on the security groups, you can override specific input variable defaults.

- `ec2_ingress_rules` controls the inbound rules for EC2 instances in the autoscaling group
- `ec2_egress_rules` controls the outbound rules for EC2 instances in the autoscaling group
- `alb_ingress_rules` controls the inbound rules for the Load Balancer
- `alb_egress_rules` controls the outbound rules for the Load Balancer

```
ec2_ingress_rules = [
{
description = "Global HTTP inbound"
from_port = "80"
to_port = "80"
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
},
{
description = "Global HTTPS inbound"
from_port = "443"
to_port = "443"
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
},
{
description = "SSH inbound"
from_port = "22"
to_port = "22"
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
]

ec2_egress_rules = [
{
description = "Global outbound"
from_port = "0"
to_port = "0"
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
]
```

### Environment Variables
To add additional [Retool environment variables](https://docs.retool.com/docs/environment-variables) to your deployment, populate the `additional_env_vars` input variable into the module.

NOTE: The `additional_env_vars` will only work as type `map(string)`. Convert all booleans and numbers into strings, e.g.

```
additional_env_vars = [
{
name = "DISABLE_GIT_SYNCING"
value = "true"
}
]
```
28 changes: 28 additions & 0 deletions modules/aws_ecs_fargate/certificate.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
data "aws_route53_zone" "apideck_com" {
name = var.domain_name
private_zone = false
}

module "apideck_acm_certificate" {
source = "terraform-aws-modules/acm/aws"
version = "~> 3.0"

domain_name = "*.${var.domain_name}"
zone_id = data.aws_route53_zone.apideck_com.zone_id

wait_for_validation = true
}

module "apideck_acm_certificate_east" {
source = "terraform-aws-modules/acm/aws"
version = "~> 3.0"

providers = {
aws = aws.us_east_1
}

domain_name = "*.${var.domain_name}"
zone_id = data.aws_route53_zone.apideck_com.zone_id

wait_for_validation = true
}
Loading