Skip to content
/ odin Public

This is the Opentofu code used to build my docker compose powered webserver on an AWS SPOT instance.

License

Notifications You must be signed in to change notification settings

bocan/odin

Repository files navigation

About

This Tofu / Terraform repo builds an a single AWS instance for my containerised platform running in a single Spot instance. AWS can stop it, delete it, whatever - because the user_data sets everything up from scratch and any important data is kept on an external volume.

It basically looks like this:

  • A dedicated VPC, and EC2 Spot instance spun up with Terraform / (OpenTofu) running a Debian Sid AMI that I've encrypted with a customer managed key.

  • The root volume is small (8G) and remains mostly untouched with only enough changes to the root volume to enable it to reboot without needing any configuration changes.

  • All important persistent data and configuration lives on a separate encrypted volume mounted at /volume. This terraform project connects the instance to it, but doesn't manage it directly.

  • Everything important is running as a Docker container via Docker Compose. There are 5 major Docker containers that need to remain up:

    • certbot: Mostly sleeping for 12 hours at a time but then checking for certs that need to be renewed
    • nginx: Powers all the static and tool sites.
    • php: Has the same mounts as nginx and runs any PHP needed. I self compile this as PHP's a monstrocity.
    • mariadb: Powers any needed mysql/mariadb databases.
    • gitea: A place I intend to move most of my private repos into. Kind of like Gitlab, but not as bloated with crap.
  • I also have a fully monitoring / metrics / observability stack running:

    • prometheus: The metrics engine.
    • grafana : A virtual pane of glass to view all the metrics.
    • cadvisor: Analyzes resource usage and performance characteristics of running containers.
    • node-exporter : Scrapes and exports my instance's metrics.
  • All Powering These Sites:

    • My home page, a static site built every 5 minutes from Git via Hugo.
    • A Wordpress site powering a personal archive. (nginx and php)
    • bocan.dev - A 1 page CV site. (just nginx)
    • cfunder.me - A personal URL shortener. (nginx and php)
    • My personal blog (nginx and hugo), and tooling hidden underneath:
    • My business site (just nginx) - but soon to be my business blog (nginx and hugo)
    • My family tree site (just nginx)
  • There are 3 crontab jobs executing commands inside the docker containers:

    • Every 15 minutes, exec into php and update my TTRSS site to get check RSS feeds.
    • Every 31 minutes, exec into php and run the Nextcloud cron processing.
    • Every 5 minutes, use Git to pull all configuration from Github, then exec into the Hugo container and generate the static blogs.
  • Issues I still need to fix:

    • I'd like to swap the AMI and disk encryption to use a CMK.
    • The Github repo that controls all of it stores the web certificates so I can't make it public yet. I need to split that piece out.
    • The big external volume only has 1 snapshot and it's not automated yet.

Requirements

Name Version
terraform >= 1.8.0
aws >= 5.0

Providers

Name Version
aws >= 5.0

Modules

Name Source Version
ec2_instance terraform-aws-modules/ec2-instance/aws 5.7.0
ec2_instance_freyja terraform-aws-modules/ec2-instance/aws 5.7.0
kms terraform-aws-modules/kms/aws 3.1.0
security_group terraform-aws-modules/security-group/aws 5.2.0
security_group_freyja terraform-aws-modules/security-group/aws 5.2.0
vpc terraform-aws-modules/vpc/aws 5.13.0

Resources

Name Type
aws_ami_copy.debian_encrypted_ami resource
aws_dlm_lifecycle_policy.odin_dlm_policy resource
aws_dlm_lifecycle_policy.odin_dlm_policy_monthly resource
aws_eip.bar resource
aws_eip.foo resource
aws_iam_instance_profile.ec2_profile resource
aws_iam_policy.ec2_policy resource
aws_iam_role.dlm_lifecycle_role resource
aws_iam_role.ec2_role resource
aws_iam_role_policy.dlm_lifecycle resource
aws_iam_role_policy_attachment.custom resource
aws_route53_record.mailserverA resource
aws_volume_attachment.this resource
aws_volume_attachment.this2 resource
aws_ami.debian data source
aws_ami.encrypted-ami data source
aws_availability_zones.available data source
aws_caller_identity.current data source
aws_ebs_volume.ebs_volume data source
aws_ebs_volume.ebs_volume_freyja data source
aws_iam_policy_document.assume_role data source
aws_iam_policy_document.dlm_lifecycle data source

Inputs

Name Description Type Default Required
ami_override The Debian Sid AMI can be updated too fast. Set this if you don't want to update it. string null no
github_token The github token I use to let Hugo write back to Github. string n/a yes
github_user The github user I use to let Hugo write back to Github. string n/a yes
passphrase Password to encrypt state string n/a yes
users_for_key The users or sts roles to give access to the customer managed key list(string) null no

Outputs

Name Description
ami_details n/a
cgw_arns List of ARNs of Customer Gateway
cgw_ids List of IDs of Customer Gateway
database_internet_gateway_route_id ID of the database internet gateway route
database_ipv6_egress_route_id ID of the database IPv6 egress route
database_nat_gateway_route_ids List of IDs of the database nat gateway route
database_network_acl_arn ARN of the database network ACL
database_network_acl_id ID of the database network ACL
database_route_table_association_ids List of IDs of the database route table association
database_route_table_ids List of IDs of database route tables
database_subnet_arns List of ARNs of database subnets
database_subnet_group ID of database subnet group
database_subnet_group_name Name of database subnet group
database_subnets List of IDs of database subnets
database_subnets_cidr_blocks List of cidr_blocks of database subnets
database_subnets_ipv6_cidr_blocks List of IPv6 cidr_blocks of database subnets in an IPv6 enabled VPC
default_network_acl_id The ID of the default network ACL
default_route_table_id The ID of the default route table
default_security_group_id The ID of the security group created by default on VPC creation
default_vpc_arn The ARN of the Default VPC
default_vpc_cidr_block The CIDR block of the Default VPC
default_vpc_default_network_acl_id The ID of the default network ACL of the Default VPC
default_vpc_default_route_table_id The ID of the default route table of the Default VPC
default_vpc_default_security_group_id The ID of the security group created by default on Default VPC creation
default_vpc_enable_dns_hostnames Whether or not the Default VPC has DNS hostname support
default_vpc_enable_dns_support Whether or not the Default VPC has DNS support
default_vpc_id The ID of the Default VPC
default_vpc_instance_tenancy Tenancy of instances spin up within Default VPC
default_vpc_main_route_table_id The ID of the main route table associated with the Default VPC
dhcp_options_id The ID of the DHCP options
ec2_instance_arn The ARN of the instance
ec2_instance_availability_zone The availability zone of the created instance
ec2_instance_capacity_reservation_specification Capacity reservation specification of the instance
ec2_instance_ebs_block_device EBS block device information
ec2_instance_ephemeral_block_device Ephemeral block device information
ec2_instance_iam_instance_profile_arn ARN assigned by AWS to the instance profile
ec2_instance_iam_instance_profile_id Instance profile's ID
ec2_instance_iam_instance_profile_unique Stable and unique string identifying the IAM instance profile
ec2_instance_iam_role_arn The Amazon Resource Name (ARN) specifying the IAM role
ec2_instance_iam_role_name The name of the IAM role
ec2_instance_iam_role_unique_id Stable and unique string identifying the IAM role
ec2_instance_id The ID of the instance
ec2_instance_instance_state The state of the instance. One of: pending, running, shutting-down, terminated, stopping, stopped
ec2_instance_primary_network_interface_id The ID of the instance's primary network interface
ec2_instance_private_dns The private DNS name assigned to the instance. Can only be used inside the Amazon EC2, and only available if you've enabled DNS hostnames for your VPC
ec2_instance_public_dns The public DNS name assigned to the instance. For EC2-VPC, this is only available if you've enabled DNS hostnames for your VPC
ec2_instance_public_ip The public IP address assigned to the instance, if applicable. NOTE: If you are using an aws_eip with your instance, you should refer to the EIP's address directly and not use public_ip as this field will change after the EIP is attached
ec2_instance_root_block_device Root block device information
ec2_instance_tags_all A map of tags assigned to the resource, including those inherited from the provider default_tags configuration block
egress_only_internet_gateway_id The ID of the egress only Internet Gateway
elasticache_network_acl_arn ARN of the elasticache network ACL
elasticache_network_acl_id ID of the elasticache network ACL
elasticache_route_table_association_ids List of IDs of the elasticache route table association
elasticache_route_table_ids List of IDs of elasticache route tables
elasticache_subnet_arns List of ARNs of elasticache subnets
elasticache_subnet_group ID of elasticache subnet group
elasticache_subnet_group_name Name of elasticache subnet group
elasticache_subnets List of IDs of elasticache subnets
elasticache_subnets_cidr_blocks List of cidr_blocks of elasticache subnets
elasticache_subnets_ipv6_cidr_blocks List of IPv6 cidr_blocks of elasticache subnets in an IPv6 enabled VPC
igw_arn The ARN of the Internet Gateway
igw_id The ID of the Internet Gateway
intra_network_acl_arn ARN of the intra network ACL
intra_network_acl_id ID of the intra network ACL
intra_route_table_association_ids List of IDs of the intra route table association
intra_route_table_ids List of IDs of intra route tables
intra_subnet_arns List of ARNs of intra subnets
intra_subnets List of IDs of intra subnets
intra_subnets_cidr_blocks List of cidr_blocks of intra subnets
intra_subnets_ipv6_cidr_blocks List of IPv6 cidr_blocks of intra subnets in an IPv6 enabled VPC
nat_ids List of allocation ID of Elastic IPs created for AWS NAT Gateway
nat_public_ips List of public Elastic IPs created for AWS NAT Gateway
natgw_ids List of NAT Gateway IDs
outpost_network_acl_arn ARN of the outpost network ACL
outpost_network_acl_id ID of the outpost network ACL
outpost_subnet_arns List of ARNs of outpost subnets
outpost_subnets List of IDs of outpost subnets
outpost_subnets_cidr_blocks List of cidr_blocks of outpost subnets
outpost_subnets_ipv6_cidr_blocks List of IPv6 cidr_blocks of outpost subnets in an IPv6 enabled VPC
private_ipv6_egress_route_ids List of IDs of the ipv6 egress route
private_nat_gateway_route_ids List of IDs of the private nat gateway route
private_network_acl_arn ARN of the private network ACL
private_network_acl_id ID of the private network ACL
private_route_table_association_ids List of IDs of the private route table association
private_route_table_ids List of IDs of private route tables
private_subnet_arns List of ARNs of private subnets
private_subnets List of IDs of private subnets
private_subnets_cidr_blocks List of cidr_blocks of private subnets
private_subnets_ipv6_cidr_blocks List of IPv6 cidr_blocks of private subnets in an IPv6 enabled VPC
ptr_record public dns
public_internet_gateway_ipv6_route_id ID of the IPv6 internet gateway route
public_internet_gateway_route_id ID of the internet gateway route
public_network_acl_arn ARN of the public network ACL
public_network_acl_id ID of the public network ACL
public_route_table_association_ids List of IDs of the public route table association
public_route_table_ids List of IDs of public route tables
public_subnet_arns List of ARNs of public subnets
public_subnets List of IDs of public subnets
public_subnets_cidr_blocks List of cidr_blocks of public subnets
public_subnets_ipv6_cidr_blocks List of IPv6 cidr_blocks of public subnets in an IPv6 enabled VPC
redshift_network_acl_arn ARN of the redshift network ACL
redshift_network_acl_id ID of the redshift network ACL
redshift_public_route_table_association_ids List of IDs of the public redshift route table association
redshift_route_table_association_ids List of IDs of the redshift route table association
redshift_route_table_ids List of IDs of redshift route tables
redshift_subnet_arns List of ARNs of redshift subnets
redshift_subnet_group ID of redshift subnet group
redshift_subnets List of IDs of redshift subnets
redshift_subnets_cidr_blocks List of cidr_blocks of redshift subnets
redshift_subnets_ipv6_cidr_blocks List of IPv6 cidr_blocks of redshift subnets in an IPv6 enabled VPC
this_customer_gateway Map of Customer Gateway attributes
vgw_arn The ARN of the VPN Gateway
vgw_id The ID of the VPN Gateway
vpc_arn The ARN of the VPC
vpc_cidr_block The CIDR block of the VPC
vpc_enable_dns_hostnames Whether or not the VPC has DNS hostname support
vpc_enable_dns_support Whether or not the VPC has DNS support
vpc_flow_log_cloudwatch_iam_role_arn The ARN of the IAM role used when pushing logs to Cloudwatch log group
vpc_flow_log_destination_arn The ARN of the destination for VPC Flow Logs
vpc_flow_log_destination_type The type of the destination for VPC Flow Logs
vpc_flow_log_id The ID of the Flow Log resource
vpc_id The ID of the VPC
vpc_instance_tenancy Tenancy of instances spin up within VPC
vpc_ipv6_association_id The association ID for the IPv6 CIDR block
vpc_ipv6_cidr_block The IPv6 CIDR block
vpc_main_route_table_id The ID of the main route table associated with this VPC
vpc_owner_id The ID of the AWS account that owns the VPC
vpc_secondary_cidr_blocks List of secondary CIDR blocks of the VPC

About

This is the Opentofu code used to build my docker compose powered webserver on an AWS SPOT instance.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published