Files
quixos/tofu/main.tf
T
Timothy J. Aveni 9bcf65d9b1 Add tofu goodies
2026-06-17 21:41:15 -07:00

210 lines
5.4 KiB
Terraform

data "aws_vpc" "default" {
count = var.vpc_id == null ? 1 : 0
default = true
}
data "aws_subnets" "default" {
count = var.subnet_id == null ? 1 : 0
filter {
name = "vpc-id"
values = [local.vpc_id]
}
}
data "aws_subnet" "selected" {
id = local.subnet_id
}
data "aws_ami" "nixos" {
count = var.nixos_ami_id == null ? 1 : 0
most_recent = true
owners = var.nixos_ami_owners
filter {
name = "name"
values = [var.nixos_ami_name_pattern]
}
filter {
name = "architecture"
values = ["arm64"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
resource "random_id" "deployment" {
byte_length = 4
}
locals {
vpc_id = var.vpc_id == null ? data.aws_vpc.default[0].id : var.vpc_id
subnet_id = var.subnet_id == null ? data.aws_subnets.default[0].ids[0] : var.subnet_id
nixos_ami_id = var.nixos_ami_id == null ? data.aws_ami.nixos[0].id : var.nixos_ami_id
domain = trimsuffix(var.subdomain, ".")
resource_name = "${var.name}-${random_id.deployment.hex}"
persist_device_id = replace(aws_ebs_volume.persist.id, "-", "")
persist_device = "/dev/disk/by-id/nvme-Amazon_Elastic_Block_Store_${local.persist_device_id}"
quixos_flake_uri = "git+${var.quixos_repo_url}?${var.quixos_ref_is_rev ? "rev" : "ref"}=${urlencode(var.quixos_ref)}"
ssh_keys = compact([var.ssh_public_key])
tags = {
Name = local.resource_name
Deployment = random_id.deployment.hex
Project = var.name
}
}
resource "random_password" "control_secret" {
length = 48
special = false
}
resource "random_password" "state_context_secret" {
length = 48
special = false
}
resource "aws_iam_role" "instance" {
name = "${local.resource_name}-instance"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "ec2.amazonaws.com"
}
}
]
})
}
resource "aws_iam_role_policy_attachment" "ssm" {
role = aws_iam_role.instance.name
policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}
resource "aws_iam_instance_profile" "instance" {
name = "${local.resource_name}-instance"
role = aws_iam_role.instance.name
}
resource "aws_security_group" "instance" {
name = "${local.resource_name}-instance"
description = "Quixos instance ingress"
vpc_id = local.vpc_id
ingress {
description = "HTTP"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "HTTPS"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
dynamic "ingress" {
for_each = var.enable_ssh ? [1] : []
content {
description = "SSH"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = length(var.ssh_allowed_cidrs) == 0 ? ["0.0.0.0/0"] : var.ssh_allowed_cidrs
}
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_key_pair" "admin" {
count = var.ssh_public_key == null ? 0 : 1
key_name = "${local.resource_name}-admin"
public_key = var.ssh_public_key
}
resource "aws_instance" "host" {
ami = local.nixos_ami_id
instance_type = var.instance_type
subnet_id = local.subnet_id
vpc_security_group_ids = [aws_security_group.instance.id]
iam_instance_profile = aws_iam_instance_profile.instance.name
associate_public_ip_address = true
key_name = var.ssh_public_key == null ? null : aws_key_pair.admin[0].key_name
user_data_replace_on_change = true
user_data = templatefile("${path.module}/user-data.sh.tftpl", {
admin_user = var.admin_user
domain = local.domain
enable_ssh = var.enable_ssh
force_package_tree_ref_on_boot = var.force_package_tree_ref_on_boot
package_tree_ref = var.package_tree_ref
package_tree_repo_url = var.package_tree_repo_url
persist_device = local.persist_device
quixos_flake_uri = local.quixos_flake_uri
ssh_authorized_keys = jsonencode(local.ssh_keys)
control_secret = random_password.control_secret.result
state_context_secret = random_password.state_context_secret.result
})
root_block_device {
volume_size = var.root_volume_size_gb
volume_type = "gp3"
}
tags = local.tags
}
resource "aws_ebs_volume" "persist" {
availability_zone = data.aws_subnet.selected.availability_zone
size = var.persist_volume_size_gb
type = "gp3"
tags = merge(local.tags, {
Name = "${local.resource_name}-persist"
})
}
resource "aws_volume_attachment" "persist" {
device_name = "/dev/sdf"
volume_id = aws_ebs_volume.persist.id
instance_id = aws_instance.host.id
}
resource "aws_eip" "host" {
domain = "vpc"
tags = local.tags
}
resource "aws_eip_association" "host" {
instance_id = aws_instance.host.id
allocation_id = aws_eip.host.id
}
resource "aws_route53_record" "host" {
zone_id = var.route53_zone_id
name = local.domain
type = "A"
ttl = 60
records = [aws_eip.host.public_ip]
}