diff --git a/install.sh b/install.sh index 08d64e2..6ce3fe5 100755 --- a/install.sh +++ b/install.sh @@ -1,6 +1,21 @@ #!/usr/bin/env bash set -euo pipefail +## +# Source Code + +# We store all initial configs in the /srv location +cd /srv + +# Clone if not yet cloned +if [ ! -d .git ]; then + git clone https://code.tjo.space/tjo-cloud/ingress.git . +else + git pull +fi + +## +# Metadata SERVICE_NAME="ingress.tjo.cloud" SERVICE_VERSION="$(git describe --tags --always --dirty)" CLOUD_REGION="$(hostname -s)" @@ -26,11 +41,11 @@ mkdir -p /etc/apt/keyrings/ wget -q -O - https://apt.grafana.com/gpg.key | gpg --dearmor | tee /etc/apt/keyrings/grafana.gpg >/dev/null echo "deb [signed-by=/etc/apt/keyrings/grafana.gpg] https://apt.grafana.com stable main" | tee /etc/apt/sources.list.d/grafana.list apt update -y -apt get install -y alloy +apt install -y alloy ## # Copy Sysmtemd service/units -cp -r root/etc/systemd/* / +#cp -r root/etc/systemd/* / ## # Ensure services are enabled @@ -55,10 +70,10 @@ systemctl reload alloy ## # Configure NGINX -cp -r root/etc/nginx/* /etc/nginx/ +#cp -r root/etc/nginx/* /etc/nginx/ systemctl reload nginx ## # Configure Webhook -cp -r root/etc/webhook/* /etc/webhook/ -systemctl reload webhook +#cp -r root/etc/webhook/* /etc/webhook/ +systemctl restart webhook diff --git a/justfile b/justfile index 88b5efe..714d3aa 100644 --- a/justfile +++ b/justfile @@ -10,6 +10,10 @@ lint: @tofu fmt -check -recursive . @tflint --recursive +format: + @tofu fmt -recursive . + @tflint --recursive + deploy: #!/usr/bin/env sh cd {{justfile_directory()}}/terraform @@ -20,3 +24,45 @@ destroy: #!/usr/bin/env sh cd {{justfile_directory()}}/terraform tofu destroy + +# Create a list of blocked IP ranges. Traffic we don't want. +ingress-blocked-list: + #!/usr/bin/env bash + GOOGLE_BOT_IPV4=$(curl -s https://raw.githubusercontent.com/lord-alfred/ipranges/main/googlebot/ipv4_merged.txt) + GOOGLE_BOT_IPV6=$(curl -s https://raw.githubusercontent.com/lord-alfred/ipranges/main/googlebot/ipv6_merged.txt) + echo "# GOOGLE_BOT IPV4 $(echo $GOOGLE_BOT_IPV4 | wc -w)" + echo "# GOOGLE_BOT IPV6 $(echo $GOOGLE_BOT_IPV6 | wc -w)" + + BING_BOT_IPV4=$(curl -s https://raw.githubusercontent.com/lord-alfred/ipranges/main/bing/ipv4_merged.txt) + echo "# BING_BOT IPV4 $(echo $BING_BOT_IPV4 | wc -w)" + + OPENAI_IPV4=$(curl -s https://raw.githubusercontent.com/lord-alfred/ipranges/main/openai/ipv4_merged.txt) + echo "# OPENAI IPV4 $(echo $OPENAI_IPV4 | wc -w)" + + FACEBOOK_IPV4=$(curl -s https://raw.githubusercontent.com/lord-alfred/ipranges/main/facebook/ipv4_merged.txt) + FACEBOOK_IPV6=$(curl -s https://raw.githubusercontent.com/lord-alfred/ipranges/main/facebook/ipv6_merged.txt) + echo "# FACEBOOK IPV4 $(echo $FACEBOOK_IPV4 | wc -w)" + echo "# FACEBOOK IPV6 $(echo $FACEBOOK_IPV6 | wc -w)" + + IP_RANGES=$(echo -e "$GOOGLE_BOT_IPV4\n$GOOGLE_BOT_IPV6\n$BING_BOT_IPV4\n$BING_BOT_IPV6\n$OPENAI_IPV4\n$FACEBOOK_IPV4\n$FACEBOOK_IPV6" | sort | uniq) + echo "#!!DO NOT EDIT!! Generated by using just ingress-blocked-list command." > root/etc/nginx/partials/blocked.conf + for ip in $IP_RANGES; do + echo "deny $ip;" >> root/etc/nginx/partials/blocked.conf + done + +provision: + #!/usr/bin/env sh + set -eou pipefail + + pushd {{justfile_directory()}}/terraform > /dev/null + NODES=$(tofu output -json | jq -r '.nodes.value[]') + popd > /dev/null + + for NODE in $NODES + do + echo "Provisioning node ${NODE}" + + ssh ubuntu@${NODE} 'sudo rm -rf /srv && sudo mkdir /srv && sudo chown ubuntu:ubuntu /srv' + + cat install.sh | ssh ubuntu@${NODE} 'sudo bash -s' + done diff --git a/root/etc/nginx/nginx.conf b/root/etc/nginx/nginx.conf new file mode 100644 index 0000000..bfa82d7 --- /dev/null +++ b/root/etc/nginx/nginx.conf @@ -0,0 +1,91 @@ +user www-data; +worker_processes auto; +pid /run/nginx.pid; +error_log /var/log/nginx/error.log; +include /etc/nginx/modules-enabled/*.conf; + +events { + worker_connections 768; +} + +error_log /dev/stderr error; + +stream { + # Map of Host -> IP + # We will route the traffic to this endpoints. + map $ssl_preread_server_name $selected_upstream { + hostnames; + + # if not knonw, use some non existing response thingy :shrug: + default 255.255.255.255:1; + + ## CLOUD + proxmox.tjo.cloud batuu.system.tjo.space:4443; + postgresql.tjo.cloud batuu.system.tjo.space:4443; + monitor.tjo.cloud hetzner.system.tjo.cloud:4443; + loki.monitor.tjo.cloud hetzner.system.tjo.cloud:4443; + prometheus.monitor.tjo.cloud hetzner.system.tjo.cloud:4443; + grpc.otel.monitor.tjo.cloud hetzner.system.tjo.cloud:4443; + http.otel.monitor.tjo.cloud hetzner.system.tjo.cloud:4443; + vault.tjo.cloud batuu.system.tjo.space:4443; + + ## HETZNER + tjo.space hetzner.system.tjo.cloud:4443; + chat.tjo.space hetzner.system.tjo.cloud:4443; + webhook.chat.tjo.space hetzner.system.tjo.cloud:4443; + matrix.chat.tjo.space hetzner.system.tjo.cloud:4443; + yt.tjo.space hetzner.system.tjo.cloud:4443; + search.tjo.space hetzner.system.tjo.cloud:4443; + send.tjo.space hetzner.system.tjo.cloud:4443; + + ## BATUU + cloud.tjo.space batuu.system.tjo.space:4443; + collabora.tjo.space batuu.system.tjo.space:4443; + code.tjo.space batuu.system.tjo.space:4443; + vault.tjo.space batuu.system.tjo.space:4443; + rss.tjo.space batuu.system.tjo.space:4443; + id.tjo.space batuu.system.tjo.space:4443; + ldap.id.tjo.space batuu.system.tjo.space:4443; + mnts.dev batuu.system.tjo.space:4443; + paperless.tjo.space batuu.system.tjo.space:4443; + penpot.tjo.space batuu.system.tjo.space:4443; + + ## JAKKU + books.tjo.space jakku.system.tjo.space:4443; + media.tjo.space jakku.system.tjo.space:4443; + next.media.tjo.space jakku.system.tjo.space:4443; + request.media.tjo.space jakku.system.tjo.space:4443; + tdarr.media.tjo.space jakku.system.tjo.space:4443; + stuff.tjo.space jakku.system.tjo.space:4443; + auth.media.tjo.space jakku.system.tjo.space:4443; + sonarr.media.tjo.space jakku.system.tjo.space:4443; + radarr.media.tjo.space jakku.system.tjo.space:4443; + lidarr.media.tjo.space jakku.system.tjo.space:4443; + prowlarr.media.tjo.space jakku.system.tjo.space:4443; + qbittorrent.media.tjo.space jakku.system.tjo.space:4443; + bazarr.media.tjo.space jakku.system.tjo.space:4443; + readarr.media.tjo.space jakku.system.tjo.space:4443; + } + + geoip2 /var/geoip.mmdb { + $geoip2_data_country_iso_code country iso_code; + $geoip2_data_latitude location latitude; + $geoip2_data_longitude location longitude; + } + + log_format basic 'country=$geoip2_data_country_iso_code lat=$geoip2_data_latitude long=$geoip2_data_longitude ' + 'ip=$remote_addr ' + 'protocol=$protocol server_name=$ssl_preread_server_name upstream=$selected_upstream status=$status bytes_sent=$bytes_sent bytes_received=$bytes_received ' + 'session_time=$session_time'; + + server { + listen 0.0.0.0:443 default_server; + listen [::]:443 default_server; + server_name _; + proxy_pass $selected_upstream; + + proxy_protocol on; + include /etc/nginx/partials/server.conf; + include /etc/nginx/partials/blocked.conf; + } +} diff --git a/root/etc/nginx/partials/blocked.conf b/root/etc/nginx/partials/blocked.conf new file mode 100644 index 0000000..ab652e3 --- /dev/null +++ b/root/etc/nginx/partials/blocked.conf @@ -0,0 +1,164 @@ +#!!DO NOT EDIT!! Generated by using just ingress-blocked-list command. +deny 102.132.96.0/19; +deny 102.221.188.0/22; +deny 103.4.96.0/22; +deny 129.134.0.0/16; +deny 13.66.139.0/24; +deny 13.66.144.0/24; +deny 13.67.10.16/28; +deny 13.69.66.240/28; +deny 13.71.172.224/28; +deny 139.217.52.0/28; +deny 147.75.208.0/20; +deny 157.240.0.0/16; +deny 157.55.39.0/24; +deny 163.114.128.0/20; +deny 163.70.128.0/17; +deny 163.77.128.0/17; +deny 173.252.64.0/18; +deny 179.60.192.0/22; +deny 185.60.216.0/22; +deny 185.89.216.0/22; +deny 191.233.204.224/28; +deny 192.178.5.0/27; +deny 192.178.6.0/27; +deny 196.49.68.0/23; +deny 199.201.64.0/22; +deny 199.30.24.0/23; +deny 2001:4860:4801:10::/60; +deny 2001:4860:4801:20::/60; +deny 2001:4860:4801:2::/64; +deny 2001:4860:4801:31::/64; +deny 2001:4860:4801:32::/63; +deny 2001:4860:4801:34::/62; +deny 2001:4860:4801:38::/62; +deny 2001:4860:4801:3c::/63; +deny 2001:4860:4801:3e::/64; +deny 2001:4860:4801:40::/61; +deny 2001:4860:4801:48::/62; +deny 2001:4860:4801:50::/63; +deny 2001:4860:4801:53::/64; +deny 2001:4860:4801:54::/63; +deny 2001:4860:4801:60::/60; +deny 2001:4860:4801:70::/61; +deny 2001:4860:4801:78::/63; +deny 2001:4860:4801:80::/61; +deny 2001:4860:4801:88::/64; +deny 2001:4860:4801:90::/62; +deny 2001:4860:4801:94::/64; +deny 2001:4860:4801:c::/64; +deny 2001:4860:4801:f::/64; +deny 20.125.163.80/28; +deny 20.15.133.160/27; +deny 20.36.108.32/28; +deny 204.15.20.0/22; +deny 20.43.120.16/28; +deny 20.74.197.0/28; +deny 207.46.13.0/24; +deny 20.79.107.240/28; +deny 2401:db00::/32; +deny 2620:0:1c00::/40; +deny 2620:10d:c090::/44; +deny 2803:6080::/29; +deny 2a03:2880::/31; +deny 2a03:2887:ff02::/47; +deny 2a03:2887:ff04::/46; +deny 2a03:2887:ff08::/47; +deny 2a03:2887:ff18::/47; +deny 2a03:2887:ff1b::/48; +deny 2a03:2887:ff1c::/46; +deny 2a03:2887:ff21::/48; +deny 2a03:2887:ff23::/48; +deny 2a03:2887:ff24::/47; +deny 2a03:2887:ff27::/48; +deny 2a03:2887:ff28::/45; +deny 2a03:2887:ff30::/48; +deny 2a03:2887:ff33::/48; +deny 2a03:2887:ff35::/48; +deny 2a03:2887:ff36::/47; +deny 2a03:2887:ff38::/46; +deny 2a03:2887:ff3f::/48; +deny 2a03:2887:ff40::/46; +deny 2a03:2887:ff44::/47; +deny 2a03:2887:ff48::/46; +deny 2a03:2887:ff4d::/48; +deny 2a03:2887:ff4e::/47; +deny 2a03:2887:ff50::/45; +deny 2a03:2887:ff58::/47; +deny 2a03:2887:ff60::/45; +deny 2a03:2887:ff68::/47; +deny 2a03:83e0::/32; +deny 2a10:f781:10:cee0::/64; +deny 2c0f:ef78:10::/47; +deny 2c0f:ef78:12::/48; +deny 2c0f:ef78:3::/48; +deny 2c0f:ef78::/47; +deny 2c0f:ef78:5::/48; +deny 2c0f:ef78:6::/48; +deny 2c0f:ef78:9::/48; +deny 2c0f:ef78:c::/46; +deny 31.13.24.0/21; +deny 31.13.64.0/18; +deny 34.100.182.96/28; +deny 34.101.50.144/28; +deny 34.118.254.0/28; +deny 34.118.66.0/28; +deny 34.126.178.96/28; +deny 34.146.150.144/28; +deny 34.147.110.144/28; +deny 34.151.74.144/28; +deny 34.152.50.64/28; +deny 34.154.114.144/28; +deny 34.155.98.32/28; +deny 34.165.18.176/28; +deny 34.175.160.64/28; +deny 34.176.130.16/28; +deny 34.22.85.0/27; +deny 34.64.82.64/28; +deny 34.65.242.112/28; +deny 34.80.50.80/28; +deny 34.88.194.0/28; +deny 34.89.10.80/28; +deny 34.89.198.80/28; +deny 34.96.162.48/28; +deny 35.247.243.240/28; +deny 40.77.139.0/25; +deny 40.77.167.0/24; +deny 40.77.177.0/24; +deny 40.77.178.0/23; +deny 40.77.188.0/22; +deny 40.77.202.0/24; +deny 40.79.131.208/28; +deny 40.79.186.176/28; +deny 45.64.40.0/22; +deny 51.105.67.0/28; +deny 52.167.144.0/24; +deny 52.230.152.0/24; +deny 52.231.148.0/28; +deny 52.233.106.0/24; +deny 57.141.0.0/21; +deny 57.141.12.0/23; +deny 57.141.8.0/22; +deny 57.144.0.0/14; +deny 65.55.210.0/24; +deny 66.220.144.0/20; +deny 66.249.64.0/25; +deny 66.249.64.128/26; +deny 66.249.64.224/27; +deny 66.249.65.0/24; +deny 66.249.66.0/25; +deny 66.249.66.160/27; +deny 66.249.66.192/27; +deny 66.249.68.0/25; +deny 66.249.69.0/24; +deny 66.249.70.0/23; +deny 66.249.72.0/23; +deny 66.249.74.0/25; +deny 66.249.74.128/27; +deny 66.249.75.0/24; +deny 66.249.76.0/23; +deny 66.249.78.0/26; +deny 66.249.79.0/24; +deny 69.171.224.0/19; +deny 69.63.176.0/20; +deny 74.119.76.0/22; diff --git a/root/etc/nginx/partials/server.conf b/root/etc/nginx/partials/server.conf new file mode 100644 index 0000000..e54a8a8 --- /dev/null +++ b/root/etc/nginx/partials/server.conf @@ -0,0 +1,5 @@ +# Default server configuration +access_log /dev/stdout basic; +resolver 9.9.9.9 1.1.1.1 8.8.8.8 8.8.4.4; +set_real_ip_from 0.0.0.0/0; +ssl_preread on; diff --git a/terraform/.terraform.lock.hcl b/terraform/.terraform.lock.hcl index affa7ef..063a06e 100644 --- a/terraform/.terraform.lock.hcl +++ b/terraform/.terraform.lock.hcl @@ -24,30 +24,6 @@ provider "registry.opentofu.org/bpg/proxmox" { ] } -provider "registry.opentofu.org/digitalocean/digitalocean" { - version = "2.40.0" - constraints = "~> 2.0" - hashes = [ - "h1:Y7VkuuqOBgv+1jgL/4Hi247K2BskXwXtR/Uk9ssK/e4=", - "zh:00235830abae70642ebefc4d9c00e5eb978e28b74abc6b34f16b078f242aa217", - "zh:09d77785f768bd568f85a121d3d79316083befe903ce4ccd5567689a23236fb0", - "zh:0c9c4e19b411702d316a6bd044903e2ec506a69d38495ed32cc31e3f3f26acae", - "zh:12b34c88faad5b6149e9a3ad1396680588e1bae263b20d6b19835460f111c190", - "zh:15f041fc57ea46673a828919efe2ef3f05f7c4b863b7d7881336b93e92bd1159", - "zh:45e01972de2fab1687a09ea8fb3e4519be11c93ef93a63f28665630850858a20", - "zh:4e18bf5c1d2ec1ec6b6a9f4b58045309006f510edf770168fc18e273e6a09289", - "zh:575528b7e36e3489d2309e0c6cb9bd9952595cac5459b914f2d2827de1a1e4fc", - "zh:67462192212f810875d556462c79f574a8f5713b7a869ba4fce25953bfcf2dd2", - "zh:7024637b31e8276b653265fdf3f479220182edde4b300b034562b4c287faefa5", - "zh:a7904721b2680be8330dde98dd826be15c67eb274da7876f042cbcd6592ac970", - "zh:b225d4b67037a19392b0ab00d1f5fc9e729db4dfc32d18d4b36225693270ef52", - "zh:bd1e8768819d6113b2ec16f939196a1f2ae6d2803824fde463a20d06e071b212", - "zh:c5da40dc0749548ee2e1943776fb41b952c994e50bbc404251df20a81f730242", - "zh:dabc3387392aaba297739e1e97fadf059258fc3efb4dff2f499dbc407b6e088d", - "zh:f42137cf424c3e7c9c935b3f73618e51096bd0367a8d364073e2d70588d2cbf2", - ] -} - provider "registry.opentofu.org/goauthentik/authentik" { version = "2024.8.3" constraints = "2024.8.3" @@ -69,43 +45,3 @@ provider "registry.opentofu.org/goauthentik/authentik" { "zh:f6af0fd2e89ea7b7e692ef893cf5fdcc6f53c37fc0c6e066a28d9c834226c539", ] } - -provider "registry.opentofu.org/hashicorp/dns" { - version = "3.4.1" - constraints = "~> 3.4.1" - hashes = [ - "h1:6Tb2wZRxfKunvjLw47ihfkaoARWIQrJd+WCOXkx0hg4=", - "zh:53f46f16fc3b25d9bdce61d7cc9a67cea9c67ea5347fcde35833451d5011f1c4", - "zh:662669802c99c7e698ca52e7a32afc19acf66d97bbc05f5effacdf0fe471848f", - "zh:8289aee49df8a0cb2fcdfded575e68df1721fc3e6ce75555def499d31b7e910d", - "zh:90aa9b049d19137ed15ea3f88238824e1fde7d1a806378cb97520391e169a96d", - "zh:9e5795e10d65927ba689cfabc06b72085055543342d1db26ef5963ae5ab5d64a", - "zh:9f39b6e0ca35cf2405fe4e13af8a405cf9b0b0c34b6b06ad36f319631405a3aa", - "zh:c37a2c140c95b3eaa9d0aeb79496b220ba1a0456d01a77fcc68bd565bee7edd5", - "zh:cd40d356c5382f0b868df2d8539f95031e3cf0c210053674ec4c7cd20c73b82a", - "zh:fde59f09e4e62fc84012fff8493bc64eac287a0245e1c8abf29b0138d3018dfb", - "zh:ffee5b54936bd43247e9316de0ecc0dde36556a2cd50f090d7f6443a3f689b95", - ] -} - -provider "registry.opentofu.org/tailscale/tailscale" { - version = "0.16.1" - constraints = "0.16.1" - hashes = [ - "h1:NDIIkEo0G/leQSvGoh2Mk74ZE2xWrWgHX/S8ZVyBDYU=", - "zh:0a9d28e5195e0e29ebf9b12b345cafcb686125008151fa01677c399d8f8f1321", - "zh:249bce2fcfd3414211ae9e49e179e31b5d3c23dd9da24dc45acdea34ad308cb0", - "zh:3129fb52a2aaa0c8c30aff21e7d4c0601d80898b3ecb9d7604b5933c14f54924", - "zh:4ec3e255f34bb4f6362ab41aa9e05a3ce040a791bc07445dec86188dee867f85", - "zh:68d3995e5a1722e24f89a385899f56a63542159b884cac989196e9538b53c6ce", - "zh:799840b3bfbd14537397f157f4e6a5e54080cd4fee51521bac675aa188e0b33e", - "zh:99f1da9fdaddd8a1255dce56edf8eb3e235293c72738cf70f1fb9ee9631b40e6", - "zh:9b18fd51e260b2f3100937c34feae5f6fe3515df9b5e27ae23d00af75249a6d4", - "zh:a7154cdce28aeb80e822a97c6bc8b8acb7a074304fd198e265ac9cbcbda0ca06", - "zh:b0ce2ca42f018e5235a2171cdd8ba9829c90c54a6b2d602bd38e0e90c43d5d5d", - "zh:c67609f7018fc6e48b17befd6eeb21197e8f524496185c5e29707efa6967a0a5", - "zh:d4c9dc9d2a5a535851fc10049506bad1e7ab88193d5dcd371f91ac1b84f43a0a", - "zh:da27f2a9b9d5a4c02ec3893a763874513825c7c4dc2bb870ba741cf7725bcf9f", - "zh:e5bc1797b97607ff3d841c6c0d40da89c3843156ad43e15ded7d41fc0ac27717", - ] -} diff --git a/terraform/dns.tf b/terraform/dns.tf deleted file mode 100644 index fcc9b43..0000000 --- a/terraform/dns.tf +++ /dev/null @@ -1,70 +0,0 @@ -locals { - nodes_for_dns = { for k, v in var.nodes : k => v if v.public != null && v.internal != null } -} - -data "digitalocean_domain" "ingress" { - name = "ingress.tjo.cloud" -} - -resource "digitalocean_record" "public" { - for_each = merge( - { - for key, node in local.nodes_for_dns : key => { - node = node.name, - ip = node.public.ipv4, - type = "A", - } - }, - { - for key, node in local.nodes_for_dns : key => { - node = node.name, - ip = node.public.ipv6, - type = "AAAA", - } - } - ) - - domain = data.digitalocean_domain.ingress.id - type = each.value.type - name = lower(each.value.node) - value = each.value.ip - ttl = 60 -} - -resource "digitalocean_record" "internal" { - for_each = merge( - { - for key, node in local.nodes_for_dns : key => { - node = node.name, - ip = node.internal.ipv4, - type = "A", - } - }, - { - for key, node in local.nodes_for_dns : key => { - node = node.name, - ip = node.internal.ipv6, - type = "AAAA", - } - } - ) - - domain = data.digitalocean_domain.ingress.id - type = each.value.type - name = "internal.${lower(each.value.node)}" - value = each.value.ip - ttl = 60 -} - -resource "digitalocean_record" "srv" { - for_each = local.nodes_for_dns - - domain = data.digitalocean_domain.ingress.id - type = "SRV" - name = digitalocean_record.internal[each.key].fqdn - value = "_nginx._tcp" - port = 9000 - priority = 10 - weight = 100 - ttl = 60 -} diff --git a/terraform/node.tf b/terraform/node.tf index db97a3f..55aaa07 100644 --- a/terraform/node.tf +++ b/terraform/node.tf @@ -3,12 +3,12 @@ locals { nodes = { for k, v in var.nodes : k => merge(v, { - id = 700 + index(keys(var.nodes), k) - hash = sha1(v.name) - mac_address = "AA:BB:07:00:${format("%v:%v", substr(sha1(v.name), 0, 2), substr(sha1(v.name), 2, 2))}" + id = 800 + index(keys(var.nodes), k) + hash = sha1(v.host) + mac_address = "AA:BB:07:00:${format("%v:%v", substr(sha1(v.host), 0, 2), substr(sha1(v.host), 2, 2))}" domain = local.domain meta = { - name = v.name + name = v.host domain = local.domain service_account = { username = authentik_user.service_account[k].username @@ -17,12 +17,21 @@ locals { } }) } + + ipv4_addresses = { + for key, node in local.nodes : key => { + for k, v in proxmox_virtual_environment_vm.nodes[key].ipv4_addresses : + proxmox_virtual_environment_vm.nodes[key].network_interface_names[k] => v + } + } } resource "proxmox_virtual_environment_download_file" "ubuntu" { + for_each = local.nodes + content_type = "iso" - datastore_id = var.common_storage - node_name = var.nodes[keys(var.nodes)[0]].host + datastore_id = each.value.iso_storage + node_name = each.value.host url = "https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img" overwrite = false } @@ -32,12 +41,12 @@ resource "proxmox_virtual_environment_file" "userdata" { node_name = each.value.host content_type = "snippets" - datastore_id = var.common_storage + datastore_id = each.value.iso_storage source_raw { data = <<-EOF #cloud-config - hostname: ${each.value.name}.${each.value.domain} + hostname: ${each.value.host}.${each.value.domain} write_files: - path: /etc/tjo.cloud/meta.json encoding: base64 @@ -48,7 +57,7 @@ resource "proxmox_virtual_environment_file" "userdata" { power_state: mode: reboot EOF - file_name = "${each.value.name}.ingress.tjo.cloud.userconfig.yaml" + file_name = "${each.value.host}.ingress.tjo.cloud.userconfig.yaml" } } @@ -56,11 +65,16 @@ resource "proxmox_virtual_environment_vm" "nodes" { for_each = local.nodes vm_id = each.value.id - name = "${each.value.name}.${each.value.domain}" + name = "${each.value.host}.${each.value.domain}" node_name = each.value.host - description = "Node ${each.value.name} for ${each.value.domain}." - tags = [each.value.domain] + description = <