Major changes

This commit is contained in:
2025-06-05 23:27:50 +02:00
parent a2dc223d1f
commit 3ea65f060f
107 changed files with 714 additions and 76 deletions
+7
View File
@@ -0,0 +1,7 @@
terraform {
backend "s3" {
bucket = "a13labs.infra.eu"
key = "aws.core.infra.tfstate"
region = "eu-west-1"
}
}
+34
View File
@@ -0,0 +1,34 @@
resource "aws_cloudwatch_metric_alarm" "billing_alarm" {
alarm_name = "billing_alarm"
comparison_operator = "GreaterThanThreshold"
metric_name = "EstimatedCharges"
namespace = "AWS/Billing"
evaluation_periods = "1"
period = "21600"
statistic = "Maximum"
threshold = local.billing_alarm_limit
alarm_description = "Billing alarm"
alarm_actions = [aws_sns_topic.billing_alarm_topic.arn]
tags = {
Name = "billing_alarm_topic_cf"
CreatedBy = "terraform"
Environment = "aws-alarms"
}
}
# The SNS topic with email subscriptions
# https://medium.com/@raghuram.arumalla153/aws-sns-topic-subscription-with-email-protocol-using-terraform-ed05f4f19b73
resource "aws_sns_topic" "billing_alarm_topic" {
name = "billing_alarm_topic"
provisioner "local-exec" {
command = "sh ${path.module}/scripts/sns_subscription.sh"
environment = {
AWS_DEFAULT_REGION = var.region
sns_arn = self.arn
sns_emails = local.billing_alarm_emails
}
}
}
+51
View File
@@ -0,0 +1,51 @@
resource "aws_s3_bucket" "infra_bucket" {
bucket = "a13labs.infra.eu"
force_destroy = true
}
resource "aws_s3_bucket_public_access_block" "infra_bucket" {
bucket = aws_s3_bucket.infra_bucket.id
block_public_acls = true
ignore_public_acls = true
block_public_policy = true
restrict_public_buckets = true
}
resource "aws_s3_bucket_versioning" "infra_bucket" {
bucket = aws_s3_bucket.infra_bucket.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_s3_bucket_lifecycle_configuration" "infra_bucket" {
bucket = aws_s3_bucket.infra_bucket.id
rule {
id = "clenaup"
status = "Enabled"
filter {
prefix = "/"
}
expiration {
days = 30
}
}
}
import {
id = "a13labs.infra.eu"
to = aws_s3_bucket.infra_bucket
}
import {
id = "a13labs.infra.eu"
to = aws_s3_bucket_public_access_block.infra_bucket
}
import {
id = "a13labs.infra.eu"
to = aws_s3_bucket_versioning.infra_bucket
}
+25
View File
@@ -0,0 +1,25 @@
locals {
billing_alarm_limit = 20
billing_alarm_emails = "c.alexandre.pires@alexpires.me"
instance_ips = [
"${local.vps_1.ip}/32",
]
vps_1 = {
id = data.terraform_remote_state.contabo.outputs.instances[0].id
name = data.terraform_remote_state.contabo.outputs.instances[0].name
ip = data.terraform_remote_state.contabo.outputs.instances[0].ip_config[0].v4[0].ip
}
}
data "terraform_remote_state" "contabo" {
backend = "s3"
config = {
bucket = "a13labs.infra.eu"
key = "contabo.core.infra.tfstate"
region = "eu-west-1"
}
}
data "aws_caller_identity" "current" {}
+83
View File
@@ -0,0 +1,83 @@
data "aws_iam_policy_document" "kms_key_policy" {
statement {
sid = "Enable IAM User Permissions"
effect = "Allow"
actions = ["kms:*"]
resources = ["*"]
principals {
type = "AWS"
identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"]
}
}
statement {
sid = "Allow IAM User Access"
effect = "Allow"
actions = [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
]
resources = ["*"]
principals {
type = "AWS"
identifiers = [aws_iam_user.k8s_secrets_user.arn]
}
condition {
# Only allow from specific IP addresses
test = "IpAddress"
variable = "aws:SourceIp"
values = ["${join(",", local.instance_ips)}"]
}
}
}
resource "aws_kms_key" "k8s_secrets" {
description = "KMS key for encrypting Kubernetes secrets"
deletion_window_in_days = 30
enable_key_rotation = true
policy = data.aws_iam_policy_document.kms_key_policy.json
}
resource "aws_iam_user" "k8s_secrets_user" {
name = "alexpires-me-microk8s"
}
resource "aws_iam_access_key" "k8s_secrets_user_key" {
user = aws_iam_user.k8s_secrets_user.name
}
data "aws_iam_policy_document" "k8s_secrets_user_policy" {
statement {
effect = "Allow"
actions = [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
]
resources = [aws_kms_key.k8s_secrets.arn]
condition {
# Only allow from specific IP addresses
test = "IpAddress"
variable = "aws:SourceIp"
values = ["${join(",", local.instance_ips)}"]
}
}
}
resource "aws_iam_user_policy" "k8s_secrets_user_policy" {
name = "alexpires-me-microk8s-policy"
user = aws_iam_user.k8s_secrets_user.name
policy = data.aws_iam_policy_document.k8s_secrets_user_policy.json
}
+14
View File
@@ -0,0 +1,14 @@
terraform {
required_version = ">1.9"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~>5.70"
}
}
}
# Configure the AWS Provider
provider "aws" {
region = var.region
}
@@ -0,0 +1,6 @@
#!/usr/bin/env sh
for email in $sns_emails; do
echo $email
aws sns subscribe --topic-arn "$sns_arn" --protocol email --notification-endpoint "$email"
done
+2
View File
@@ -0,0 +1,2 @@
AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY
AWS_SECRET_ACCESS_KEY=$AWS_SECRET_KEY
+4
View File
@@ -0,0 +1,4 @@
variable "region" {
description = "AWS Default region"
default = "eu-west-1"
}
+7
View File
@@ -0,0 +1,7 @@
terraform {
backend "s3" {
bucket = "a13labs.infra.eu"
key = "cloudns.core.infra.tfstate"
region = "eu-west-1"
}
}
+207
View File
@@ -0,0 +1,207 @@
locals {
vps_1 = {
id = data.terraform_remote_state.contabo.outputs.instances[0].id
name = data.terraform_remote_state.contabo.outputs.instances[0].name
ip = data.terraform_remote_state.contabo.outputs.instances[0].ip_config[0].v4[0].ip
}
default_ttl = "3600"
domains = {
"a13labs.me" = [
{
type = "A"
value = local.vps_1.ip
},
{
type = "MX"
priority = "10"
value = "mail-pt.securemail.pro"
},
{
type = "TXT"
value = "v=spf1 include:_spf.tem.scaleway.com include:spf.webapps.net ~all"
},
{
name = "imap"
type = "CNAME"
value = "${local.vps_1.name}.a13labs.me"
},
{
name = "mail"
type = "CNAME"
value = "mail-pt.securemail.pro"
},
{
name = "smtp"
type = "CNAME"
value = "${local.vps_1.name}.a13labs.me"
},
{
name = "_dmarc"
type = "TXT"
value = "v=DMARC1; p=none; rua=mailto:admin@a13labs.me"
},
{
name = local.vps_1.name
type = "A"
value = local.vps_1.ip
},
{
name = "_imap._tcp"
type = "SRV"
priority = "0"
weight = "1"
port = "993"
value = "imap.a13labs.me"
},
{
name = "_smtp._tcp"
type = "SRV"
priority = "0"
weight = "1"
port = "465"
value = "smtp.a13labs.me"
},
{
name = "${var.scaleway_dkim_key}._domainkey"
type = "TXT"
value = "v=DKIM1; h=sha256; k=rsa; p=${var.a13labs_me_scaleway_dkim_value}"
},
],
"alexpires.me" = [
{
type = "A"
value = local.vps_1.ip
},
{
name = ""
type = "MX"
priority = "10"
value = "mail-pt.securemail.pro"
},
{
type = "TXT"
value = "v=spf1 include:_spf.tem.scaleway.com include:spf.webapps.net ~all"
},
{
name = "tv"
type = "CNAME"
value = "${local.vps_1.name}.alexpires.me"
},
{
name = "www"
type = "CNAME"
value = "${local.vps_1.name}.alexpires.me"
},
{
name = "blog"
type = "CNAME"
value = "${local.vps_1.name}.alexpires.me"
},
{
name = "code"
type = "CNAME"
value = "${local.vps_1.name}.alexpires.me"
},
{
name = "imap"
type = "CNAME"
value = "${local.vps_1.name}.alexpires.me"
},
{
name = "mail"
type = "CNAME"
value = "mail-pt.securemail.pro"
},
{
name = "smtp"
type = "CNAME"
value = "${local.vps_1.name}.alexpires.me"
},
{
name = "cloud"
type = "CNAME"
value = "${local.vps_1.name}.alexpires.me"
},
{
name = "_dmarc"
type = "TXT"
value = "v=DMARC1; p=none; rua=mailto:admin@alexpires.me"
},
{
name = "prod-01"
type = "CNAME"
value = "${local.vps_1.name}.alexpires.me"
},
{
name = "_keybase"
type = "TXT"
value = "keybase-site-verification=${var.keybase_site_verification}"
},
{
name = "rustdesk"
type = "CNAME"
value = "${local.vps_1.name}.alexpires.me"
},
{
name = local.vps_1.name
type = "A"
value = local.vps_1.ip
},
{
name = "_imap._tcp"
type = "SRV"
priority = "0"
weight = "1"
port = "993"
value = "imap.alexpires.me"
},
{
name = "_smtp._tcp"
type = "SRV"
priority = "0"
weight = "1"
port = "465"
value = "smtp.alexpires.me"
},
{
name = "${var.scaleway_dkim_key}._domainkey"
type = "TXT"
value = "v=DKIM1; h=sha256; k=rsa; p=${var.alexpires_me_scaleway_dkim_value}"
},
{
name = "webdav"
type = "CNAME"
value = "${local.vps_1.name}.alexpires.me"
},
{
name = "ai"
type = "CNAME"
value = "${local.vps_1.name}.alexpires.me"
},
]
}
records = flatten([for domain, records in local.domains : [
for record in records : {
name = lookup(record, "name", "")
zone = domain
type = record.type
value = record.value
priority = lookup(record, "priority", null)
weight = lookup(record, "weight", null)
port = lookup(record, "port", null)
}
]])
}
data "terraform_remote_state" "contabo" {
backend = "s3"
config = {
bucket = "a13labs.infra.eu"
key = "contabo.core.infra.tfstate"
region = "eu-west-1"
}
}
+14
View File
@@ -0,0 +1,14 @@
terraform {
required_version = "~>1.8"
required_providers {
cloudns = {
source = "ClouDNS/cloudns"
version = "~>1.0"
}
}
}
provider "cloudns" {
auth_id = var.cloudns_auth_id
password = var.cloudns_password
}
+26
View File
@@ -0,0 +1,26 @@
resource "cloudns_dns_zone" "zones" {
for_each = local.domains
domain = each.key
type = "master"
}
import {
for_each = local.domains
to = cloudns_dns_zone.zones[each.key]
id = each.key
}
resource "cloudns_dns_record" "records" {
for_each = {
for i, record in local.records :
i => record
}
name = each.value.name
zone = each.value.zone
type = each.value.type
value = each.value.value
priority = lookup(each.value, "priority", null)
weight = lookup(each.value, "weight", null)
port = lookup(each.value, "port", null)
ttl = lookup(each.value, "ttl", local.default_ttl)
}
+8
View File
@@ -0,0 +1,8 @@
AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY
AWS_SECRET_ACCESS_KEY=$AWS_SECRET_KEY
TF_VAR_cloudns_auth_id=$CLOUDNS_AUTH_ID
TF_VAR_cloudns_password=$CLOUDNS_PASSWORD
TF_VAR_scaleway_dkim_key=$SCALEWAY_DKIM_KEY
TF_VAR_alexpires_me_scaleway_dkim_value=$ALEXPIRES_ME_SCALEWAY_DKIM_VALUE
TF_VAR_a13labs_me_scaleway_dkim_value=$A13LABS_ME_SCALEWAY_DKIM_VALUE
TF_VAR_keybase_site_verification=$KEYBASE_SITE_VERIFICATION
+36
View File
@@ -0,0 +1,36 @@
variable "cloudns_auth_id" {
description = "Cloudns Auth ID"
type = string
sensitive = true
}
variable "cloudns_password" {
description = "Cloudns Password"
type = string
sensitive = true
}
variable "scaleway_dkim_key" {
description = "Scaleway DKIM key"
type = string
sensitive = true
}
variable "alexpires_me_scaleway_dkim_value" {
description = "Scaleway DKIM value (alexpires.me)"
type = string
sensitive = true
}
variable "a13labs_me_scaleway_dkim_value" {
description = "Scaleway DKIM value (a13labs.me)"
type = string
sensitive = true
}
variable "keybase_site_verification" {
description = "Keybase site verification"
type = string
sensitive = true
}
+7
View File
@@ -0,0 +1,7 @@
terraform {
backend "s3" {
bucket = "a13labs.infra.eu"
key = "contabo.core.infra.tfstate"
region = "eu-west-1"
}
}
+3
View File
@@ -0,0 +1,3 @@
resource "contabo_instance" "vps_1" {
}
+18
View File
@@ -0,0 +1,18 @@
output "instances" {
value = [
{
cpu_cores = contabo_instance.vps_1.cpu_cores
disk_mb = contabo_instance.vps_1.disk_mb
id = contabo_instance.vps_1.id
image_id = contabo_instance.vps_1.image_id
ip_config = contabo_instance.vps_1.ip_config
mac_address = contabo_instance.vps_1.mac_address
name = contabo_instance.vps_1.name
os_type = contabo_instance.vps_1.os_type
ram_mb = contabo_instance.vps_1.ram_mb
v_host_id = contabo_instance.vps_1.v_host_id
},
]
description = "VPS instances details"
sensitive = true
}
+17
View File
@@ -0,0 +1,17 @@
terraform {
required_version = "~>1.8"
required_providers {
contabo = {
source = "contabo/contabo"
version = ">= 0.1.31"
}
}
}
provider "contabo" {
oauth2_client_id = var.contabo_client_id
oauth2_client_secret = var.contabo_client_secret
oauth2_user = var.contabo_api_user
oauth2_pass = var.contabo_api_password
}
+6
View File
@@ -0,0 +1,6 @@
AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY
AWS_SECRET_ACCESS_KEY=$AWS_SECRET_KEY
TF_VAR_contabo_client_id=$CONTABO_CLIENT_ID
TF_VAR_contabo_client_secret=$CONTABO_CLIENT_SECRET
TF_VAR_contabo_api_password=$CONTABO_API_PASSWORD
TF_VAR_contabo_api_user=$CONTABO_USER_NAME
+23
View File
@@ -0,0 +1,23 @@
variable "contabo_client_id" {
description = "Contabo Client ID"
type = string
sensitive = true
}
variable "contabo_client_secret" {
description = "Contabo Client Secret"
type = string
sensitive = true
}
variable "contabo_api_password" {
description = "Contabo API Password"
type = string
sensitive = true
}
variable "contabo_api_user" {
description = "Contabo API User"
type = string
sensitive = true
}
+7
View File
@@ -0,0 +1,7 @@
terraform {
backend "s3" {
bucket = "a13labs.infra.eu"
key = "scaleway.core.infra.tfstate"
region = "eu-west-1"
}
}
+45
View File
@@ -0,0 +1,45 @@
resource "scaleway_object_bucket" "infra_assets" {
name = "a13labs-infra-${var.bucket_suffix}"
project_id = var.scaleway_project_id
region = "fr-par"
}
resource "scaleway_object_bucket_policy" "policy" {
bucket = scaleway_object_bucket.infra_assets.name
policy = jsonencode({
Version = "2023-04-17",
Id = "AllowMachineDownload",
Statement = [
{
Effect = "Allow"
Action = [
"s3:ListBucket",
"s3:GetObject",
]
Principal = "*"
Resource = [
scaleway_object_bucket.infra_assets.name,
"${scaleway_object_bucket.infra_assets.name}/*",
]
Condition = {
IpAddress = {
"aws:SourceIp" = local.instance_ips
}
},
},
{
Effect = "Allow"
Action = [
"s3:*",
]
Principal = {
SCW = "user_id:${var.scaleway_user_id}"
}
Resource = [
scaleway_object_bucket.infra_assets.name,
"${scaleway_object_bucket.infra_assets.name}/*",
]
},
]
})
}
+21
View File
@@ -0,0 +1,21 @@
locals {
instance_ips = [
"${local.vps_1.ip}/32",
]
vps_1 = {
id = data.terraform_remote_state.contabo.outputs.instances[0].id
name = data.terraform_remote_state.contabo.outputs.instances[0].name
ip = data.terraform_remote_state.contabo.outputs.instances[0].ip_config[0].v4[0].ip
}
}
data "terraform_remote_state" "contabo" {
backend = "s3"
config = {
bucket = "a13labs.infra.eu"
key = "contabo.core.infra.tfstate"
region = "eu-west-1"
}
}
+18
View File
@@ -0,0 +1,18 @@
resource "scaleway_object" "system_id_encryption_key" {
bucket = scaleway_object_bucket.infra_assets.id
key = "keys/${var.system_id}"
content_base64 = base64encode(var.encryption_key)
}
resource "scaleway_object" "system_id_encryption_aws_credentials" {
bucket = scaleway_object_bucket.infra_assets.id
key = "keys/${var.system_id}-encryption-service-credentials.json"
content = jsonencode({
access_key = var.kms_access_key
secret_key = var.kms_secret_key
region = "eu-west-1"
key_arn = var.kms_key_arn
})
}
+19
View File
@@ -0,0 +1,19 @@
terraform {
required_version = "~>1.8"
required_providers {
scaleway = {
source = "scaleway/scaleway"
version = "~>2.13"
}
}
}
provider "scaleway" {
zone = "fr-par-2"
region = "fr-par"
access_key = var.scaleway_access_key
secret_key = var.scaleway_secret_key
organization_id = var.scaleway_organization_id
}
+5
View File
@@ -0,0 +1,5 @@
resource "scaleway_registry_namespace" "a13labs" {
name = "a13labs"
description = "A13Labs container registry"
is_public = false
}
+12
View File
@@ -0,0 +1,12 @@
AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY
AWS_SECRET_ACCESS_KEY=$AWS_SECRET_KEY
TF_VAR_scaleway_access_key=$SCALEWAY_ACCESS_KEY
TF_VAR_scaleway_secret_key=$SCALEWAY_SECRET_KEY
TF_VAR_scaleway_project_id=$SCALEWAY_PROJECT_ID
TF_VAR_scaleway_organization_id=$SCALEWAY_ORGANIZATION_ID
TF_VAR_scaleway_user_id=$SCALEWAY_USER_ID
TF_VAR_bucket_suffix=$BUCKET_SUFFIX
TF_VAR_encryption_key=$ENCRYPT_KEY
TF_VAR_kms_access_key=$KMS_ACCESS_KEY
TF_VAR_kms_secret_key=$KMS_SECRET_KEY
TF_VAR_kms_key_arn=$KMS_KEY_ARN
+65
View File
@@ -0,0 +1,65 @@
variable "scaleway_access_key" {
description = "Scaleway Access key"
type = string
sensitive = true
}
variable "scaleway_secret_key" {
description = "Scaleway Secret key"
type = string
sensitive = true
}
variable "scaleway_project_id" {
description = "Scaleway Project Id"
type = string
sensitive = true
}
variable "scaleway_organization_id" {
description = "Scaleway Organization Id"
type = string
sensitive = true
}
variable "scaleway_user_id" {
description = "Scaleway User Id"
type = string
sensitive = true
}
variable "encryption_key" {
description = "Encryption key for sensitive data"
type = string
sensitive = true
}
variable "bucket_suffix" {
description = "Suffix for bucket names"
type = string
sensitive = true
}
variable "system_id" {
description = "System ID"
type = string
sensitive = true
}
variable "kms_access_key" {
description = "KMS User Access key"
type = string
sensitive = true
}
variable "kms_secret_key" {
description = "KMS User Secret key"
type = string
sensitive = true
}
variable "kms_key_arn" {
description = "KMS Access key ARN"
type = string
sensitive = true
}