diff --git a/container-registry/registry-deployment.yaml b/apps/container-registry/registry-deployment.yaml similarity index 100% rename from container-registry/registry-deployment.yaml rename to apps/container-registry/registry-deployment.yaml diff --git a/container-registry/registry-storage.yaml b/apps/container-registry/registry-storage.yaml similarity index 100% rename from container-registry/registry-storage.yaml rename to apps/container-registry/registry-storage.yaml diff --git a/gittea/docker_gitea_backup.tf b/apps/gitea/docker_gitea_backup.tf similarity index 100% rename from gittea/docker_gitea_backup.tf rename to apps/gitea/docker_gitea_backup.tf diff --git a/gittea/host_prep.tf b/apps/gitea/host_prep.tf similarity index 100% rename from gittea/host_prep.tf rename to apps/gitea/host_prep.tf diff --git a/gittea/k8s_gitea.tf b/apps/gitea/k8s_gitea.tf similarity index 100% rename from gittea/k8s_gitea.tf rename to apps/gitea/k8s_gitea.tf diff --git a/gittea/providers.tf b/apps/gitea/providers.tf similarity index 100% rename from gittea/providers.tf rename to apps/gitea/providers.tf diff --git a/gittea/variables.tf b/apps/gitea/variables.tf similarity index 100% rename from gittea/variables.tf rename to apps/gitea/variables.tf diff --git a/web-app/Dockerfile b/apps/website/Dockerfile similarity index 100% rename from web-app/Dockerfile rename to apps/website/Dockerfile diff --git a/web-app/buildkitd.toml b/apps/website/buildkitd.toml similarity index 100% rename from web-app/buildkitd.toml rename to apps/website/buildkitd.toml diff --git a/web-app/cv.php b/apps/website/cv.php similarity index 100% rename from web-app/cv.php rename to apps/website/cv.php diff --git a/web-app/gnu.webp b/apps/website/gnu.webp similarity index 100% rename from web-app/gnu.webp rename to apps/website/gnu.webp diff --git a/web-app/images/jv.webp b/apps/website/images/jv.webp similarity index 100% rename from web-app/images/jv.webp rename to apps/website/images/jv.webp diff --git a/web-app/images/profile.webp b/apps/website/images/profile.webp similarity index 100% rename from web-app/images/profile.webp rename to apps/website/images/profile.webp diff --git a/web-app/index.php b/apps/website/index.php similarity index 100% rename from web-app/index.php rename to apps/website/index.php diff --git a/web-app/lang/en.php b/apps/website/lang/en.php similarity index 100% rename from web-app/lang/en.php rename to apps/website/lang/en.php diff --git a/web-app/lang/nah.php b/apps/website/lang/nah.php similarity index 100% rename from web-app/lang/nah.php rename to apps/website/lang/nah.php diff --git a/web-app/lang_helper.php b/apps/website/lang_helper.php similarity index 100% rename from web-app/lang_helper.php rename to apps/website/lang_helper.php diff --git a/web-app/partials/footer.php b/apps/website/partials/footer.php similarity index 100% rename from web-app/partials/footer.php rename to apps/website/partials/footer.php diff --git a/web-app/partials/header.php b/apps/website/partials/header.php similarity index 100% rename from web-app/partials/header.php rename to apps/website/partials/header.php diff --git a/web-app/partials/translation_ui.php b/apps/website/partials/translation_ui.php similarity index 100% rename from web-app/partials/translation_ui.php rename to apps/website/partials/translation_ui.php diff --git a/web-app/save_lang.php b/apps/website/save_lang.php similarity index 100% rename from web-app/save_lang.php rename to apps/website/save_lang.php diff --git a/web-app/styles.css b/apps/website/styles.css similarity index 100% rename from web-app/styles.css rename to apps/website/styles.css diff --git a/web-app/translation.js b/apps/website/translation.js similarity index 100% rename from web-app/translation.js rename to apps/website/translation.js diff --git a/web-app/web-app.yaml b/apps/website/web-app.yaml similarity index 100% rename from web-app/web-app.yaml rename to apps/website/web-app.yaml diff --git a/argocd/main.tf b/argocd/main.tf deleted file mode 100644 index 9420823..0000000 --- a/argocd/main.tf +++ /dev/null @@ -1,135 +0,0 @@ -resource "kubernetes_namespace" "argocd" { - metadata { - name = "argocd" - } -} - -data "http" "argocd_manifest" { - url = "https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml" -} - -resource "kubernetes_manifest" "argocd_core" { - for_each = { for idx, doc in provider::kubernetes::manifest_decode_multi(data.http.argocd_manifest.response_body) : idx => doc } - - manifest = merge( - each.value, - contains(["ClusterRole", "ClusterRoleBinding", "CustomResourceDefinition", "Namespace"], lookup(each.value, "kind", "")) ? {} : { - metadata = merge( - try(each.value.metadata, {}), - { - namespace = kubernetes_namespace.argocd.metadata[0].name - } - ) - }, - lookup(each.value, "kind", "") == "Service" && lookup(try(each.value.metadata, {}), "name", "") == "argocd-server" ? { - spec = merge( - try(each.value.spec, {}), - { - type = "NodePort" - ports = [ - { - name = "http" - port = 80 - protocol = "TCP" - targetPort = 8080 - nodePort = 30501 - }, - { - name = "https" - port = 443 - protocol = "TCP" - targetPort = 8080 - } - ] - } - ) - } : {} - ) - - field_manager { - force_conflicts = true - } - - depends_on = [kubernetes_namespace.argocd] -} - -resource "kubernetes_secret_v1" "argocd_private_repo" { - metadata { - name = "my-homelab-repo-secret" - namespace = kubernetes_namespace.argocd.metadata[0].name - labels = { - "argocd.argoproj.io/secret-type" = "repository" - } - } - - data = { - type = "git" - url = "http://192.168.100.68:30300/jv/my-homelab-configs" - username = "jv" - password = "Summer12#$" - } - - depends_on = [kubernetes_manifest.argocd_core] -} - -resource "kubernetes_manifest" "argocd_app_registry" { - manifest = { - apiVersion = "argoproj.io/v1alpha1" - kind = "Application" - metadata = { - name = "container-registry" - namespace = "argocd" - } - spec = { - project = "default" - source = { - repoURL = "http://192.168.100.68:30300/jv/my-homelab-configs" - targetRevision = "HEAD" - path = "container-registry" # Points to the folder containing your registry YAMLs - } - destination = { - server = "https://kubernetes.default.svc" - namespace = "container-registry" # Deploys into this namespace - } - syncPolicy = { - automated = { - prune = true - selfHeal = true - } - syncOptions = ["CreateNamespace=true"] - } - } - } - depends_on = [kubernetes_manifest.argocd_core] -} - -resource "kubernetes_manifest" "argocd_app_web_app" { - manifest = { - apiVersion = "argoproj.io/v1alpha1" - kind = "Application" - metadata = { - name = "php-web-app" - namespace = "argocd" - } - spec = { - project = "default" - source = { - repoURL = "http://192.168.100.68:30300/jv/my-homelab-configs" - targetRevision = "HEAD" - path = "web-app" # ArgoCD ignores the PHP/Docker files and grabs web-app.yaml - } - destination = { - server = "https://kubernetes.default.svc" - namespace = "default" - } - syncPolicy = { - automated = { - prune = true - selfHeal = true - } - syncOptions = ["CreateNamespace=true"] - } - } - } - depends_on = [kubernetes_manifest.argocd_core] -} diff --git a/argocd/providers.tf b/argocd/providers.tf deleted file mode 100644 index e3fca5f..0000000 --- a/argocd/providers.tf +++ /dev/null @@ -1,13 +0,0 @@ -terraform { - required_providers { - kubernetes = { - source = "hashicorp/kubernetes" - version = "~> 2.24" - } - } -} - -provider "kubernetes" { - config_path = "~/.kube/config" - config_context = "kubernetes-admin@kubernetes" -} diff --git a/bootstrap/apps/main.tf b/bootstrap/apps/main.tf new file mode 100644 index 0000000..86c4cdd --- /dev/null +++ b/bootstrap/apps/main.tf @@ -0,0 +1,74 @@ +terraform { + required_version = ">= 1.0" + required_providers { + kubernetes = { + source = "hashicorp/kubernetes" + version = "~> 2.26" + } + } +} + +provider "kubernetes" { + config_path = "/home/jv/.kube/config" +} + +resource "kubernetes_manifest" "container_registry" { + manifest = { + apiVersion = "argoproj.io/v1alpha1" + kind = "Application" + metadata = { + name = "container-registry" + namespace = "argocd" + } + spec = { + project = "default" + source = { + repoURL = "https://github.com/juvdiaz/my-homelab-configs.git" + targetRevision = "HEAD" + path = "apps/container-registry" + } + destination = { + server = "https://kubernetes.default.svc" + namespace = "container-registry" + } + syncPolicy = { + automated = { + prune = true + selfHeal = true + } + syncOptions = ["CreateNamespace=true"] + } + } + } +} + +resource "kubernetes_manifest" "production_website" { + depends_on = [kubernetes_manifest.container_registry] + manifest = { + apiVersion = "argoproj.io/v1alpha1" + kind = "Application" + metadata = { + name = "production-website" + namespace = "argocd" + } + spec = { + project = "default" + source = { + repoURL = "https://github.com/juvdiaz/my-homelab-configs.git" + targetRevision = "HEAD" + path = "apps/website" + } + destination = { + server = "https://kubernetes.default.svc" + namespace = "website-production" + } + syncPolicy = { + automated = { + prune = true + selfHeal = true + } + syncOptions = ["CreateNamespace=true"] + } + } + } +} diff --git a/bootstrap/cluster/main.tf b/bootstrap/cluster/main.tf new file mode 100644 index 0000000..3037668 --- /dev/null +++ b/bootstrap/cluster/main.tf @@ -0,0 +1,75 @@ +terraform { + required_version = ">= 1.0" + required_providers { + null = { + source = "hashicorp/null" + version = "~> 3.2" + } + external = { + source = "hashicorp/external" + version = "~> 2.3" + } + } +} + +resource "null_resource" "kubeadm_control_plane" { + provisioner "local-exec" { + command = < /tmp/join.sh", + "sudo sh /tmp/join.sh", + "rm -f /tmp/join.sh" + ] + } + + provisioner "remote-exec" { + when = destroy + inline = [ + "sudo kubeadm reset --force", + "sudo iptables -F && sudo iptables -t nat -F && sudo iptables -t mangle -F && sudo iptables -X", + "sudo rm -rf /var/lib/kubelet/ /var/lib/cni/ /etc/cni/net.d" + ] + } +} diff --git a/bootstrap/platform/main.tf b/bootstrap/platform/main.tf new file mode 100644 index 0000000..38190b7 --- /dev/null +++ b/bootstrap/platform/main.tf @@ -0,0 +1,108 @@ +terraform { + required_version = ">= 1.0" + required_providers { + helm = { + source = "hashicorp/helm" + version = "~> 2.12" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = "~> 2.26" + } + } +} + +provider "kubernetes" { + config_path = "/home/jv/.kube/config" +} + +provider "helm" { + kubernetes { + config_path = "/home/jv/.kube/config" + } +} + +resource "helm_release" "cilium" { + name = "cilium" + repository = "https://helm.cilium.io/" + chart = "cilium" + namespace = "kube-system" + + set { + name = "operator.replicas" + value = "1" + } +} + +resource "helm_release" "longhorn" { + depends_on = [helm_release.cilium] + name = "longhorn" + repository = "https://charts.longhorn.io" + chart = "longhorn" + namespace = "longhorn-system" + create_namespace = true + timeout = 600 + + # Scale configurations down for our small 2-node footprint + set { + name = "csi.attacherReplicaCount" + value = "1" + } + set { + name = "csi.provisionerReplicaCount" + value = "1" + } + set { + name = "csi.resizerReplicaCount" + value = "1" + } + set { + name = "csi.snapshotterReplicaCount" + value = "1" + } + set { + name = "defaultSettings.defaultReplicaCount" + value = "1" + } + + # Global Tolerations to allow Longhorn structural pods to map onto control planes + set { + name = "global.tolerations[0].key" + value = "node-role.kubernetes.io/control-plane" + } + set { + name = "global.tolerations[0].operator" + value = "Exists" + } + set { + name = "global.tolerations[0].effect" + value = "NoSchedule" + } +} + +resource "helm_release" "argocd" { + depends_on = [helm_release.longhorn] + name = "argocd" + repository = "https://argoproj.github.io/argo-helm" + chart = "argo-cd" + namespace = "argocd" + create_namespace = true +} + +resource "kubernetes_secret_v1" "argocd_private_repo" { + depends_on = [helm_release.argocd] + metadata { + name = "my-homelab-repo-secret" + namespace = "argocd" + labels = { + "argocd.argoproj.io/secret-type" = "repository" + } + } + + data = { + type = "git" + url = "http://192.168.100.68:30300/jv/my-homelab-configs" + username = "jv" + password = "Summer12#$" + } +} diff --git a/lab.sh b/lab.sh new file mode 100755 index 0000000..7bdd337 --- /dev/null +++ b/lab.sh @@ -0,0 +1,64 @@ +up() { + echo "Deploying the homelab infrastructure..." + + cd bootstrap/cluster + tofu init + tofu apply -auto-approve + + cd ../platform + tofu init + tofu apply -auto-approve + + cd ../apps + tofu init + tofu apply -auto-approve + + cd ../.. + echo "Deployment successfully completed!" +} + +nuke() { + echo "Brutally nuking the homelab infrastructure..." + + echo "--> Terminating local OpenTofu tasks..." + killall tofu terraform 2>/dev/null || true + + echo "--> Eviscerating local Kubernetes components (Laptop)..." + sudo kubeadm reset --force || true + sudo systemctl stop containerd 2>/dev/null || true + sudo killall containerd-shim-runc-v2 2>/dev/null || true + + sudo umount /var/lib/containerd/srun/* 2>/dev/null || true + sudo rm -rf /var/lib/containerd/* /run/containerd/* + sudo rm -rf /etc/kubernetes/ /var/lib/etcd/ /var/lib/kubelet/ /var/lib/cni/ /etc/cni/net.d /home/jv/.kube/ + + sudo iptables -F && sudo iptables -t nat -F && sudo iptables -t mangle -F && sudo iptables -X + sudo ip link delete cilium_host 2>/dev/null || true + sudo ip link delete cilium_net 2>/dev/null || true + sudo ip link delete cilium_vxlan 2>/dev/null || true + + sudo systemctl start containerd + + echo "--> Eviscerating remote Kubernetes components (Raspberry Pi)..." + ssh -o ConnectTimeout=5 jv@192.168.100.89 << 'EOF' 2>/dev/null || true + sudo kubeadm reset --force + sudo killall containerd-shim-runc-v2 2>/dev/null || true + sudo rm -rf /var/lib/kubelet/ /var/lib/cni/ /etc/cni/net.d /var/lib/containerd/* + sudo iptables -F && sudo iptables -t nat -F && sudo iptables -t mangle -F && sudo iptables -X +EOF + + echo "--> Deleting OpenTofu tracking state files..." + rm -rf bootstrap/cluster/terraform.tfstate* + rm -rf bootstrap/cluster/.terraform/ + rm -rf bootstrap/cluster/.terraform.lock.hcl + + rm -rf bootstrap/platform/terraform.tfstate* + rm -rf bootstrap/platform/.terraform/ + rm -rf bootstrap/platform/.terraform.lock.hcl + + rm -rf bootstrap/apps/terraform.tfstate* + rm -rf bootstrap/apps/.terraform/ + rm -rf bootstrap/apps/.terraform.lock.hcl + + echo "Destruction complete! Your hardware is completely sanitized." +}