hearth/terraform/bootstrap/main.tf
Eric Garcia b1065ca887 feat(minimal): Add k3s-on-EC2 infrastructure for single user
Decision from 12-expert alignment dialogue on single-user scale.
Implements Option E with modifications:

- t4g.small spot instance (~$5/mo)
- k3s with Traefik for ingress + Let's Encrypt TLS
- SQLite database for Forgejo
- S3 backups with 30-day lifecycle
- EBS gp3 20GB encrypted
- Admin SSH on port 2222, Git SSH on port 22

Total cost: ~$7.50/month

Includes:
- terraform/minimal/ - full terraform configuration
- terraform/bootstrap/ - state backend (already applied)
- docs/spikes/0001-single-user-scale.md - decision documentation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 06:21:55 -05:00

93 lines
1.8 KiB
HCL

# Terraform Backend Bootstrap
# Creates S3 bucket and DynamoDB table for terraform state
terraform {
required_version = ">= 1.5.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.30"
}
}
}
provider "aws" {
region = "us-east-1"
profile = "hearth"
default_tags {
tags = {
Project = "hearth"
ManagedBy = "terraform"
Environment = "production"
}
}
}
# S3 Bucket for Terraform State
resource "aws_s3_bucket" "terraform_state" {
bucket = "hearth-terraform-state-${data.aws_caller_identity.current.account_id}"
lifecycle {
prevent_destroy = true
}
}
resource "aws_s3_bucket_versioning" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_s3_bucket_server_side_encryption_configuration" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "aws:kms"
}
bucket_key_enabled = true
}
}
resource "aws_s3_bucket_public_access_block" "terraform_state" {
bucket = aws_s3_bucket.terraform_state.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
# DynamoDB Table for State Locking
resource "aws_dynamodb_table" "terraform_locks" {
name = "hearth-terraform-locks"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}
data "aws_caller_identity" "current" {}
output "state_bucket" {
value = aws_s3_bucket.terraform_state.id
}
output "state_bucket_arn" {
value = aws_s3_bucket.terraform_state.arn
}
output "lock_table" {
value = aws_dynamodb_table.terraform_locks.id
}
output "account_id" {
value = data.aws_caller_identity.current.account_id
}