import * as dotenv from "dotenv"; import { cleanEnv, str } from "envalid"; import { Construct } from "constructs"; import { App, TerraformStack, S3Backend } from "cdktf"; import { HelmProvider } from "@cdktf/provider-helm/lib/provider"; import { KubernetesProvider } from "@cdktf/provider-kubernetes/lib/provider"; import { GiteaServer } from "./gitea"; import { OnePassword } from "./1password"; import { PostgresCluster } from "./postgres"; import { Longhorn } from "./longhorn"; import { AuthentikServer } from "./authentik"; import { RedisCluster } from "./redis"; import { CertManager } from "./cert-manager"; import { Manifest } from "@cdktf/provider-kubernetes/lib/manifest"; import { PiHole } from "./pihole"; import { MemcachedCluster } from "./memcached"; import { Nginx } from "./nginx"; import { Prometheus } from "./prometheus"; import { MetalLB } from "./metallb"; dotenv.config(); const env = cleanEnv(process.env, { R2_ACCESS_KEY_ID: str(), R2_SECRET_ACCESS_KEY: str(), ACCOUNT_ID: str({ desc: "Cloudflare account id." }), BUCKET: str({ desc: "The name of the R2 bucket." }), }); class Homelab extends TerraformStack { constructor(scope: Construct, id: string) { super(scope, id); const kubernetes = new KubernetesProvider(this, "kubernetes", { configPath: "~/.kube/config", }); const helm = new HelmProvider(this, "helm", { kubernetes: { configPath: "~/.kube/config", }, }); new Manifest(this, "core-dns", { provider: kubernetes, manifest: { kind: "ConfigMap", apiVersion: "v1", metadata: { name: "coredns-custom", namespace: "kube-system", }, data: { "forward.override": `forward . /etc/resolv.conf { policy sequential } `, }, }, }); new Longhorn(this, "longhorn", { namespace: "longhorn-system", name: "longhorn", version: "1.8.2", providers: { kubernetes, helm, }, }); new MetalLB(this, "metallb", { provider: helm, name: "metallb", namespace: "metallb-system", version: "0.15.2", }); new OnePassword(this, "one-password", { provider: kubernetes, }); new Nginx(this, "nginx", { provider: helm, namespace: "nginx-system", name: "ingress-nginx-internal", version: "4.13.0", }); new PiHole(this, "pihole", { namespace: "pihole-system", provider: helm, name: "pihole", version: "2.26.1", }); new Prometheus(this, "prometheus", { provider: helm, namespace: "prometheus-system", name: "prometheus-operator", version: "75.10.0", }); const certManagerApiVersion = "cert-manager.io/v1"; new CertManager(this, "cert-manager", { certManagerApiVersion, name: "cert-manager", namespace: "cert-manager", version: "1.18.2", providers: { kubernetes, helm, }, }); new PostgresCluster(this, "postgres-cluster", { certManagerApiVersion, version: "0.24.0", name: "postgres-cluster", namespace: "postgres-system", providers: { kubernetes, helm, }, storageClass: "longhorn-crypto", users: ["shahab"], primaryUser: "shahab", initSecretName: "postgres-password", }); new RedisCluster(this, "redis-cluster", { provider: helm, namespace: "redis-system", name: "redis", }); new MemcachedCluster(this, "memcached-cluster", { provider: helm, namespace: "memcached-system", name: "memcached", }); new AuthentikServer(this, "authentik-server", { provider: helm, name: "authentik", namespace: "authentik-system", version: "2025.6.3", }); new GiteaServer(this, "gitea-server", { name: "gitea", namespace: "gitea-system", provider: helm, version: "12.1.1", }); } } const app = new App(); const stack = new Homelab(app, "homelab"); new S3Backend(stack, { bucket: env.BUCKET, key: "terraform.tfstate", region: "auto", skipCredentialsValidation: true, skipMetadataApiCheck: true, skipRegionValidation: true, skipRequestingAccountId: true, skipS3Checksum: true, accessKey: env.R2_ACCESS_KEY_ID, secretKey: env.R2_SECRET_ACCESS_KEY, endpoints: { s3: `https://${env.ACCOUNT_ID}.r2.cloudflarestorage.com/homelab-terraform-state`, }, }); app.synth();