first commit

This commit is contained in:
2026-08-09 19:52:19 -04:00
commit f12fb4d7a1
25 changed files with 597 additions and 0 deletions
+27
View File
@@ -0,0 +1,27 @@
# Optional production-style path
This directory provisions one encrypted Ubuntu EC2 host with a deliberately
small network surface. It is a scaffold for the documented cloud path; the
local k3d path remains the primary, cost-free portfolio demo.
The AWS account, region, AMI, SSH key pair, and administrator CIDR are inputs,
not repository values. Do not commit a real `terraform.tfvars` file or private
keys. The security group intentionally exposes SSH and the Kubernetes API only
to `admin_cidr`; add any public application ports explicitly when needed.
Example workflow:
```bash
cp terraform.tfvars.example terraform.tfvars
# Edit every replace-* value and set admin_cidr to your current IP /32.
terraform init
terraform validate
terraform plan
terraform apply
terraform output -raw public_ip
```
Then run `ansible/bootstrap-k3s.yml` against the output IP. `terraform destroy`
removes the lab resources when finished. This path is not required for the
portfolio demo and is not invoked by CI.
+88
View File
@@ -0,0 +1,88 @@
data "aws_availability_zones" "available" {
state = "available"
}
locals {
availability_zone = coalesce(var.availability_zone, data.aws_availability_zones.available.names[0])
}
resource "aws_vpc" "cluster" {
cidr_block = "10.42.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
tags = { Name = "k8s-security-baseline" }
}
resource "aws_subnet" "cluster" {
vpc_id = aws_vpc.cluster.id
cidr_block = "10.42.1.0/24"
availability_zone = local.availability_zone
tags = { Name = "k8s-security-baseline" }
}
resource "aws_internet_gateway" "cluster" {
vpc_id = aws_vpc.cluster.id
}
resource "aws_route_table" "cluster" {
vpc_id = aws_vpc.cluster.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.cluster.id
}
}
resource "aws_route_table_association" "cluster" {
subnet_id = aws_subnet.cluster.id
route_table_id = aws_route_table.cluster.id
}
resource "aws_security_group" "cluster" {
name = "k8s-security-baseline"
description = "Minimal access for the optional single-node K3s lab host"
vpc_id = aws_vpc.cluster.id
ingress {
description = "SSH from the administrator CIDR"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = [var.admin_cidr]
}
ingress {
description = "Kubernetes API from the administrator CIDR"
from_port = 6443
to_port = 6443
protocol = "tcp"
cidr_blocks = [var.admin_cidr]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_instance" "k3s" {
ami = var.ami_id
instance_type = var.instance_type
subnet_id = aws_subnet.cluster.id
vpc_security_group_ids = [aws_security_group.cluster.id]
key_name = var.ssh_key_name
associate_public_ip_address = true
root_block_device {
volume_size = 30
volume_type = "gp3"
encrypted = true
}
tags = { Name = "k8s-security-baseline" }
}
+10
View File
@@ -0,0 +1,10 @@
output "public_ip" {
description = "Public IP to place in the Ansible inventory."
value = aws_instance.k3s.public_ip
}
output "ssh_command" {
description = "SSH command for initial connectivity testing."
value = "ssh ubuntu@${aws_instance.k3s.public_ip}"
}
@@ -0,0 +1,7 @@
aws_region = "us-east-1"
availability_zone = null
instance_type = "t3.medium"
ssh_key_name = "replace-with-existing-key-pair"
admin_cidr = "203.0.113.10/32"
ami_id = "replace-with-ubuntu-22.04-ami-for-your-region"
+33
View File
@@ -0,0 +1,33 @@
variable "aws_region" {
description = "AWS region for the optional production-style K3s host."
type = string
default = "us-east-1"
}
variable "availability_zone" {
description = "Availability zone for the subnet. Leave null to use the first AZ."
type = string
default = null
}
variable "instance_type" {
description = "EC2 instance type for the lab node."
type = string
default = "t3.medium"
}
variable "ssh_key_name" {
description = "Existing EC2 key pair name used for Ansible bootstrap."
type = string
}
variable "admin_cidr" {
description = "CIDR allowed to SSH to the node; restrict this to your admin IP."
type = string
}
variable "ami_id" {
description = "Ubuntu 22.04 LTS AMI ID for the selected region."
type = string
}
+15
View File
@@ -0,0 +1,15 @@
terraform {
required_version = ">= 1.6.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = var.aws_region
}