diff --git a/.gitignore b/.gitignore index a977916..38210c5 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ .vagrant/ + +.terraform/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..092eb02 --- /dev/null +++ b/README.md @@ -0,0 +1,10 @@ +# Supernodes + +## IP Addressing + +- Assign a single IPv4 address per supernode + - management IP to reach the machine + - NAT IP to route client traffic + - assigned from our `/24` aggregate +- Assign a `/64` loopback prefix for all supernodes in a domain + - each supernode gets one IP from this prefix diff --git a/terraform/.terraform.lock.hcl b/terraform/.terraform.lock.hcl new file mode 100644 index 0000000..d79a427 --- /dev/null +++ b/terraform/.terraform.lock.hcl @@ -0,0 +1,37 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/e-breuninger/netbox" { + version = "3.7.6" + constraints = "3.7.6" + hashes = [ + "h1:OLsYUpow9TBdKRvgqheB/5n2N5VCbF3QyXRNxuQZoqA=", + "zh:2b48a6678e4c99f6dab3650a3e7d8d34498c40b85838f998f7c24089e7e8922d", + "zh:2d77118e2e96bf31d5a58a4a8000819341442c6b8fe2994eab5094a245f34d46", + "zh:368c5f626cb6e288a840ffbf06a9b6458187d9f2dba1eae0e5c6b3f83abf0f7b", + "zh:51decc9df47e0d06b28082a8b43887db37c983754a0bab02f57f7dd22f2c0621", + "zh:73e428c809e6c335478357eca9d69853d1066fa8050c2d46a0829482741973c3", + "zh:9ae0e400fd41b38d9799b3e4b88338c0f0c4466d2195a4b20d1c668bca536bdc", + "zh:a1e53a8464904c020225e349ec0ccaf6452b1f7ea2c0bf1328437a922b672dfc", + "zh:e2d0071cafd11e915061528904b8192dc6df87151d0f6329fda820e3cbdd0bae", + ] +} + +provider "registry.terraform.io/hashicorp/null" { + version = "3.2.2" + hashes = [ + "h1:IMVAUHKoydFrlPrl9OzasDnw/8ntZFerCC9iXw1rXQY=", + "zh:3248aae6a2198f3ec8394218d05bd5e42be59f43a3a7c0b71c66ec0df08b69e7", + "zh:32b1aaa1c3013d33c245493f4a65465eab9436b454d250102729321a44c8ab9a", + "zh:38eff7e470acb48f66380a73a5c7cdd76cc9b9c9ba9a7249c7991488abe22fe3", + "zh:4c2f1faee67af104f5f9e711c4574ff4d298afaa8a420680b0cb55d7bbc65606", + "zh:544b33b757c0b954dbb87db83a5ad921edd61f02f1dc86c6186a5ea86465b546", + "zh:696cf785090e1e8cf1587499516b0494f47413b43cb99877ad97f5d0de3dc539", + "zh:6e301f34757b5d265ae44467d95306d61bef5e41930be1365f5a8dcf80f59452", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:913a929070c819e59e94bb37a2a253c228f83921136ff4a7aa1a178c7cce5422", + "zh:aa9015926cd152425dbf86d1abdbc74bfe0e1ba3d26b3db35051d7b9ca9f72ae", + "zh:bb04798b016e1e1d49bcc76d62c53b56c88c63d6f2dfe38821afef17c416a0e1", + "zh:c23084e1b23577de22603cff752e59128d83cfecc2e6819edadd8cf7a10af11e", + ] +} diff --git a/terraform/main.tf b/terraform/main.tf index a8618c9..77e1252 100644 --- a/terraform/main.tf +++ b/terraform/main.tf @@ -1,2 +1,14 @@ resource "null_resource" "test" { } + +module "supernode" { + count = var.supernode_count + + source = "./modules/supernode" + + supernode_name = "${var.domain_name}_${count.index}" + + prefix_ipv4_id = data.netbox_prefix.primary_ipv4.id + prefix_ipv6_id = netbox_available_prefix.domain_ipv6.id + loopback_prefix_ipv6_id = netbox_prefix.loopback_ipv6.id +} diff --git a/terraform/modules/supernode/main.tf b/terraform/modules/supernode/main.tf new file mode 100644 index 0000000..9b7f4b3 --- /dev/null +++ b/terraform/modules/supernode/main.tf @@ -0,0 +1,7 @@ +terraform { + required_providers { + netbox = { + source = "e-breuninger/netbox" + } + } +} diff --git a/terraform/modules/supernode/primary-ipv4.tf b/terraform/modules/supernode/primary-ipv4.tf new file mode 100644 index 0000000..e04a356 --- /dev/null +++ b/terraform/modules/supernode/primary-ipv4.tf @@ -0,0 +1,20 @@ +resource "netbox_available_prefix" "primary_ipv4" { + description = "Primary Address ${var.supernode_name}" + status = "active" + + parent_prefix_id = var.prefix_ipv4_id + prefix_length = 32 + + tags = toset(var.tags) +} + +resource "netbox_available_ip_address" "primary_ipv4" { + status = "active" + + description = "Primary Address ${var.supernode_name}" + + prefix_id = netbox_available_prefix.primary_ipv4.id + // TODO: set interface_id + + tags = toset(var.tags) +} diff --git a/terraform/modules/supernode/primary-ipv6.tf b/terraform/modules/supernode/primary-ipv6.tf new file mode 100644 index 0000000..67a1fdb --- /dev/null +++ b/terraform/modules/supernode/primary-ipv6.tf @@ -0,0 +1,20 @@ +resource "netbox_available_prefix" "primary_ipv6" { + description = "Primary Address ${var.supernode_name}" + status = "active" + + parent_prefix_id = var.loopback_prefix_ipv6_id + prefix_length = 128 + + tags = toset(var.tags) +} + +resource "netbox_available_ip_address" "primary_ipv6" { + status = "active" + + description = "Primary Address ${var.supernode_name}" + + prefix_id = netbox_available_prefix.primary_ipv6.id + // TODO: set interface_id + + tags = toset(var.tags) +} diff --git a/terraform/modules/supernode/variables.tf b/terraform/modules/supernode/variables.tf new file mode 100644 index 0000000..4c6a319 --- /dev/null +++ b/terraform/modules/supernode/variables.tf @@ -0,0 +1,25 @@ +variable "supernode_name" { + type = string + description = "Name of the Supernode" +} + +variable "tags" { + type = list(string) + description = "Tags for the resources" + default = [] +} + +variable "prefix_ipv4_id" { + type = string + description = "ID of the Supernode IPv4 prefix" +} + +variable "prefix_ipv6_id" { + type = string + description = "ID of the Supernode IPv6 prefix" +} + +variable "loopback_prefix_ipv6_id" { + type = string + description = "ID of the Loopback Supernode IPv6 prefix" +} diff --git a/terraform/primary-prefixes.tf b/terraform/primary-prefixes.tf new file mode 100644 index 0000000..f58bcf3 --- /dev/null +++ b/terraform/primary-prefixes.tf @@ -0,0 +1,24 @@ +data "netbox_prefix" "primary_ipv4" { + prefix = var.primary_prefix_ipv4 +} + +data "netbox_prefix" "primary_ipv6" { + prefix = var.primary_prefix_ipv6 +} + +resource "netbox_available_prefix" "domain_ipv6" { + description = "Supernode IPv6 addresses ${var.domain_name}" + prefix_length = 56 + status = "reserved" + parent_prefix_id = data.netbox_prefix.primary_ipv6.id + + tags = toset(var.tags) +} + +resource "netbox_prefix" "loopback_ipv6" { + prefix = cidrsubnet(netbox_available_prefix.domain_ipv6.prefix, 8, 0) + description = "Supernode IPv6 loopback addresses ${var.domain_name}" + status = "reserved" + + tags = toset(var.tags) +} diff --git a/terraform/providers.tf b/terraform/providers.tf new file mode 100644 index 0000000..e8344e7 --- /dev/null +++ b/terraform/providers.tf @@ -0,0 +1,12 @@ +terraform { + required_providers { + netbox = { + source = "e-breuninger/netbox" + version = "3.7.6" + } + } +} + +provider "netbox" { + server_url = "https://netbox.freifunk-duesseldorf.de" +} diff --git a/terraform/variables.tf b/terraform/variables.tf new file mode 100644 index 0000000..bb24c17 --- /dev/null +++ b/terraform/variables.tf @@ -0,0 +1,29 @@ +variable "domain_name" { + type = string + description = "Name of the supernode domain" + default = "dev" +} + +variable "tags" { + type = list(string) + description = "Tags for the resources" + default = [] +} + +variable "supernode_count" { + type = number + description = "Number of supernodes for this domain" + default = 2 +} + +variable "primary_prefix_ipv4" { + type = string + description = "Prefix to issue primary IPv4 addresses from" + default = "45.151.166.0/24" +} + +variable "primary_prefix_ipv6" { + type = string + description = "Prefix to issue primary IPv6 addresses from" + default = "2001:678:b7c::/48" +}