summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2023-12-31 23:46:41 +0200
committerPaul Buetow <paul@buetow.org>2023-12-31 23:46:41 +0200
commit86e3ca1ac57ebd3544dd84d9cb4b1cf3916df6ba (patch)
tree780b6c3e30d28542e5f08da93c3e81a84def298d
parent41ae28fd70083ab347aa613bd78a5ad3fbc8c612 (diff)
initial radicale server
-rw-r--r--org-buetow-base/ecr.tf33
-rw-r--r--org-buetow-base/outputs.tf4
-rw-r--r--org-buetow-bastion/user_data.tpl12
-rw-r--r--org-buetow-ecs/ecs.tf7
-rw-r--r--org-buetow-ecs/radicaleservice.tf156
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"
+ }
+}
+
+