From 53c494992750be5f207c6f0b0ed0adce4a75b6ef Mon Sep 17 00:00:00 2001 From: DeveloperDurp Date: Thu, 13 Feb 2025 06:06:23 -0600 Subject: [PATCH] Add terraform for infra --- .gitlab/.gitlab-ci.yml | 2 + infra/.gitlab/.gitlab-ci.yml | 94 ++++++++++++++++ infra/authentik/Chart.yaml | 12 ++ infra/authentik/templates/ingress.yaml | 42 +++++++ infra/authentik/templates/secrets.yaml | 28 +++++ infra/authentik/values.yaml | 56 ++++++++++ infra/terraform/main.tf | 149 +++++++++++++++++++++++++ infra/terraform/variables.tf | 14 +++ 8 files changed, 397 insertions(+) create mode 100644 .gitlab/.gitlab-ci.yml create mode 100644 infra/.gitlab/.gitlab-ci.yml create mode 100644 infra/authentik/Chart.yaml create mode 100644 infra/authentik/templates/ingress.yaml create mode 100644 infra/authentik/templates/secrets.yaml create mode 100644 infra/authentik/values.yaml create mode 100644 infra/terraform/main.tf create mode 100644 infra/terraform/variables.tf diff --git a/.gitlab/.gitlab-ci.yml b/.gitlab/.gitlab-ci.yml new file mode 100644 index 0000000..080d92c --- /dev/null +++ b/.gitlab/.gitlab-ci.yml @@ -0,0 +1,2 @@ +include: + - local: infra/.gitlab/.gitlab-ci.yml \ No newline at end of file diff --git a/infra/.gitlab/.gitlab-ci.yml b/infra/.gitlab/.gitlab-ci.yml new file mode 100644 index 0000000..da46909 --- /dev/null +++ b/infra/.gitlab/.gitlab-ci.yml @@ -0,0 +1,94 @@ +stages: + - plan + - apply + - destroy + +variables: + WORKDIR: $CI_PROJECT_DIR/infra + GITLAB_TF_ADDRESS: ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/infra + +image: + name: registry.internal.durp.info/opentofu/opentofu:latest + entrypoint: [""] + +.tf-init: + before_script: + - cd $WORKDIR + - | + tofu init -reconfigure -backend-config="address=${GITLAB_TF_ADDRESS}" \ + -backend-config="lock_address=${GITLAB_TF_ADDRESS}/lock" \ + -backend-config="unlock_address=${GITLAB_TF_ADDRESS}/lock" \ + -backend-config="username=gitlab-ci-token" \ + -backend-config="password=${CI_JOB_TOKEN}" \ + -backend-config="lock_method=POST" \ + -backend-config="unlock_method=DELETE" \ + -backend-config="retry_wait_min=5" + +format: + stage: .pre + allow_failure: false + script: + - cd $WORKDIR + - tofu fmt -diff -check -write=false + rules: + - changes: + - .tf + +validate: + stage: .pre + allow_failure: false + extends: .tf-init + script: + - tofu validate + rules: + - changes: + - .tf + +plan-infrastructure: + stage: plan + variables: + PLAN: plan.tfplan + JSON_PLAN_FILE: tfplan.json + ENVIRONMENT_NAME: infra + allow_failure: false + extends: .tf-init + script: + - apk add --update curl jq + - alias convert_report="jq -r '([.resource_changes[].change.actions?]|flatten)|{\"create\":(map(select(.==\"create\"))|length),\"update\":(map(select(.==\"update\"))|length),\"delete\":(map(select(.==\"delete\"))|length)}'" + - tofu plan -out=$PLAN $ARGUMENTS + - tofu show --json $PLAN | jq -r '([.resource_changes[].change.actions?]|flatten)|{"create":(map(select(.=="create"))|length),"update":(map(select(.=="update"))|length),"delete":(map(select(.=="delete"))|length)}' > $JSON_PLAN_FILE + artifacts: + reports: + terraform: $WORKDIR/$JSON_PLAN_FILE + needs: ["validate","format"] + rules: + - changes: + - .tf + +apply-infrastructure: + stage: apply + variables: + ENVIRONMENT_NAME: infra + allow_failure: false + extends: .tf-init + script: + - tofu apply -auto-approve $ARGUMENTS + rules: + - changes: + - .tf + when: manual + needs: ["plan-infrastructure"] + +destroy-infrastructure: + stage: destroy + variables: + ENVIRONMENT_NAME: infra + allow_failure: false + extends: .tf-init + script: + - tofu destory -auto-approve $ARGUMENTS + rules: + - changes: + - .tf + when: manual + needs: ["plan-infrastructure"] diff --git a/infra/authentik/Chart.yaml b/infra/authentik/Chart.yaml new file mode 100644 index 0000000..c87b677 --- /dev/null +++ b/infra/authentik/Chart.yaml @@ -0,0 +1,12 @@ +apiVersion: v2 +name: authentik +description: A Helm chart for Kubernetes +type: application + +version: 0.1.0 +appVersion: "1.16.0" + +dependencies: +- name: authentik + repository: https://charts.goauthentik.io + version: 2024.8.3 \ No newline at end of file diff --git a/infra/authentik/templates/ingress.yaml b/infra/authentik/templates/ingress.yaml new file mode 100644 index 0000000..ac10303 --- /dev/null +++ b/infra/authentik/templates/ingress.yaml @@ -0,0 +1,42 @@ +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRoute +metadata: + name: authentik-ingress +spec: + entryPoints: + - websecure + routes: + - match: Host(`authentik.durp.info`) && PathPrefix(`/`) + kind: Rule + services: + - name: authentik-server + port: 80 + tls: + secretName: authentik-tls + +--- + +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: authentik-tls +spec: + secretName: authentik-tls + issuerRef: + name: letsencrypt-production + kind: ClusterIssuer + commonName: "authentik.durp.info" + dnsNames: + - "authentik.durp.info" + +--- + +kind: Service +apiVersion: v1 +metadata: + name: authentik-external-dns + annotations: + external-dns.alpha.kubernetes.io/hostname: authentik.durp.info +spec: + type: ExternalName + externalName: durp.info diff --git a/infra/authentik/templates/secrets.yaml b/infra/authentik/templates/secrets.yaml new file mode 100644 index 0000000..07b7747 --- /dev/null +++ b/infra/authentik/templates/secrets.yaml @@ -0,0 +1,28 @@ +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: authentik-secret +spec: + secretStoreRef: + name: vault + kind: ClusterSecretStore + target: + name: db-pass + data: + - secretKey: dbpass + remoteRef: + key: secrets/authentik/database + property: dbpass + - secretKey: secretkey + remoteRef: + key: secrets/authentik/database + property: secretkey + - secretKey: postgresql-postgres-password + remoteRef: + key: secrets/authentik/database + property: dbpass + - secretKey: postgresql-password + remoteRef: + key: secrets/authentik/database + property: dbpass + diff --git a/infra/authentik/values.yaml b/infra/authentik/values.yaml new file mode 100644 index 0000000..4fa183b --- /dev/null +++ b/infra/authentik/values.yaml @@ -0,0 +1,56 @@ +authentik: + global: + env: + - name: AUTHENTIK_POSTGRESQL__PASSWORD + valueFrom: + secretKeyRef: + name: db-pass + key: dbpass + - name: AUTHENTIK_SECRET_KEY + valueFrom: + secretKeyRef: + name: db-pass + key: secretkey + revisionHistoryLimit: 1 + image: + repository: registry.durp.info/goauthentik/server + pullPolicy: Always + authentik: + outposts: + container_image_base: registry.durp.info/goauthentik/%(type)s:%(version)s + postgresql: + host: '{{ .Release.Name }}-postgresql-hl' + name: "authentik" + user: "authentik" + port: 5432 + server: + name: server + replicas: 3 + worker: + replicas: 3 + postgresql: + enabled: true + image: + registry: registry.durp.info + repository: bitnami/postgresql + pullPolicy: Always + postgresqlUsername: "authentik" + postgresqlDatabase: "authentik" + existingSecret: db-pass + persistence: + enabled: true + storageClass: longhorn + accessModes: + - ReadWriteMany + redis: + enabled: true + master: + persistence: + enabled: false + image: + registry: registry.durp.info + repository: bitnami/redis + pullPolicy: Always + architecture: standalone + auth: + enabled: false diff --git a/infra/terraform/main.tf b/infra/terraform/main.tf new file mode 100644 index 0000000..9568353 --- /dev/null +++ b/infra/terraform/main.tf @@ -0,0 +1,149 @@ +terraform { + backend "http" {} + required_providers { + proxmox = { + source = "Telmate/proxmox" + version = "3.0.1-rc6" + } + } +} + +provider "proxmox" { + pm_parallel = 1 + pm_tls_insecure = true + pm_api_url = var.pm_api_url + pm_user = var.pm_user + pm_password = var.pm_password + pm_debug = false +} + +locals { + sshkeys = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDEphzWgwUZnvL6E5luKLt3WO0HK7Kh63arSMoNl5gmjzXyhG1DDW0OKfoIl0T+JZw/ZjQ7iii6tmSLFRk6nuYCldqe5GVcFxvTzX4/xGEioAyG0IiUGKy6s+9xzO8QXF0EtSNPH0nfHNKcCjgwWAzM+Lt6gW0Vqs+aU5ICuDiEchmvYPz+rBaVldJVTG7m3ogKJ2aIF7HU/pCPp5l0E9gMOw7s0ABijuc3KXLEWCYgL39jIST6pFH9ceRLmu8Xy5zXHAkkEEauY/e6ld0hlzLadiUD7zYJMdDcm0oRvenYcUlaUl9gS0569IpfsJsjCejuqOxCKzTHPJDOT0f9TbIqPXkGq3s9oEJGpQW+Z8g41BqRpjBCdBk+yv39bzKxlwlumDwqgx1WP8xxKavAWYNqNRG7sBhoWwtxYEOhKXoLNjBaeDRnO5OY5AQJvONWpuByyz0R/gTh4bOFVD+Y8WWlKbT4zfhnN70XvapRsbZiaGhJBPwByAMGg6XxSbC6xtbyligVGCEjCXbTLkeKq1w0DuItY+FBGO3J2k90OiciTVSeyiVz9J/Y03UB0gHdsMCoVNrj+9QWfrTLDhM7D5YrXUt5nj2LQTcbtf49zoQXWxUhozlg42E/FJU/Yla7y55qWizAEVyP2/Ks/PHrF679k59HNd2IJ/aicA9QnmWtLQ== ansible" + template = "Debian12-Template" + storage = "cache-domains" + emulatessd = true + format = "raw" + dnsserver = "192.168.12.1" + tags = "postgres" + vlan = 12 + postgres = { + count = 3 + name = ["postgres-01", "postgres-02", "postgres-03"] + cores = 2 + memory = "1024" + drive = 20 + node = ["mothership", "overlord", "vanguard"] + ip = ["31", "32", "33"] + } + postgres = { + count = 3 + name = ["postgres-01", "postgres-02", "postgres-03"] + cores = 4 + memory = "4096" + drive = 40 + node = ["mothership", "overlord", "vanguard"] + ip = ["34", "35", "36"] + } +} + +resource "proxmox_vm_qemu" "postgres" { + count = local.postgres.count + ciuser = "administrator" + vmid = "${local.vlan}${local.postgres.ip[count.index]}" + name = local.postgres.name[count.index] + target_node = local.postgres.node[count.index] + clone = local.template + tags = local.tags + qemu_os = "l26" + full_clone = true + os_type = "cloud-init" + agent = 1 + cores = local.postgres.cores + sockets = 1 + cpu_type = "host" + memory = local.postgres.memory + scsihw = "virtio-scsi-pci" + #bootdisk = "scsi0" + boot = "order=virtio0" + onboot = true + sshkeys = local.sshkeys + disks { + ide { + ide2 { + cloudinit { + storage = local.storage + } + } + } + virtio { + virtio0 { + disk { + size = local.postgres.drive + format = local.format + storage = local.storage + } + } + } + } + network { + id = 0 + model = "virtio" + bridge = "vmbr0" + tag = local.vlan + } + #Cloud Init Settings + ipconfig0 = "ip=192.168.${local.vlan}.${local.postgres.ip[count.index]}/24,gw=192.168.${local.vlan}.1" + searchdomain = "durp.loc" + nameserver = local.dnsserver +} + +resource "proxmox_vm_qemu" "postgres" { + count = local.postgres.count + ciuser = "administrator" + vmid = "${local.vlan}${local.postgres.ip[count.index]}" + name = local.postgres.name[count.index] + target_node = local.postgres.node[count.index] + clone = local.template + tags = local.tags + qemu_os = "l26" + full_clone = true + os_type = "cloud-init" + agent = 1 + cores = local.postgres.cores + sockets = 1 + cpu_type = "host" + memory = local.postgres.memory + scsihw = "virtio-scsi-pci" + #bootdisk = "scsi0" + boot = "order=virtio0" + onboot = true + sshkeys = local.sshkeys + disks { + ide { + ide2 { + cloudinit { + storage = local.storage + } + } + } + virtio { + virtio0 { + disk { + size = local.postgres.drive + format = local.format + storage = local.storage + } + } + } + } + network { + id = 0 + model = "virtio" + bridge = "vmbr0" + tag = local.vlan + } + #Cloud Init Settings + ipconfig0 = "ip=192.168.${local.vlan}.${local.postgres.ip[count.index]}/24,gw=192.168.${local.vlan}.1" + searchdomain = "durp.loc" + nameserver = local.dnsserver +} diff --git a/infra/terraform/variables.tf b/infra/terraform/variables.tf new file mode 100644 index 0000000..31a92e0 --- /dev/null +++ b/infra/terraform/variables.tf @@ -0,0 +1,14 @@ +variable "pm_api_url" { + description = "API URL to Proxmox provider" + type = string +} + +variable "pm_password" { + description = "Passowrd to Proxmox provider" + type = string +} + +variable "pm_user" { + description = "UIsername to Proxmox provider" + type = string +}