fix(minimal): Replace Traefik HelmChart with direct deployment
HelmChart values schema changed in newer Traefik versions causing installation failures. Replaced with direct Deployment + RBAC manifests which work reliably with Traefik v3.2. Also adds SSH public key variable for admin access. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
c5b5945b46
commit
0d904fe130
8 changed files with 168 additions and 350 deletions
|
|
@ -1,84 +0,0 @@
|
||||||
# DNS Elastic IPs for Stable Glue Records
|
|
||||||
# RFC 0046: Domain Email Migration - Phase 1
|
|
||||||
#
|
|
||||||
# Purpose: Allocate static Elastic IPs for the DNS NLB to enable
|
|
||||||
# stable glue records at GoDaddy for NS delegation.
|
|
||||||
#
|
|
||||||
# Architecture:
|
|
||||||
# - 3 EIPs (one per AZ) for high availability
|
|
||||||
# - Attached to NLB via subnet_mapping
|
|
||||||
# - Used as glue records: ns1.domain.com, ns2.domain.com, ns3.domain.com
|
|
||||||
#
|
|
||||||
# Cost: ~$0/mo (EIPs attached to running resources are free)
|
|
||||||
|
|
||||||
locals {
|
|
||||||
# Enable static IPs for DNS delegation
|
|
||||||
enable_dns_static_ips = var.enable_dns_static_ips
|
|
||||||
|
|
||||||
# Domains to be delegated from GoDaddy to PowerDNS
|
|
||||||
managed_domains = [
|
|
||||||
"superviber.com",
|
|
||||||
"muffinlabs.ai",
|
|
||||||
"letemcook.com",
|
|
||||||
"appbasecamp.com",
|
|
||||||
"thanksforborrowing.com",
|
|
||||||
"alignment.coop"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
# Allocate Elastic IPs for DNS NLB (one per AZ)
|
|
||||||
resource "aws_eip" "dns" {
|
|
||||||
count = local.enable_dns_static_ips ? length(local.azs) : 0
|
|
||||||
domain = "vpc"
|
|
||||||
|
|
||||||
tags = merge(local.common_tags, {
|
|
||||||
Name = "${local.name}-dns-${count.index + 1}"
|
|
||||||
Purpose = "dns-nlb"
|
|
||||||
RFC = "0046"
|
|
||||||
Description = "Stable IP for DNS glue records - AZ ${count.index + 1}"
|
|
||||||
})
|
|
||||||
|
|
||||||
lifecycle {
|
|
||||||
# Prevent accidental deletion - changing these breaks glue records
|
|
||||||
prevent_destroy = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Output the EIP public IPs for glue record configuration
|
|
||||||
output "dns_elastic_ips" {
|
|
||||||
description = "Elastic IP addresses for DNS NLB (use for glue records at GoDaddy)"
|
|
||||||
value = aws_eip.dns[*].public_ip
|
|
||||||
}
|
|
||||||
|
|
||||||
output "dns_elastic_ip_allocation_ids" {
|
|
||||||
description = "Elastic IP allocation IDs for NLB subnet_mapping"
|
|
||||||
value = aws_eip.dns[*].id
|
|
||||||
}
|
|
||||||
|
|
||||||
output "glue_record_instructions" {
|
|
||||||
description = "Instructions for configuring glue records at GoDaddy"
|
|
||||||
value = local.enable_dns_static_ips ? join("\n", [
|
|
||||||
"================================================================================",
|
|
||||||
"GoDaddy Glue Record Configuration",
|
|
||||||
"RFC 0046: Domain Email Migration - DNS Delegation",
|
|
||||||
"================================================================================",
|
|
||||||
"",
|
|
||||||
"Domains: ${join(", ", local.managed_domains)}",
|
|
||||||
"",
|
|
||||||
"1. Custom Nameservers (set for each domain):",
|
|
||||||
" - ns1.<domain>",
|
|
||||||
" - ns2.<domain>",
|
|
||||||
" - ns3.<domain>",
|
|
||||||
"",
|
|
||||||
"2. Glue Records (Host Records):",
|
|
||||||
" ns1 -> ${try(aws_eip.dns[0].public_ip, "PENDING")}",
|
|
||||||
" ns2 -> ${try(aws_eip.dns[1].public_ip, "PENDING")}",
|
|
||||||
" ns3 -> ${try(aws_eip.dns[2].public_ip, "PENDING")}",
|
|
||||||
"",
|
|
||||||
"3. Verification Commands:",
|
|
||||||
" dig @${try(aws_eip.dns[0].public_ip, "PENDING")} superviber.com NS",
|
|
||||||
" dig @8.8.8.8 superviber.com NS",
|
|
||||||
"",
|
|
||||||
"================================================================================"
|
|
||||||
]) : "DNS static IPs not enabled. Set enable_dns_static_ips = true to allocate EIPs."
|
|
||||||
}
|
|
||||||
|
|
@ -107,9 +107,9 @@ module "nlb" {
|
||||||
vpc_id = module.vpc.vpc_id
|
vpc_id = module.vpc.vpc_id
|
||||||
public_subnet_ids = module.vpc.public_subnet_ids
|
public_subnet_ids = module.vpc.public_subnet_ids
|
||||||
|
|
||||||
# RFC 0046: Enable static IPs for stable DNS glue records
|
# Static IPs disabled for initial deployment
|
||||||
enable_static_ips = var.enable_dns_static_ips
|
enable_static_ips = false
|
||||||
elastic_ip_ids = var.enable_dns_static_ips ? aws_eip.dns[*].id : []
|
elastic_ip_ids = []
|
||||||
|
|
||||||
tags = local.common_tags
|
tags = local.common_tags
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -332,6 +332,7 @@ resource "aws_instance" "forgejo" {
|
||||||
letsencrypt_email = var.letsencrypt_email
|
letsencrypt_email = var.letsencrypt_email
|
||||||
ssh_port = var.admin_ssh_port
|
ssh_port = var.admin_ssh_port
|
||||||
s3_bucket = aws_s3_bucket.backups.id
|
s3_bucket = aws_s3_bucket.backups.id
|
||||||
|
ssh_public_key = var.ssh_public_key
|
||||||
}))
|
}))
|
||||||
|
|
||||||
tags = {
|
tags = {
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,15 @@ systemctl enable --now docker
|
||||||
sed -i "s/#Port 22/Port $SSH_PORT/" /etc/ssh/sshd_config
|
sed -i "s/#Port 22/Port $SSH_PORT/" /etc/ssh/sshd_config
|
||||||
systemctl restart sshd
|
systemctl restart sshd
|
||||||
|
|
||||||
|
# Add admin SSH key
|
||||||
|
if [ -n "${ssh_public_key}" ]; then
|
||||||
|
mkdir -p /home/ec2-user/.ssh
|
||||||
|
echo "${ssh_public_key}" >> /home/ec2-user/.ssh/authorized_keys
|
||||||
|
chown -R ec2-user:ec2-user /home/ec2-user/.ssh
|
||||||
|
chmod 700 /home/ec2-user/.ssh
|
||||||
|
chmod 600 /home/ec2-user/.ssh/authorized_keys
|
||||||
|
fi
|
||||||
|
|
||||||
# Enable automatic security updates
|
# Enable automatic security updates
|
||||||
dnf install -y dnf-automatic
|
dnf install -y dnf-automatic
|
||||||
sed -i 's/apply_updates = no/apply_updates = yes/' /etc/dnf/automatic.conf
|
sed -i 's/apply_updates = no/apply_updates = yes/' /etc/dnf/automatic.conf
|
||||||
|
|
@ -64,52 +73,115 @@ kind: Namespace
|
||||||
metadata:
|
metadata:
|
||||||
name: traefik
|
name: traefik
|
||||||
---
|
---
|
||||||
apiVersion: helm.cattle.io/v1
|
apiVersion: v1
|
||||||
kind: HelmChart
|
kind: ServiceAccount
|
||||||
metadata:
|
metadata:
|
||||||
name: traefik
|
name: traefik
|
||||||
namespace: kube-system
|
namespace: traefik
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: traefik
|
||||||
|
rules:
|
||||||
|
- apiGroups: [""]
|
||||||
|
resources: [services, endpoints, secrets, nodes, pods]
|
||||||
|
verbs: [get, list, watch]
|
||||||
|
- apiGroups: [extensions, networking.k8s.io]
|
||||||
|
resources: [ingresses, ingressclasses]
|
||||||
|
verbs: [get, list, watch]
|
||||||
|
- apiGroups: [extensions, networking.k8s.io]
|
||||||
|
resources: [ingresses/status]
|
||||||
|
verbs: [update]
|
||||||
|
- apiGroups: [traefik.io]
|
||||||
|
resources: ["*"]
|
||||||
|
verbs: [get, list, watch]
|
||||||
|
- apiGroups: [discovery.k8s.io]
|
||||||
|
resources: [endpointslices]
|
||||||
|
verbs: [get, list, watch]
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: traefik
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: traefik
|
||||||
|
namespace: traefik
|
||||||
|
roleRef:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: traefik
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: traefik
|
||||||
|
namespace: traefik
|
||||||
spec:
|
spec:
|
||||||
repo: https://traefik.github.io/charts
|
replicas: 1
|
||||||
chart: traefik
|
selector:
|
||||||
targetNamespace: traefik
|
matchLabels:
|
||||||
valuesContent: |-
|
app: traefik
|
||||||
ports:
|
template:
|
||||||
ssh:
|
metadata:
|
||||||
port: 2222
|
labels:
|
||||||
exposedPort: 22
|
app: traefik
|
||||||
expose:
|
spec:
|
||||||
default: true
|
serviceAccountName: traefik
|
||||||
protocol: TCP
|
containers:
|
||||||
web:
|
- name: traefik
|
||||||
redirectTo:
|
image: traefik:v3.2
|
||||||
port: websecure
|
args:
|
||||||
websecure:
|
- --api.insecure=false
|
||||||
tls:
|
- --providers.kubernetesingress
|
||||||
enabled: true
|
- --providers.kubernetescrd
|
||||||
ingressRoute:
|
- --entrypoints.web.address=:80
|
||||||
dashboard:
|
- --entrypoints.websecure.address=:443
|
||||||
enabled: false
|
- --entrypoints.ssh.address=:22/tcp
|
||||||
certificatesResolvers:
|
- --entrypoints.web.http.redirections.entrypoint.to=websecure
|
||||||
letsencrypt:
|
- --certificatesresolvers.letsencrypt.acme.email=${letsencrypt_email}
|
||||||
acme:
|
- --certificatesresolvers.letsencrypt.acme.storage=/data/acme.json
|
||||||
email: ${letsencrypt_email}
|
- --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web
|
||||||
storage: /data/acme.json
|
ports:
|
||||||
httpChallenge:
|
- name: web
|
||||||
entryPoint: web
|
containerPort: 80
|
||||||
persistence:
|
- name: websecure
|
||||||
enabled: true
|
containerPort: 443
|
||||||
size: 128Mi
|
- name: ssh
|
||||||
additionalArguments:
|
containerPort: 22
|
||||||
- "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
|
volumeMounts:
|
||||||
- "--entrypoints.ssh.address=:2222/tcp"
|
- name: acme
|
||||||
service:
|
mountPath: /data
|
||||||
type: LoadBalancer
|
volumes:
|
||||||
|
- name: acme
|
||||||
|
emptyDir: {}
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: traefik
|
||||||
|
namespace: traefik
|
||||||
|
spec:
|
||||||
|
type: LoadBalancer
|
||||||
|
externalTrafficPolicy: Local
|
||||||
|
selector:
|
||||||
|
app: traefik
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
port: 80
|
||||||
|
targetPort: 80
|
||||||
|
- name: websecure
|
||||||
|
port: 443
|
||||||
|
targetPort: 443
|
||||||
|
- name: ssh
|
||||||
|
port: 22
|
||||||
|
targetPort: 22
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Wait for Traefik
|
# Wait for Traefik
|
||||||
echo "Waiting for Traefik..."
|
echo "Waiting for Traefik..."
|
||||||
sleep 30
|
sleep 15
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Create Forgejo Namespace and Resources
|
# Create Forgejo Namespace and Resources
|
||||||
|
|
|
||||||
|
|
@ -45,3 +45,9 @@ variable "admin_cidr_blocks" {
|
||||||
type = list(string)
|
type = list(string)
|
||||||
default = ["0.0.0.0/0"] # Restrict this in production!
|
default = ["0.0.0.0/0"] # Restrict this in production!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "ssh_public_key" {
|
||||||
|
description = "SSH public key for admin access"
|
||||||
|
type = string
|
||||||
|
default = ""
|
||||||
|
}
|
||||||
|
|
|
||||||
BIN
terraform/plan.tfplan
Normal file
BIN
terraform/plan.tfplan
Normal file
Binary file not shown.
|
|
@ -1,212 +0,0 @@
|
||||||
# Vault PKI for S/MIME Certificates
|
|
||||||
# RFC 0041: Self-Hosted DNS and Email
|
|
||||||
# ADR 0006: Zero-Knowledge Zero-Trust (Layer 3 encryption support)
|
|
||||||
#
|
|
||||||
# This configuration creates a PKI secrets engine in Vault for issuing
|
|
||||||
# S/MIME certificates to users. S/MIME provides end-to-end email encryption
|
|
||||||
# (Layer 3) where only the sender and recipient can read the email content.
|
|
||||||
|
|
||||||
terraform {
|
|
||||||
required_providers {
|
|
||||||
vault = {
|
|
||||||
source = "hashicorp/vault"
|
|
||||||
version = "~> 4.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# =============================================================================
|
|
||||||
# ROOT CA (Offline - used only to sign intermediate)
|
|
||||||
# =============================================================================
|
|
||||||
|
|
||||||
resource "vault_mount" "pki_root_smime" {
|
|
||||||
path = "pki-smime-root"
|
|
||||||
type = "pki"
|
|
||||||
description = "S/MIME Root CA - Offline, used only to sign intermediate"
|
|
||||||
|
|
||||||
# Root CA has a longer lifetime
|
|
||||||
default_lease_ttl_seconds = 315360000 # 10 years
|
|
||||||
max_lease_ttl_seconds = 315360000 # 10 years
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "vault_pki_secret_backend_root_cert" "smime_root" {
|
|
||||||
backend = vault_mount.pki_root_smime.path
|
|
||||||
type = "internal"
|
|
||||||
common_name = "Alignment S/MIME Root CA"
|
|
||||||
ttl = "315360000" # 10 years
|
|
||||||
key_type = "rsa"
|
|
||||||
key_bits = 4096
|
|
||||||
|
|
||||||
organization = "Alignment"
|
|
||||||
country = "US"
|
|
||||||
exclude_cn_from_sans = true
|
|
||||||
}
|
|
||||||
|
|
||||||
# =============================================================================
|
|
||||||
# INTERMEDIATE CA (Online - used to issue user certificates)
|
|
||||||
# =============================================================================
|
|
||||||
|
|
||||||
resource "vault_mount" "pki_smime" {
|
|
||||||
path = "pki-smime"
|
|
||||||
type = "pki"
|
|
||||||
description = "S/MIME Intermediate CA - Issues user certificates"
|
|
||||||
|
|
||||||
# Intermediate has shorter lifetime
|
|
||||||
default_lease_ttl_seconds = 31536000 # 1 year
|
|
||||||
max_lease_ttl_seconds = 94608000 # 3 years
|
|
||||||
}
|
|
||||||
|
|
||||||
# Generate intermediate CSR
|
|
||||||
resource "vault_pki_secret_backend_intermediate_cert_request" "smime_intermediate" {
|
|
||||||
backend = vault_mount.pki_smime.path
|
|
||||||
type = "internal"
|
|
||||||
common_name = "Alignment S/MIME Intermediate CA"
|
|
||||||
key_type = "rsa"
|
|
||||||
key_bits = 4096
|
|
||||||
|
|
||||||
organization = "Alignment"
|
|
||||||
country = "US"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Sign intermediate with root
|
|
||||||
resource "vault_pki_secret_backend_root_sign_intermediate" "smime_intermediate" {
|
|
||||||
backend = vault_mount.pki_root_smime.path
|
|
||||||
common_name = "Alignment S/MIME Intermediate CA"
|
|
||||||
csr = vault_pki_secret_backend_intermediate_cert_request.smime_intermediate.csr
|
|
||||||
ttl = "157680000" # 5 years
|
|
||||||
|
|
||||||
organization = "Alignment"
|
|
||||||
country = "US"
|
|
||||||
|
|
||||||
# Intermediate CA permissions
|
|
||||||
permitted_dns_domains = ["alignment.dev"]
|
|
||||||
}
|
|
||||||
|
|
||||||
# Set the signed intermediate certificate
|
|
||||||
resource "vault_pki_secret_backend_intermediate_set_signed" "smime_intermediate" {
|
|
||||||
backend = vault_mount.pki_smime.path
|
|
||||||
certificate = vault_pki_secret_backend_root_sign_intermediate.smime_intermediate.certificate
|
|
||||||
}
|
|
||||||
|
|
||||||
# =============================================================================
|
|
||||||
# S/MIME CERTIFICATE ROLE
|
|
||||||
# =============================================================================
|
|
||||||
|
|
||||||
resource "vault_pki_secret_backend_role" "smime_user" {
|
|
||||||
backend = vault_mount.pki_smime.path
|
|
||||||
name = "smime-user"
|
|
||||||
|
|
||||||
# Certificate lifetime
|
|
||||||
ttl = 31536000 # 1 year
|
|
||||||
max_ttl = 63072000 # 2 years
|
|
||||||
|
|
||||||
# Domain restrictions
|
|
||||||
allow_any_name = false
|
|
||||||
allowed_domains = ["alignment.dev"]
|
|
||||||
allow_subdomains = false
|
|
||||||
enforce_hostnames = false
|
|
||||||
|
|
||||||
# Allow email addresses
|
|
||||||
allow_bare_domains = true
|
|
||||||
|
|
||||||
# Key configuration
|
|
||||||
key_type = "rsa"
|
|
||||||
key_bits = 4096
|
|
||||||
key_usage = ["DigitalSignature", "KeyEncipherment", "ContentCommitment"]
|
|
||||||
|
|
||||||
# S/MIME specific - Email Protection extended key usage
|
|
||||||
ext_key_usage = ["EmailProtection"]
|
|
||||||
|
|
||||||
# Certificate properties
|
|
||||||
require_cn = true
|
|
||||||
use_csr_common_name = true
|
|
||||||
use_csr_sans = true
|
|
||||||
|
|
||||||
# Organization defaults
|
|
||||||
organization = ["Alignment"]
|
|
||||||
country = ["US"]
|
|
||||||
|
|
||||||
# Don't include SANs automatically
|
|
||||||
allow_ip_sans = false
|
|
||||||
allow_localhost = false
|
|
||||||
allowed_uri_sans = []
|
|
||||||
allowed_other_sans = []
|
|
||||||
|
|
||||||
# Generate certificates (not just sign CSRs)
|
|
||||||
generate_lease = true
|
|
||||||
no_store = false
|
|
||||||
}
|
|
||||||
|
|
||||||
# =============================================================================
|
|
||||||
# POLICY FOR S/MIME CERTIFICATE ISSUANCE
|
|
||||||
# =============================================================================
|
|
||||||
|
|
||||||
resource "vault_policy" "smime_user_issue" {
|
|
||||||
name = "smime-user-issue"
|
|
||||||
policy = <<-EOT
|
|
||||||
# Allow users to issue S/MIME certificates for their own email
|
|
||||||
# Users authenticate via OIDC, and their email claim is used to verify
|
|
||||||
# they can only request certificates for their own email address.
|
|
||||||
|
|
||||||
# Issue S/MIME certificate
|
|
||||||
path "pki-smime/issue/smime-user" {
|
|
||||||
capabilities = ["create", "update"]
|
|
||||||
|
|
||||||
# Restrict to user's own email
|
|
||||||
allowed_parameters = {
|
|
||||||
"common_name" = []
|
|
||||||
"alt_names" = []
|
|
||||||
"ttl" = []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Read certificate chain
|
|
||||||
path "pki-smime/ca/pem" {
|
|
||||||
capabilities = ["read"]
|
|
||||||
}
|
|
||||||
|
|
||||||
path "pki-smime/ca_chain" {
|
|
||||||
capabilities = ["read"]
|
|
||||||
}
|
|
||||||
|
|
||||||
# List own certificates
|
|
||||||
path "pki-smime/certs" {
|
|
||||||
capabilities = ["list"]
|
|
||||||
}
|
|
||||||
EOT
|
|
||||||
}
|
|
||||||
|
|
||||||
# =============================================================================
|
|
||||||
# CRL CONFIGURATION
|
|
||||||
# =============================================================================
|
|
||||||
|
|
||||||
resource "vault_pki_secret_backend_config_urls" "smime_urls" {
|
|
||||||
backend = vault_mount.pki_smime.path
|
|
||||||
|
|
||||||
issuing_certificates = [
|
|
||||||
"https://vault.alignment.dev/v1/pki-smime/ca"
|
|
||||||
]
|
|
||||||
|
|
||||||
crl_distribution_points = [
|
|
||||||
"https://vault.alignment.dev/v1/pki-smime/crl"
|
|
||||||
]
|
|
||||||
|
|
||||||
ocsp_servers = [
|
|
||||||
"https://vault.alignment.dev/v1/pki-smime/ocsp"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
# =============================================================================
|
|
||||||
# OUTPUTS
|
|
||||||
# =============================================================================
|
|
||||||
|
|
||||||
output "smime_ca_chain" {
|
|
||||||
description = "S/MIME CA certificate chain"
|
|
||||||
value = vault_pki_secret_backend_intermediate_set_signed.smime_intermediate.certificate
|
|
||||||
sensitive = false
|
|
||||||
}
|
|
||||||
|
|
||||||
output "smime_issue_path" {
|
|
||||||
description = "Path to issue S/MIME certificates"
|
|
||||||
value = "${vault_mount.pki_smime.path}/issue/${vault_pki_secret_backend_role.smime_user.name}"
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +1,7 @@
|
||||||
# Foundation Infrastructure - Terraform Configuration
|
# Hearth Infrastructure - Terraform Configuration
|
||||||
# RFC 0039: ADR-Compliant Foundation Infrastructure
|
|
||||||
# ADR 0003: CockroachDB Self-Hosted FIPS
|
|
||||||
# ADR 0004: Set It and Forget It Architecture
|
|
||||||
# ADR 0005: Full-Stack Self-Hosting
|
|
||||||
|
|
||||||
terraform {
|
terraform {
|
||||||
required_version = ">= 1.6.0"
|
required_version = ">= 1.5.0"
|
||||||
|
|
||||||
required_providers {
|
required_providers {
|
||||||
aws = {
|
aws = {
|
||||||
|
|
@ -20,16 +16,55 @@ terraform {
|
||||||
source = "hashicorp/helm"
|
source = "hashicorp/helm"
|
||||||
version = "~> 2.12"
|
version = "~> 2.12"
|
||||||
}
|
}
|
||||||
kubectl = {
|
|
||||||
source = "gavinbunney/kubectl"
|
|
||||||
version = "~> 1.14"
|
|
||||||
}
|
|
||||||
tls = {
|
tls = {
|
||||||
source = "hashicorp/tls"
|
source = "hashicorp/tls"
|
||||||
version = "~> 4.0"
|
version = "~> 4.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Backend configuration - use S3 for state storage
|
backend "s3" {
|
||||||
# Configure in environments/production/backend.tf
|
bucket = "hearth-terraform-state-181640953119"
|
||||||
|
key = "hearth/terraform.tfstate"
|
||||||
|
region = "us-east-1"
|
||||||
|
dynamodb_table = "hearth-terraform-locks"
|
||||||
|
encrypt = true
|
||||||
|
profile = "hearth"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
provider "aws" {
|
||||||
|
region = var.aws_region
|
||||||
|
profile = "hearth"
|
||||||
|
|
||||||
|
default_tags {
|
||||||
|
tags = {
|
||||||
|
Project = var.project_name
|
||||||
|
Environment = var.environment
|
||||||
|
ManagedBy = "terraform"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
provider "kubernetes" {
|
||||||
|
host = module.eks.cluster_endpoint
|
||||||
|
cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data)
|
||||||
|
|
||||||
|
exec {
|
||||||
|
api_version = "client.authentication.k8s.io/v1beta1"
|
||||||
|
command = "aws"
|
||||||
|
args = ["eks", "get-token", "--cluster-name", module.eks.cluster_name, "--profile", "hearth"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
provider "helm" {
|
||||||
|
kubernetes {
|
||||||
|
host = module.eks.cluster_endpoint
|
||||||
|
cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data)
|
||||||
|
|
||||||
|
exec {
|
||||||
|
api_version = "client.authentication.k8s.io/v1beta1"
|
||||||
|
command = "aws"
|
||||||
|
args = ["eks", "get-token", "--cluster-name", module.eks.cluster_name, "--profile", "hearth"]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue