diff options
| author | Paul Buetow <paul@buetow.org> | 2023-12-31 23:46:41 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2023-12-31 23:46:41 +0200 |
| commit | 86e3ca1ac57ebd3544dd84d9cb4b1cf3916df6ba (patch) | |
| tree | 780b6c3e30d28542e5f08da93c3e81a84def298d | |
| parent | 41ae28fd70083ab347aa613bd78a5ad3fbc8c612 (diff) | |
initial radicale server
| -rw-r--r-- | org-buetow-base/ecr.tf | 33 | ||||
| -rw-r--r-- | org-buetow-base/outputs.tf | 4 | ||||
| -rw-r--r-- | org-buetow-bastion/user_data.tpl | 12 | ||||
| -rw-r--r-- | org-buetow-ecs/ecs.tf | 7 | ||||
| -rw-r--r-- | org-buetow-ecs/radicaleservice.tf | 156 |
5 files changed, 201 insertions, 11 deletions
diff --git a/org-buetow-base/ecr.tf b/org-buetow-base/ecr.tf new file mode 100644 index 0000000..1f3794c --- /dev/null +++ b/org-buetow-base/ecr.tf @@ -0,0 +1,33 @@ +# Radicale Docker image from https://codeberg.org/snonux/docker-radicale-server +resource "aws_ecr_repository" "readicale" { + name = "radicale" + + tags = { + Name = "radicale" + } +} + +resource "aws_iam_policy" "ecr_radicale_read" { + name = "ecr-radicale-read" + description = "Allow ECS tasks to pull from ECR" + + policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Effect = "Allow", + Action = [ + "ecr:GetDownloadUrlForLayer", + "ecr:BatchGetImage", + "ecr:BatchCheckLayerAvailability" + ], + Resource = "arn:aws:ecr:eu-central-1:634617747016:repository/radicale" + }, + { + Effect = "Allow", + Action = "ecr:GetAuthorizationToken", + Resource = "*" + } + ] + }) +} diff --git a/org-buetow-base/outputs.tf b/org-buetow-base/outputs.tf index 5f585fe..7eed919 100644 --- a/org-buetow-base/outputs.tf +++ b/org-buetow-base/outputs.tf @@ -42,3 +42,7 @@ output "zone_certificate_arn" { # For buetow.cloud and *.buetow.cloud value = "arn:aws:acm:eu-central-1:634617747016:certificate/fbf5627c-9a4c-4c62-9c33-038e140f3f12" } + +output "ecr_radicale_read_arn" { + value = aws_iam_policy.ecr_radicale_read.arn +} diff --git a/org-buetow-bastion/user_data.tpl b/org-buetow-bastion/user_data.tpl index 63c81ec..bad9cbf 100644 --- a/org-buetow-bastion/user_data.tpl +++ b/org-buetow-bastion/user_data.tpl @@ -1,16 +1,8 @@ #!/bin/bash -# Docker sudo yum update -y -sudo install postgresql15 -y # PostgreSQL client programs -sudo amazon-linux-extras install docker -y -sudo service docker enabl -sudo service docker start -sudo usermod -a -G docker ec2-user - -# Docker Compose -sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose -sudo chmod +x /usr/local/bin/docker-compose +sudo yum install -y postgresql15 httpd-tools +#sudo amazon-linux-extras install docker -y # EFS yum install -y amazon-efs-utils diff --git a/org-buetow-ecs/ecs.tf b/org-buetow-ecs/ecs.tf index 63ddde5..a46389c 100644 --- a/org-buetow-ecs/ecs.tf +++ b/org-buetow-ecs/ecs.tf @@ -25,7 +25,12 @@ resource "aws_iam_role" "ecs_execution_role" { } } -resource "aws_iam_role_policy_attachment" "ecs_execution_role_policy_attach" { +resource "aws_iam_role_policy_attachment" "ecs_execution_role_policy_attach1" { role = aws_iam_role.ecs_execution_role.name policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy" } + +resource "aws_iam_role_policy_attachment" "ecs_execution_role_policy_attach2" { + role = aws_iam_role.ecs_execution_role.name + policy_arn = data.terraform_remote_state.base.outputs.ecr_radicale_read_arn +} diff --git a/org-buetow-ecs/radicaleservice.tf b/org-buetow-ecs/radicaleservice.tf new file mode 100644 index 0000000..6a003df --- /dev/null +++ b/org-buetow-ecs/radicaleservice.tf @@ -0,0 +1,156 @@ +resource "aws_route53_record" "a_record_radicale" { + zone_id = data.terraform_remote_state.base.outputs.zone_id + name = "radicale.${data.terraform_remote_state.base.outputs.zone_name}." + type = "A" + + alias { + name = data.terraform_remote_state.elb.outputs.alb_dns_name + zone_id = data.terraform_remote_state.elb.outputs.alb_zone_id + evaluate_target_health = true + } +} + +resource "aws_route53_record" "aaaa_record_radicale" { + zone_id = data.terraform_remote_state.base.outputs.zone_id + name = "radicale.${data.terraform_remote_state.base.outputs.zone_name}." + type = "AAAA" + + alias { + name = data.terraform_remote_state.elb.outputs.alb_dns_name + zone_id = data.terraform_remote_state.elb.outputs.alb_zone_id + evaluate_target_health = true + } +} + +resource "aws_ecs_task_definition" "radicale" { + family = "radicale" + network_mode = "awsvpc" + requires_compatibilities = ["FARGATE"] + cpu = "256" + memory = "512" + execution_role_arn = aws_iam_role.ecs_execution_role.arn + + tags = { + Name = "radicale" + } + + volume { + name = "radicale-collections-efs-volume" + efs_volume_configuration { + file_system_id = data.terraform_remote_state.base.outputs.self_hosted_services_efs_id + root_directory = "/ecs/radicale/collections" + } + } + + volume { + name = "radicale-auth-efs-volume" + efs_volume_configuration { + file_system_id = data.terraform_remote_state.base.outputs.self_hosted_services_efs_id + root_directory = "/ecs/radicale/auth" + } + } + + container_definitions = jsonencode([{ + name = "radicale", + image = "634617747016.dkr.ecr.eu-central-1.amazonaws.com/radicale:latest", + portMappings = [{ + containerPort = 8080, + hostPort = 8080 + }], + mountPoints = [ + { + sourceVolume = "radicale-collections-efs-volume" + containerPath = "/collections" + readOnly = false + }, + { + sourceVolume = "radicale-auth-efs-volume" + containerPath = "/auth" + readOnly = true + } + ], + "logConfiguration" : { + "logDriver" : "awslogs", + "options" : { + "awslogs-group" : "/ecs/containers", + "awslogs-region" : "eu-central-1", + "awslogs-stream-prefix" : "radicale" + } + } + }]) +} + +resource "aws_ecs_service" "radicale" { + name = "radicale" + cluster = aws_ecs_cluster.ecs_cluster.id + task_definition = aws_ecs_task_definition.radicale.arn + launch_type = "FARGATE" + deployment_maximum_percent = 100 + deployment_minimum_healthy_percent = 0 + desired_count = 1 + + tags = { + Name = "radicale" + } + + load_balancer { + target_group_arn = aws_lb_target_group.radicale_tg.arn + container_name = "radicale" # Must match the name in your container definition + container_port = 8080 # The port your container is listening on + } + + network_configuration { + subnets = [ + data.terraform_remote_state.base.outputs.public_subnet_a_id, + data.terraform_remote_state.base.outputs.public_subnet_b_id, + data.terraform_remote_state.base.outputs.public_subnet_c_id, + ] + security_groups = [data.terraform_remote_state.base.outputs.allow_web_sg_id] + assign_public_ip = true + } +} + +resource "aws_lb_target_group" "radicale_tg" { + name = "radicale-tg" + port = 8080 + protocol = "HTTP" + vpc_id = data.terraform_remote_state.base.outputs.vpc_id + target_type = "ip" + + health_check { + enabled = true + healthy_threshold = 2 + unhealthy_threshold = 2 + interval = 30 + path = "/.web/" + protocol = "HTTP" + timeout = 3 + matcher = "200-299" + } + + tags = { + Name = "radicale" + } +} + +resource "aws_lb_listener_rule" "radicale_https_listener_rule" { + listener_arn = data.terraform_remote_state.elb.outputs.alb_https_listener_arn + priority = 106 + + action { + type = "forward" + target_group_arn = aws_lb_target_group.radicale_tg.arn + } + + condition { + host_header { + values = ["radicale.${data.terraform_remote_state.base.outputs.zone_name}"] + } + } + + tags = { + Name = "radicale" + } +} + + |
