Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion backend/pdm.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions backend/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ dependencies = [
"cryptography>=43.0.0",
"openai>=1.52.0",
"pydantic>=2.9.2",
"gunicorn>=23.0.0",
]
name = "backend"
version = "0.1.0"
Expand Down
1 change: 1 addition & 0 deletions infrastructure/applications/.tool-versions
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
terraform 1.9.8
23 changes: 22 additions & 1 deletion infrastructure/applications/applications.tf
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,20 @@ locals {

module "pretix" {
source = "./pretix"
count = local.deploy_pretix ? 1 : 0
count = 1
ecs_arm_ami = local.ecs_arm_ami
server_ip = module.cluster.server_ip
cluster_id = module.cluster.cluster_id
logs_group_name = module.cluster.logs_group_name
}

module "pycon_backend" {
source = "./pycon_backend"
ecs_arm_ami = local.ecs_arm_ami
cluster_id = module.cluster.cluster_id
security_group_id = module.cluster.security_group_id
server_ip = module.cluster.server_ip
logs_group_name = module.cluster.logs_group_name

providers = {
aws = aws
Expand All @@ -40,3 +47,17 @@ module "emails" {
aws.us = aws.us
}
}

module "cluster" {
source = "./cluster"
ecs_arm_ami = local.ecs_arm_ami

providers = {
aws = aws
aws.us = aws.us
}
}

output "server_public_ip" {
value = module.cluster.server_public_ip
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,38 @@
locals {
pycon_web_domain = local.is_prod ? "admin.pycon.it" : "${terraform.workspace}-admin.pycon.it"
pretix_web_domain = local.is_prod ? "tickets.pycon.it" : "${terraform.workspace}-tickets.pycon.it"
}

data "aws_cloudfront_origin_request_policy" "all_viewer" {
name = "Managed-AllViewer"
}

data "aws_cloudfront_cache_policy" "caching_disabled" {
name = "Managed-CachingDisabled"
}

data "aws_cloudfront_origin_request_policy" "all_viewer_except_host_header" {
name = "Managed-AllViewerExceptHostHeader"
data "aws_acm_certificate" "cert" {
domain = "*.pycon.it"
statuses = ["ISSUED"]
provider = aws.us
}

resource "aws_cloudfront_distribution" "application" {
enabled = true
is_ipv6_enabled = true
comment = "${terraform.workspace}-${var.application}"
comment = "${terraform.workspace} server"
wait_for_deployment = false
aliases = [var.domain]
aliases = [
local.pycon_web_domain,
local.pretix_web_domain
]

origin {
domain_name = var.origin_url
domain_name = aws_eip.server.public_dns
origin_id = "default"

custom_origin_config {
origin_protocol_policy = "https-only"
origin_protocol_policy = "http-only"
http_port = "80"
https_port = "443"
origin_ssl_protocols = ["TLSv1"]
Expand All @@ -29,7 +43,7 @@ resource "aws_cloudfront_distribution" "application" {
cloudfront_default_certificate = false
minimum_protocol_version = "TLSv1"
ssl_support_method = "sni-only"
acm_certificate_arn = var.certificate_arn
acm_certificate_arn = data.aws_acm_certificate.cert.arn
}

default_cache_behavior {
Expand All @@ -38,16 +52,10 @@ resource "aws_cloudfront_distribution" "application" {
target_origin_id = "default"

cache_policy_id = data.aws_cloudfront_cache_policy.caching_disabled.id
origin_request_policy_id = data.aws_cloudfront_origin_request_policy.all_viewer_except_host_header.id
origin_request_policy_id = data.aws_cloudfront_origin_request_policy.all_viewer.id

viewer_protocol_policy = "redirect-to-https"
compress = true

lambda_function_association {
event_type = "viewer-request"
lambda_arn = var.forward_host_header_lambda_arn
include_body = false
}
}

restrictions {
Expand Down
27 changes: 27 additions & 0 deletions infrastructure/applications/cluster/domains.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
data "aws_route53_zone" "zone" {
name = "pycon.it"
}

resource "aws_route53_record" "web_pycon" {
zone_id = data.aws_route53_zone.zone.zone_id
name = local.pycon_web_domain
type = "A"

alias {
name = aws_cloudfront_distribution.application.domain_name
zone_id = aws_cloudfront_distribution.application.hosted_zone_id
evaluate_target_health = false
}
}

resource "aws_route53_record" "web_tickets" {
zone_id = data.aws_route53_zone.zone.zone_id
name = local.pretix_web_domain
type = "A"

alias {
name = aws_cloudfront_distribution.application.domain_name
zone_id = aws_cloudfront_distribution.application.hosted_zone_id
evaluate_target_health = false
}
}
81 changes: 81 additions & 0 deletions infrastructure/applications/cluster/iam.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
resource "aws_iam_instance_profile" "server" {
name = "pythonit-${terraform.workspace}-server"
role = aws_iam_role.server.name
}

resource "aws_iam_role" "server" {
name = "pythonit-${terraform.workspace}-server-role"
assume_role_policy = data.aws_iam_policy_document.server_assume_role.json
}

resource "aws_iam_role_policy" "server" {
name = "pythonit-${terraform.workspace}-server-policy"
role = aws_iam_role.server.id
policy = data.aws_iam_policy_document.server_role_policy.json
}

data "aws_iam_policy_document" "server_assume_role" {
statement {
effect = "Allow"

principals {
type = "Service"
identifiers = ["ec2.amazonaws.com", "ecs-tasks.amazonaws.com"]
}

actions = ["sts:AssumeRole"]
}
}

data "aws_iam_policy_document" "server_role_policy" {
statement {
effect = "Allow"
actions = [
"iam:PassRole",
"ses:*",
"ecs:*",
"ecr:*",
"ec2:DescribeInstances",
]
resources = [
"*"
]
}

statement {
effect = "Allow"
actions = ["cloudwatch:PutMetricData", "logs:*"]
resources = ["*"]
}

statement {
effect = "Allow"
actions = ["s3:*"]
resources = [
"arn:aws:s3:::${terraform.workspace}-pycon-backend-media",
"arn:aws:s3:::${terraform.workspace}-pycon-backend-media/*",
"arn:aws:s3:::${terraform.workspace}-pretix-media",
"arn:aws:s3:::${terraform.workspace}-pretix-media/*",
]
}

statement {
actions = [
"sns:CreatePlatformEndpoint",
"sns:Publish"
]
resources = ["*"]
effect = "Allow"
}

statement {
actions = [
"sqs:SendMessage",
"sqs:DeleteMessage",
"sqs:GetQueueAttributes",
"sqs:ReceiveMessage",
]
resources = ["*"]
effect = "Allow"
}
}
83 changes: 83 additions & 0 deletions infrastructure/applications/cluster/load_balancer_task.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
resource "aws_ecs_task_definition" "traefik" {
family = "pythonit-${terraform.workspace}-traefik"

container_definitions = jsonencode([
{
name = "traefik"
image = "traefik:v3.1.2"
memoryReservation = 200
essential = true

environment = [
{
name = "TRAEFIK_PROVIDERS_ECS_CLUSTERS"
value = aws_ecs_cluster.cluster.name
},
{
name = "TRAEFIK_PROVIDERS_ECS_AUTODISCOVERCLUSTERS"
value = "false",
},
{
name = "TRAEFIK_PROVIDERS_ECS_EXPOSEDBYDEFAULT",
value = "false",
},
{
name = "TRAEFIK_ENTRYPOINTS_WEB_ADDRESS",
value = ":80"
},
{
name = "TRAEFIK_LOG_LEVEL",
value = "DEBUG"
}
]

portMappings = [
{
containerPort = 80
hostPort = 80
},
]

mountPoints = []
systemControls = [
{
"namespace" : "net.core.somaxconn",
"value" : "4096"
}
]

logConfiguration = {
logDriver = "awslogs"
options = {
"awslogs-group" = aws_cloudwatch_log_group.cluster.name
"awslogs-region" = "eu-central-1"
"awslogs-stream-prefix" = "traefik"
}
}

healthCheck = {
retries = 3
command = [
"CMD-SHELL",
"echo 4"
]
timeout = 3
interval = 10
}

stopTimeout = 300
}
])

requires_compatibilities = []
tags = {}
}

resource "aws_ecs_service" "traefik" {
name = "traefik"
cluster = aws_ecs_cluster.cluster.id
task_definition = aws_ecs_task_definition.traefik.arn
desired_count = 1
deployment_minimum_healthy_percent = 0
deployment_maximum_percent = 100
}
9 changes: 9 additions & 0 deletions infrastructure/applications/cluster/logs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
resource "aws_cloudwatch_log_group" "cluster" {
name = "/ecs/pythonit-${terraform.workspace}-cluster"
retention_in_days = 3
}


output "logs_group_name" {
value = aws_cloudwatch_log_group.cluster.name
}
16 changes: 16 additions & 0 deletions infrastructure/applications/cluster/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
locals {
is_prod = terraform.workspace == "production"
}

resource "aws_ecs_cluster" "cluster" {
name = "pythonit-${terraform.workspace}"
}

output "cluster_id" {
value = aws_ecs_cluster.cluster.id
}

resource "aws_ecs_account_setting_default" "trunking" {
name = "awsvpcTrunking"
value = "enabled"
}
Loading