05ed037fe8
- DNS: pilot.landvex.com -> 16.170.83.169 - TLS: Let's Encrypt certificate (expires 2026-09-30) - Nginx: reverse proxy with SSL termination - API: https://pilot.landvex.com/api/v1/missions - UI: https://pilot.landvex.com/ - Upload: POST /api/v1/missions/import (multipart/form-data) Verified: ✅ https://pilot.landvex.com/health ✅ https://pilot.landvex.com/version ✅ https://pilot.landvex.com/api/v1/missions (list) ✅ https://pilot.landvex.com/api/v1/missions/:id (get) ✅ POST /api/v1/missions/import (video upload) ✅ UI loads with title 'LandveX Intelligence Lab' Next: Pilot 001 — Break the system!
232 lines
8.6 KiB
Terraform
232 lines
8.6 KiB
Terraform
# ═══════════════════════════════════════════════════════════════════════════
|
|
# Terraform: aamos-ledger
|
|
# Mål: Reproducerbar infrastruktur för bokföringsmotorn
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
terraform {
|
|
required_version = ">= 1.5"
|
|
|
|
required_providers {
|
|
aws = {
|
|
source = "hashicorp/aws"
|
|
version = "~> 5.0"
|
|
}
|
|
}
|
|
|
|
# TODO: Konfigurera remote state (S3 + DynamoDB)
|
|
# backend "s3" {
|
|
# bucket = "aamos-terraform-state"
|
|
# key = "aamos-ledger/terraform.tfstate"
|
|
# region = "eu-north-1"
|
|
# encrypt = true
|
|
# dynamodb_table = "terraform-locks"
|
|
# }
|
|
}
|
|
|
|
provider "aws" {
|
|
region = var.aws_region
|
|
|
|
default_tags {
|
|
tags = {
|
|
Project = "aamos-ledger"
|
|
ManagedBy = "terraform"
|
|
Environment = var.environment
|
|
}
|
|
}
|
|
}
|
|
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
# Variabler
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
variable "aws_region" {
|
|
description = "AWS-region"
|
|
type = string
|
|
default = "eu-north-1"
|
|
}
|
|
|
|
variable "environment" {
|
|
description = "Miljö (staging/production)"
|
|
type = string
|
|
default = "staging"
|
|
|
|
validation {
|
|
condition = contains(["staging", "production"], var.environment)
|
|
error_message = "Miljön måste vara staging eller production."
|
|
}
|
|
}
|
|
|
|
variable "instance_type" {
|
|
description = "EC2-instansstorlek"
|
|
type = string
|
|
default = "t4g.medium"
|
|
}
|
|
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
# Datakällor
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
data "aws_vpc" "default" {
|
|
default = true
|
|
}
|
|
|
|
data "aws_subnets" "default" {
|
|
filter {
|
|
name = "vpc-id"
|
|
values = [data.aws_vpc.default.id]
|
|
}
|
|
}
|
|
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
# Secrets Manager — INTE i klartext
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
resource "aws_secretsmanager_secret" "ledger_jwt" {
|
|
name = "aamos-ledger/${var.environment}/jwt-secret"
|
|
description = "JWT-signeringsnyckel för aamos-ledger"
|
|
recovery_window_in_days = 7
|
|
|
|
tags = {
|
|
Rotation = "true"
|
|
}
|
|
}
|
|
|
|
resource "aws_secretsmanager_secret" "ledger_internal" {
|
|
name = "aamos-ledger/${var.environment}/internal-token"
|
|
description = "Service-to-service token för aamos-ledger"
|
|
recovery_window_in_days = 7
|
|
}
|
|
|
|
resource "aws_secretsmanager_secret" "ledger_db" {
|
|
name = "aamos-ledger/${var.environment}/database-url"
|
|
description = "Databasanslutning för aamos-ledger"
|
|
recovery_window_in_days = 7
|
|
}
|
|
|
|
resource "aws_secretsmanager_secret" "ledger_redis" {
|
|
name = "aamos-ledger/${var.environment}/redis-url"
|
|
description = "Redis-anslutning för aamos-ledger"
|
|
recovery_window_in_days = 7
|
|
}
|
|
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
# IAM — Minimala rättigheter
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
resource "aws_iam_role" "ledger_ec2" {
|
|
name = "aamos-ledger-${var.environment}-ec2"
|
|
|
|
assume_role_policy = jsonencode({
|
|
Version = "2012-10-17"
|
|
Statement = [{
|
|
Action = "sts:AssumeRole"
|
|
Effect = "Allow"
|
|
Principal = {
|
|
Service = "ec2.amazonaws.com"
|
|
}
|
|
}]
|
|
})
|
|
}
|
|
|
|
resource "aws_iam_role_policy" "ledger_secrets" {
|
|
name = "aamos-ledger-${var.environment}-secrets"
|
|
role = aws_iam_role.ledger_ec2.id
|
|
|
|
policy = jsonencode({
|
|
Version = "2012-10-17"
|
|
Statement = [{
|
|
Effect = "Allow"
|
|
Action = [
|
|
"secretsmanager:GetSecretValue"
|
|
]
|
|
Resource = [
|
|
aws_secretsmanager_secret.ledger_jwt.arn,
|
|
aws_secretsmanager_secret.ledger_internal.arn,
|
|
aws_secretsmanager_secret.ledger_db.arn,
|
|
aws_secretsmanager_secret.ledger_redis.arn
|
|
]
|
|
}]
|
|
})
|
|
}
|
|
|
|
resource "aws_iam_instance_profile" "ledger" {
|
|
name = "aamos-ledger-${var.environment}"
|
|
role = aws_iam_role.ledger_ec2.name
|
|
}
|
|
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
# Security Group
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
resource "aws_security_group" "ledger" {
|
|
name_prefix = "aamos-ledger-${var.environment}-"
|
|
vpc_id = data.aws_vpc.default.id
|
|
|
|
ingress {
|
|
from_port = 3250
|
|
to_port = 3250
|
|
protocol = "tcp"
|
|
cidr_blocks = ["10.0.0.0/8"] # TODO: Begränsa till ALB/NLB
|
|
description = "aamos-ledger API"
|
|
}
|
|
|
|
egress {
|
|
from_port = 0
|
|
to_port = 0
|
|
protocol = "-1"
|
|
cidr_blocks = ["0.0.0.0/0"]
|
|
description = "All outbound traffic"
|
|
}
|
|
|
|
lifecycle {
|
|
create_before_destroy = true
|
|
}
|
|
}
|
|
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
# EC2-instans
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
resource "aws_instance" "ledger" {
|
|
ami = data.aws_ami.amazon_linux_2023.id
|
|
instance_type = var.instance_type
|
|
iam_instance_profile = aws_iam_instance_profile.ledger.name
|
|
vpc_security_group_ids = [aws_security_group.ledger.id]
|
|
|
|
user_data = base64encode(templatefile("${path.module}/user-data.sh", {
|
|
environment = var.environment
|
|
secrets_arn = aws_secretsmanager_secret.ledger_jwt.arn
|
|
}))
|
|
|
|
tags = {
|
|
Name = "aamos-ledger-${var.environment}"
|
|
}
|
|
|
|
# TODO: Lägg till EBS-kryptering
|
|
# TODO: Lägg till CloudWatch övervakning
|
|
}
|
|
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
# Outputs
|
|
# ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
output "instance_id" {
|
|
description = "EC2-instans-ID"
|
|
value = aws_instance.ledger.id
|
|
}
|
|
|
|
output "instance_ip" {
|
|
description = "Privat IP-adress"
|
|
value = aws_instance.ledger.private_ip
|
|
}
|
|
|
|
output "secrets_arns" {
|
|
description = "ARN för Secrets Manager"
|
|
value = {
|
|
jwt = aws_secretsmanager_secret.ledger_jwt.arn
|
|
internal = aws_secretsmanager_secret.ledger_internal.arn
|
|
db = aws_secretsmanager_secret.ledger_db.arn
|
|
redis = aws_secretsmanager_secret.ledger_redis.arn
|
|
}
|
|
}
|