From 274fd90d2c9990669586157795e7839f94074c2f Mon Sep 17 00:00:00 2001 From: Tine Date: Tue, 20 Aug 2024 21:03:23 +0200 Subject: [PATCH] feat: initial commit Having problems with how to upload raw disk image to proxmox using terraform. --- .envrc | 7 ++ .gitignore | 42 ++++++++++++ Dockerfile | 36 ++++++++++ configuration.nix | 13 ++++ devbox.json | 20 ++++++ devbox.lock | 101 +++++++++++++++++++++++++++ flake.lock | 101 +++++++++++++++++++++++++++ flake.nix | 49 +++++++++++++ justfile | 26 +++++++ terraform/.terraform.lock.hcl | 89 ++++++++++++++++++++++++ terraform/node.tf | 125 ++++++++++++++++++++++++++++++++++ terraform/nodes.tf | 28 ++++++++ terraform/records.tf | 35 ++++++++++ terraform/terraform.tf | 38 +++++++++++ terraform/variables.tf | 32 +++++++++ 15 files changed, 742 insertions(+) create mode 100644 .envrc create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 configuration.nix create mode 100644 devbox.json create mode 100644 devbox.lock create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 justfile create mode 100644 terraform/.terraform.lock.hcl create mode 100644 terraform/node.tf create mode 100644 terraform/nodes.tf create mode 100644 terraform/records.tf create mode 100644 terraform/terraform.tf create mode 100644 terraform/variables.tf diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..84fc8e5 --- /dev/null +++ b/.envrc @@ -0,0 +1,7 @@ +# Automatically sets up your devbox environment whenever you cd into this +# directory via our direnv integration: + +eval "$(devbox generate direnv --print-envrc)" + +# check out https://www.jetpack.io/devbox/docs/ide_configuration/direnv/ +# for more details diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..27a9393 --- /dev/null +++ b/.gitignore @@ -0,0 +1,42 @@ +# ---> Terraform +# Local .terraform directories +**/.terraform/* + +# .tfstate files +**/*.tfstate +**/*.tfstate.* + +# Crash log files +crash.log +crash.*.log + +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc + +# ENV +.env +admin.*config + +# Nix +result diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c8cac82 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,36 @@ +ARG NGINX_VERSION=1.27.1 +FROM nginx:$NGINX_VERSION AS build + +RUN mkdir -p /var/lib/GeoIP/ + +RUN apt-get update \ + && apt-get install -y \ + build-essential \ + libpcre2-dev \ + zlib1g-dev \ + libgeoip-dev \ + libmaxminddb-dev \ + wget \ + git + +ARG GEOIP2_VERSION=3.4 +RUN cd /opt \ + && git clone --depth 1 -b $GEOIP2_VERSION --single-branch https://github.com/leev/ngx_http_geoip2_module.git \ + && wget -O - http://nginx.org/download/nginx-$NGINX_VERSION.tar.gz | tar zxfv - \ + && mv /opt/nginx-$NGINX_VERSION /opt/nginx \ + && cd /opt/nginx \ + && ./configure --with-compat --add-dynamic-module=/opt/ngx_http_geoip2_module --with-stream \ + && make modules + +# Production +FROM nginx:$NGINX_VERSION AS production + +COPY --from=build /opt/nginx/objs/ngx_http_geoip2_module.so /usr/lib/nginx/modules +COPY --from=build /opt/nginx/objs/ngx_stream_geoip2_module.so /usr/lib/nginx/modules + +RUN apt-get update \ + && apt-get install -y --no-install-recommends --no-install-suggests libmaxminddb0 \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* \ + && chmod -R 644 /usr/lib/nginx/modules/ngx_http_geoip2_module.so \ + && chmod -R 644 /usr/lib/nginx/modules/ngx_stream_geoip2_module.so diff --git a/configuration.nix b/configuration.nix new file mode 100644 index 0000000..64caa71 --- /dev/null +++ b/configuration.nix @@ -0,0 +1,13 @@ +{ + inputs, + lib, + config, + pkgs, + ... +} : { + system.stateVersion = "23.11"; + + environment.systemPackages = [ + pkgs.nginx + ]; +} diff --git a/devbox.json b/devbox.json new file mode 100644 index 0000000..87ae00a --- /dev/null +++ b/devbox.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://raw.githubusercontent.com/jetify-com/devbox/0.12.0/.schema/devbox.schema.json", + "packages": [ + "tflint@latest", + "tenv@latest" + ], + "env": { + "TENV_AUTO_INSTALL": "true" + }, + "shell": { + "init_hook": [ + "echo 'Welcome to devbox!' > /dev/null" + ], + "scripts": { + "test": [ + "echo \"Error: no test specified\" && exit 1" + ] + } + } +} diff --git a/devbox.lock b/devbox.lock new file mode 100644 index 0000000..fcf0f43 --- /dev/null +++ b/devbox.lock @@ -0,0 +1,101 @@ +{ + "lockfile_version": "1", + "packages": { + "tenv@latest": { + "last_modified": "2024-08-18T12:44:29Z", + "resolved": "github:NixOS/nixpkgs/ff1c2669bbb4d0dd9e62cc94f0968cfa652ceec1#tenv", + "source": "devbox-search", + "version": "3.0.0", + "systems": { + "aarch64-darwin": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/0zbz338z744cmpp0z2rmzygab4b8pili-tenv-3.0.0", + "default": true + } + ], + "store_path": "/nix/store/0zbz338z744cmpp0z2rmzygab4b8pili-tenv-3.0.0" + }, + "aarch64-linux": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/fiwf4p798kamjy6waaqn0nl6dvzrz6r0-tenv-3.0.0", + "default": true + } + ], + "store_path": "/nix/store/fiwf4p798kamjy6waaqn0nl6dvzrz6r0-tenv-3.0.0" + }, + "x86_64-darwin": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/g87m0hmaqlb9gcg2c8ln1lx9fyzqx1m0-tenv-3.0.0", + "default": true + } + ], + "store_path": "/nix/store/g87m0hmaqlb9gcg2c8ln1lx9fyzqx1m0-tenv-3.0.0" + }, + "x86_64-linux": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/x22lfx74nns131xxmnhpnnn7gz6hfp1r-tenv-3.0.0", + "default": true + } + ], + "store_path": "/nix/store/x22lfx74nns131xxmnhpnnn7gz6hfp1r-tenv-3.0.0" + } + } + }, + "tflint@latest": { + "last_modified": "2024-08-18T12:44:29Z", + "resolved": "github:NixOS/nixpkgs/ff1c2669bbb4d0dd9e62cc94f0968cfa652ceec1#tflint", + "source": "devbox-search", + "version": "0.52.0", + "systems": { + "aarch64-darwin": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/2kqp4ba1anc4c1vxm31criv2cnw7bm8i-tflint-0.52.0", + "default": true + } + ], + "store_path": "/nix/store/2kqp4ba1anc4c1vxm31criv2cnw7bm8i-tflint-0.52.0" + }, + "aarch64-linux": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/zq3wrj237i9v6jvjfiiglhqrxnn5yfbl-tflint-0.52.0", + "default": true + } + ], + "store_path": "/nix/store/zq3wrj237i9v6jvjfiiglhqrxnn5yfbl-tflint-0.52.0" + }, + "x86_64-darwin": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/57xd6fdjgkhyi8p69bik9bhjz3nxz4gk-tflint-0.52.0", + "default": true + } + ], + "store_path": "/nix/store/57xd6fdjgkhyi8p69bik9bhjz3nxz4gk-tflint-0.52.0" + }, + "x86_64-linux": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/ldy3j1qq62nq1fm9q3rpmnd0glpzvfma-tflint-0.52.0", + "default": true + } + ], + "store_path": "/nix/store/ldy3j1qq62nq1fm9q3rpmnd0glpzvfma-tflint-0.52.0" + } + } + } + } +} diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..aaca5fc --- /dev/null +++ b/flake.lock @@ -0,0 +1,101 @@ +{ + "nodes": { + "flake-utils": { + "locked": { + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixlib": { + "locked": { + "lastModified": 1723942470, + "narHash": "sha256-QdSArN0xKESEOTcv+3kE6yu4B4WX9lupZ4+Htx3RXGg=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "531a2e8416a6d8200a53eddfbdb8f2c8dc4a1251", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "nixos-generators": { + "inputs": { + "nixlib": "nixlib", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1724028932, + "narHash": "sha256-U11ZiQPrpIBdv7oS23bNdX9GCxe/hPf/ARr64P2Wj1Y=", + "owner": "nix-community", + "repo": "nixos-generators", + "rev": "5fd22603892e4ec5ac6085058ed658243143aacd", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixos-generators", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1720535198, + "narHash": "sha256-zwVvxrdIzralnSbcpghA92tWu2DV2lwv89xZc8MTrbg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "205fd4226592cc83fd4c0885a3e4c9c400efabb5", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixos-generators": "nixos-generators", + "nixpkgs": "nixpkgs", + "xc": "xc" + } + }, + "xc": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1724081153, + "narHash": "sha256-j2bfrmjBSf87ByVSGUaNzHk3Hh605/rOjar3slWAhjQ=", + "owner": "joerdav", + "repo": "xc", + "rev": "48e28d6f29623b0c2eedce688fcb7d29f0d2976e", + "type": "github" + }, + "original": { + "owner": "joerdav", + "repo": "xc", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..5ae0374 --- /dev/null +++ b/flake.nix @@ -0,0 +1,49 @@ +{ + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11"; + nixos-generators = { + url = "github:nix-community/nixos-generators"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + xc = { + url = "github:joerdav/xc"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = { nixpkgs, nixos-generators, xc, ... }: + let + pkgsForSystem = system: import nixpkgs { + inherit system; + overlays = [ + (final: prev: { xc = xc.packages.${system}.xc; }) + ]; + }; + allVMs = [ "x86_64-linux" "aarch64-linux" ]; + forAllVMs = f: nixpkgs.lib.genAttrs allVMs (system: f { + inherit system; + pkgs = pkgsForSystem system; + }); + in + { + packages = forAllVMs ({ system, pkgs }: { + vm = nixos-generators.nixosGenerate { + format = "proxmox"; + system = system; + + specialArgs = { + pkgs = pkgs; + #diskSize = "8G"; + }; + + modules = [ + # Pin nixpkgs to the flake input, so that the packages installed + # come from the flake inputs.nixpkgs.url. + ({ ... }: { nix.registry.nixpkgs.flake = nixpkgs; }) + # Apply the rest of the config. + ./configuration.nix + ]; + }; + }); + }; +} diff --git a/justfile b/justfile new file mode 100644 index 0000000..674e068 --- /dev/null +++ b/justfile @@ -0,0 +1,26 @@ +# Always use devbox environment to run commands. +set shell := ["devbox", "run"] +# Load dotenv +set dotenv-load + +export TENV_AUTO_INSTALL := "true" + +default: + @just --list + +lint: + @tofu fmt -check -recursive . + @tflint --recursive + +build: + @nix build .#vm + +deploy: + #!/usr/bin/env sh + export NIX_RESULT_DIR=$(nix build --print-out-paths .#vm) + export IMAGE_NAME=$(ls ${NIX_RESULT_DIR} | grep ".vma.zst") + export TF_VAR_image_path=${NIX_RESULT_DIR}/${IMAGE_NAME} + + cd {{justfile_directory()}}/terraform + tofu init + tofu apply diff --git a/terraform/.terraform.lock.hcl b/terraform/.terraform.lock.hcl new file mode 100644 index 0000000..3354b09 --- /dev/null +++ b/terraform/.terraform.lock.hcl @@ -0,0 +1,89 @@ +# This file is maintained automatically by "tofu init". +# Manual edits may be lost in future updates. + +provider "registry.opentofu.org/bpg/proxmox" { + version = "0.61.1" + constraints = "0.61.1" + hashes = [ + "h1:6kz2Rdjc8+TVq2aUxEQXLOwbb9OdhJJei0L1fC4K2R4=", + "zh:27d8b589a2dc1e0a5b0f8ab299b9f3704a2f0b69799d1d4d8845c68056986d1f", + "zh:46dfa6b33ddd7007a2144f38090457604eb56a59a303b37bb0ad1be5c84ddaca", + "zh:47a1b14a759393c5ecc76f2feb950677c418c910b8c677fde0dd3e4675c41579", + "zh:582e49d109d1c2b1f3b1268a7cbc43548f3c6d96a87c92a5428767097a5e383e", + "zh:5e98ad6afae5969a4c3ffb14c0484936550c66c8313d7686551c29b633ff32f2", + "zh:7b9e24b76f947ab8f1e571cf61beefc983b7d2aa1b85df35c4f015728fe37a38", + "zh:8255ca210f279a0f7b8ca2762df26d2ea1a01704298c5e3d5cf601bd39a743f0", + "zh:85d7655fdc95dedced9cf8105a0beeb0d7bc8f668c55f62019a7215a76d60300", + "zh:8aeea5a1d001b06baaf923b754e1a14d06c75eb8c8b87a7f65a3c8205fc8b079", + "zh:a9cfab6c06f613658c5fdd83742cd22c0eb7563778924b1407965ef8c36c1ce0", + "zh:ceaab67801d49a92eb5858b1ddae6df2569462e5ffbe31f9dbd79dcb684ea142", + "zh:dc25b506d5c55d1d78a335d3ebd03213c99b4b2a5859812349a955c2f746ff7e", + "zh:e04b477fd77a0d37a0bdb76a7cf69184dad9e7fbba9b4f3a378a8901b82b75e5", + "zh:f1e6838d9141557f73340df9b21fce5a82b41cc16ae36f063a920ccc36bc0758", + "zh:f26e0763dbe6a6b2195c94b44696f2110f7f55433dc142839be16b9697fa5597", + ] +} + +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/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/node.tf b/terraform/node.tf new file mode 100644 index 0000000..b7de91e --- /dev/null +++ b/terraform/node.tf @@ -0,0 +1,125 @@ +locals { + nodes_with_names = { + for k, v in var.nodes : k => merge(v, { + id = 700 + index(keys(var.nodes), k) + hash = sha1(v.name) + }) + } + nodes = { + for k, v in local.nodes_with_names : k => merge(v, { + mac_address = "AA:BB:07:00:${format("%v:%v", substr(v.hash, 0, 2), substr(v.hash, 2, 2))}" + }) + } + + + 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 + } + } + ipv6_addresses = { + for key, node in local.nodes : key => { + for k, v in proxmox_virtual_environment_vm.nodes[key].ipv6_addresses : + proxmox_virtual_environment_vm.nodes[key].network_interface_names[k] => v + } + } + + nodes_with_address = { + for k, v in local.nodes : + k => merge(v, { + ipv4 = local.ipv4_addresses[k]["eth0"][0] + ipv6 = local.ipv6_addresses[k]["eth0"][0] + }) + } +} + +resource "proxmox_virtual_environment_file" "ingress" { + content_type = "iso" + datastore_id = var.common_storage + node_name = values(var.nodes)[0].host + + source_file { + path = var.image_path + file_name = "ingress-tjo-cloud.img" + } +} + +resource "proxmox_virtual_environment_file" "cloudinit" { + for_each = local.nodes + + node_name = each.value.host + content_type = "snippets" + datastore_id = var.common_storage + + source_raw { + data = <<-EOF + + EOF + file_name = "${each.value.name}-ingress-tjo-cloud.cloudinit.yaml" + } +} + +resource "proxmox_virtual_environment_vm" "nodes" { + for_each = local.nodes + + vm_id = each.value.id + name = each.value.name + node_name = each.value.host + + description = "Node ${each.value.name} for ingress.tjo.cloud." + tags = concat( + ["tjo-space"], + [each.value.name] + ) + + stop_on_destroy = true + timeout_start_vm = 60 + timeout_stop_vm = 60 + timeout_shutdown_vm = 60 + timeout_reboot = 60 + timeout_create = 120 + + cpu { + cores = each.value.cores + type = "host" + } + memory { + dedicated = each.value.memory + } + + operating_system { + type = "l26" + } + + agent { + enabled = true + timeout = "1m" + } + + network_device { + bridge = each.value.bridge + mac_address = each.value.mac_address + } + + cdrom { + enabled = true + file_id = proxmox_virtual_environment_file.ingress.id + } + + scsi_hardware = "virtio-scsi-single" + disk { + file_format = "raw" + interface = "virtio0" + datastore_id = each.value.storage + size = each.value.boot_size + backup = true + cache = "none" + iothread = true + } + + initialization { + datastore_id = each.value.storage + meta_data_file_id = proxmox_virtual_environment_file.cloudinit[each.key].id + } +} diff --git a/terraform/nodes.tf b/terraform/nodes.tf new file mode 100644 index 0000000..40e7713 --- /dev/null +++ b/terraform/nodes.tf @@ -0,0 +1,28 @@ + +locals { + locations = { + DE = ["46.4.88.62", "2a01:4f8:202:2395::"] + SI = ["93.103.125.118", "2a01:261:455:6c00:21e:6ff:fe45:c34"] + } +} + +data "digitalocean_domain" "ingress" { + name = "ingress.tjo.cloud" +} + +resource "digitalocean_record" "locations" { + for_each = merge([ + for location, ips in local.locations : { + for ip in ips : "${location} at ${ip}" => { + location = location, + ip = ip, + } + } + ]...) + + domain = data.digitalocean_domain.ingress.id + type = strcontains(each.value.ip, ":") ? "AAAA" : "A" + name = lower(each.value.location) + value = each.value.ip + ttl = 60 +} diff --git a/terraform/records.tf b/terraform/records.tf new file mode 100644 index 0000000..5221de4 --- /dev/null +++ b/terraform/records.tf @@ -0,0 +1,35 @@ +locals { + listeners = [ + { + domain = "k8s.tjo.cloud" + name = "api" + locations = ["SI", "DE"] + }, + { + domain = "k8s.tjo.cloud" + name = "dashboard" + locations = ["SI", "DE"] + } + ] +} + +resource "digitalocean_record" "listeners" { + for_each = merge(flatten([ + for listener in local.listeners : + [ + for location in listener.locations : { + for ip in local.locations[location] : "${ip} for ${listener.name}.${listener.domain} at ${location}" => { + ip = ip + domain = listener.domain + name = listener.name + } + } + ] + ])...) + + domain = each.value.domain + type = strcontains(each.value.ip, ":") ? "AAAA" : "A" + name = each.value.name + value = each.value.ip + ttl = 60 +} diff --git a/terraform/terraform.tf b/terraform/terraform.tf new file mode 100644 index 0000000..88a9394 --- /dev/null +++ b/terraform/terraform.tf @@ -0,0 +1,38 @@ +terraform { + required_providers { + digitalocean = { + source = "digitalocean/digitalocean" + version = "~> 2.0" + } + dns = { + source = "hashicorp/dns" + version = "~> 3.4.1" + } + proxmox = { + source = "bpg/proxmox" + version = "0.61.1" + } + tailscale = { + source = "tailscale/tailscale" + version = "0.16.1" + } + } + + required_version = "~> 1.7.3" +} + +provider "digitalocean" { + token = var.digitalocean_token +} + + +provider "proxmox" { + # FIXME: Traefik/NGINX breaks this! 500 ERROR + endpoint = "https://178.63.49.225:8006/api2/json" + insecure = true + api_token = var.proxmox_token + ssh { + agent = true + username = "root" + } +} diff --git a/terraform/variables.tf b/terraform/variables.tf new file mode 100644 index 0000000..fae3d30 --- /dev/null +++ b/terraform/variables.tf @@ -0,0 +1,32 @@ +variable "nodes" { + type = map(object({ + name = string + + host = string + bridge = string + + cores = optional(number, 1) + memory = optional(number, 512) + + storage = optional(string, "main") + boot_size = optional(number, 8) + + cloudinit = string + })) +} + +variable "common_storage" { + type = string +} + +variable "digitalocean_token" { + type = string +} + +variable "proxmox_token" { + type = string +} + +variable "image_path" { + type = string +}