diff --git a/.github/workflows/tofu-deploy.yaml b/.github/workflows/tofu-deploy.yaml new file mode 100644 index 0000000..576c6b4 --- /dev/null +++ b/.github/workflows/tofu-deploy.yaml @@ -0,0 +1,32 @@ +name: Infrastructure Deployment on Self Hosted Kubernetes Cluster + +on: + workflow_dispatch: + push: + branches: + - task/** + - bug/** + pull_request: + branches: + - main + types: + - opened + - synchronize + - closed + +concurrency: + group: deployment + cancel-in-progress: false + +jobs: + infrastructure_deploy: + name: Infrastructure Deployment on Self Hosted Kubernetes Cluster + uses: necro-cloud/automations/.github/workflows/tofu-deploy.yml@main + with: + deployment_name: Kubernetes Infrastructure + folder_path: example + runners: cloud + pre_plan_script: tofu apply --target=module.helm -var-file terraform.tfvars.json -auto-approve + secrets: + KUBECONFIG: ${{ secrets.KUBECONFIG }} + TFVARS: ${{ secrets.TFVARS }} diff --git a/README.md b/README.md index e88ea12..40baec3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # necronizer's cloud modules -OpenTofu Modules that can be used to deploy a functioning self hosted cloud solution perfect for side projects +OpenTofu Modules that can be used to deploy a functioning self hosted cloud solution perfect for side projects. For a guide on how to use these modules, please navigate to the [example](./example) directory. # Requirements and Dependencies diff --git a/example/README.md b/example/README.md new file mode 100644 index 0000000..32ab36b --- /dev/null +++ b/example/README.md @@ -0,0 +1,21 @@ +# necronizer's cloud guide to use OpenTofu modules + +This directory mainly contains OpenTofu files on how to use the [modules](https://github.com/necro-cloud/modules) for deploying a self hosted cloud solution perfect for side projects and also is used for testing out modules when new features are being worked on. + +# Requirements and Dependencies + +The following is required to start using this repository: +1. [OpenTofu](https://opentofu.org/) - Since modules are written in OpenTofu, we deploy all components using OpenTofu +2. Kubernetes Cluster - Any kubernetes cluster can do, tested out with my [self hosted kubernetes cluster](https://github.com/necro-cloud/kubernetes) +3. [Cloudflare Token and DNS Zones](https://www.cloudflare.com/) - Currently all modules use Cloudflare for provisioning public SSL certificates using DNS01 challenge validation. +4. An SMTP Server - For sending mails using Keycloak Authentication + +# Usage Instructions: + +**Step 1:** Setup a TFVARS file, an example for which is given [here](terraform-example.tfvars.json) which will require SMTP Server details to be added along with [Cloudflare Token](https://cert-manager.io/docs/configuration/acme/dns01/cloudflare/#api-tokens) and DNS to be used. Save the file as `terraform.tfvars.json`. + +**Step 2:** Initialize the state with OpenTofu by running the following command: `tofu init` + +**Step 3:** Deploy all required CRDs using OpenTofu by executing the following command: `tofu apply --target=module.helm -var-file terraform.tfvars.json -auto-approve` + +**Step 4:** Now you can deploy all components using OpenTofu by executing the following command: `tofu apply -var-file terraform.tfvars.json -auto-approve` diff --git a/example/locals.tf b/example/locals.tf new file mode 100644 index 0000000..f6aeec3 --- /dev/null +++ b/example/locals.tf @@ -0,0 +1,14 @@ +locals { + keycloak_realm_settings = { + display_name = "Necronizer's Cloud" + application_name = "cloud" + base_url = var.keycloak_authentication_base_url + valid_login_redirect_path = var.keycloak_authentication_valid_login_redirect_path + valid_logout_redirect_path = var.keycloak_authentication_valid_logout_redirect_path + smtp_host = var.smtp_host + smtp_port = var.smtp_port + smtp_mail = var.smtp_mail + smtp_username = var.smtp_username + smtp_password = var.smtp_password + } +} diff --git a/example/main.tf b/example/main.tf new file mode 100644 index 0000000..1f3a883 --- /dev/null +++ b/example/main.tf @@ -0,0 +1,115 @@ +# Fetch the Kubernetes API Endpoint to be used for whitelisting by other modules +data "kubernetes_endpoints_v1" "kubernetes_api_endpoint" { + metadata { + name = "kubernetes" + namespace = "default" + + } +} + +# Deploy all required helm charts for deploying the infrastructure +module "helm" { + source = "git::https://github.com/necro-cloud/modules//modules/helm?ref=main" + server_node_selector = "cloud" +} + +# Setup a Cluster Issuer for all private TLS certificates +module "cluster-issuer" { + source = "git::https://github.com/necro-cloud/modules//modules/cluster-issuer?ref=main" + + depends_on = [module.helm] +} + +# Garage Deployment for an S3 compatible object storage solution +module "garage" { + source = "git::https://github.com/necro-cloud/modules//modules/garage?ref=main" + + // Certificates Details + cluster_issuer_name = module.cluster-issuer.cluster-issuer-name + cloudflare_token = var.cloudflare_token + cloudflare_email = var.cloudflare_email + domain = var.domain + + // Granting required namespaces access to the Garage cluster + access_namespaces = "postgres" + + // Configuring required configurations on the Garage Cluster + required_buckets = var.garage_required_buckets + required_access_keys = var.garage_required_access_keys + + // Whitelisting Kubernetes API Endpoints in the Network Policy + kubernetes_api_ip = one(flatten(data.kubernetes_endpoints_v1.kubernetes_api_endpoint.subset[*].address[*].ip)) + kubernetes_api_protocol = one(flatten(data.kubernetes_endpoints_v1.kubernetes_api_endpoint.subset[*].port[*].protocol)) + kubernetes_api_port = one(flatten(data.kubernetes_endpoints_v1.kubernetes_api_endpoint.subset[*].port[*].port)) +} + +# Cloudnative PG Deployment for PostgreSQL Database Solution +module "cnpg" { + source = "git::https://github.com/necro-cloud/modules//modules/cnpg?ref=main" + + // Garage Cluster Details for configuration of PITR Backups + garage_certificate_authority = module.garage.garage_internal_certificate_secret + garage_namespace = module.garage.garage_namespace + garage_configuration = "walbackups-credentials" + backup_bucket_name = "postgresql" + + // Required client details to allow access and generate credentials and certificates for + clients = [ + { + namespace = "cloud" + user = "cloud" + database = "cloud" + derRequired = false + privateKeyEncoding = "PKCS1" + } + ] + + // Certificate details for internal and ingress(pgadmin) certificates + cloudflare_token = var.cloudflare_token + cloudflare_email = var.cloudflare_email + domain = var.domain + cluster_issuer_name = module.cluster-issuer.cluster-issuer-name + + // Whitelisting Kubernetes API Endpoints in the Network Policy + kubernetes_api_ip = one(flatten(data.kubernetes_endpoints_v1.kubernetes_api_endpoint.subset[*].address[*].ip)) + kubernetes_api_protocol = one(flatten(data.kubernetes_endpoints_v1.kubernetes_api_endpoint.subset[*].port[*].protocol)) + kubernetes_api_port = one(flatten(data.kubernetes_endpoints_v1.kubernetes_api_endpoint.subset[*].port[*].port)) + + // Dependency on Garage Deployment + depends_on = [module.garage] +} + +# Keycloak Cluster Deployment for Identity Solution +module "keycloak" { + source = "git::https://github.com/necro-cloud/modules//modules/keycloak?ref=main" + + // PostgreSQL Database Details for database details + cluster_issuer_name = module.cluster-issuer.cluster-issuer-name + postgres_namespace = module.cnpg.namespace + cluster_name = module.cnpg.cluster_name + database_server_certificate_authority_name = module.cnpg.server-certificate-authority + database_client_certificate_name = "postgresql-keycloak-client-certificate" + database_credentials = "credentials-keycloak" + + // Certificate details for ingress + cloudflare_token = var.cloudflare_token + cloudflare_email = var.cloudflare_email + domain = var.domain + + // Realm Settings for auto configuration of required clients + realm_settings = local.keycloak_realm_settings + + // Dependency on CNPG PostgreSQL Deployment + depends_on = [module.cnpg] +} + +# Valkey Deployment for In Memory Storage Solution +module "valkey" { + source = "git::https://github.com/necro-cloud/modules//modules/valkey?ref=main" + + // Certificate details for TLS Authentication + cluster_issuer_name = module.cluster-issuer.cluster-issuer-name + + // Granting required namespaces access to the Valkey + access_namespaces = "cloud" +} diff --git a/example/providers.tf b/example/providers.tf new file mode 100644 index 0000000..7511879 --- /dev/null +++ b/example/providers.tf @@ -0,0 +1,29 @@ +terraform { + required_providers { + kubernetes = { + source = "hashicorp/kubernetes" + version = "2.38.0" + } + helm = { + source = "hashicorp/helm" + version = "3.1.1" + } + random = { + source = "hashicorp/random" + version = "3.7.2" + } + } + + backend "kubernetes" { + secret_suffix = "deployment" + } +} + +provider "kubernetes" { +} + +provider "helm" { +} + +provider "random" { +} diff --git a/example/variables.tf b/example/variables.tf new file mode 100644 index 0000000..f969200 --- /dev/null +++ b/example/variables.tf @@ -0,0 +1,133 @@ +# --------------- DNS SETTINGS VARIABLES --------------- # +variable "cloudflare_token" { + description = "Token for generating Ingress Certificates to be associated with MinIO Storage Solution" + type = string + nullable = false +} + +variable "cloudflare_email" { + description = "Email for generating Ingress Certificates to be associated with MinIO Storage Solution" + type = string + nullable = false +} + +variable "domain" { + description = "Domain for which Ingress Certificate is to be generated for" + type = string + nullable = false +} + +# --------------- GARAGE CONFIGURATION VARIABLES --------------- # + +variable "garage_required_access_keys" { + description = "Access Keys required to be configured within the Garage Cluster" + type = list(object({ + name = string + createBucket = bool + permissions = list(object({ + bucket = string + owner = bool + read = bool + write = bool + })) + })) + default = [ + { + name = "walbackups", + createBucket = false, + permissions = [ + { + bucket = "postgresql", + owner = true, + read = true, + write = true + } + ] + }, + { + name = "master", + createBucket = true, + permissions = [ + { + bucket = "postgresql", + owner = true, + read = true, + write = true + }, + { + bucket = "cloud", + owner = true, + read = true, + write = true + }] + }, + { + name = "cloud", + createBucket = true, + permissions = [ + { + bucket = "cloud", + owner = true, + read = true, + write = true + }, + ] + }] +} + +variable "garage_required_buckets" { + description = "Buckets to deploy in the Garage Cluster" + type = list(string) + default = ["cloud", "postgresql"] +} + +# --------------- KEYCLOAK REALM CONFIGURATION VARIABLES --------------- # + +variable "keycloak_authentication_base_url" { + description = "Base URL for Keycloak in order to use SSO Authentication with" + type = string + default = "http://localhost:5173" +} + +variable "keycloak_authentication_valid_login_redirect_path" { + description = "Valid Login Redirect Path for Keycloak in order to use SSO Authentication with" + type = string + default = "/auth/signin/callback" +} + +variable "keycloak_authentication_valid_logout_redirect_path" { + description = "Valid Logout Redirect Path for Keycloak in order to use SSO Authentication with" + type = string + default = "/auth/signout/callback" +} + +# --------------- SMTP SERVER VARIABLES --------------- # +variable "smtp_host" { + description = "Host of the SMTP Server to be used for sending mails" + type = string + nullable = false +} + +variable "smtp_port" { + description = "Port Number of the SMTP Server to be used for sending mails" + type = number + nullable = false +} + +variable "smtp_mail" { + description = "Mail ID of the SMTP Server to be used for sending mails" + type = string + nullable = false +} + +variable "smtp_username" { + description = "Username of the SMTP Server to be used for authentication" + type = string + nullable = false +} + +variable "smtp_password" { + description = "Password of the SMTP Server to be used for authentication" + type = string + nullable = false +} diff --git a/modules/cluster-issuer/README.md b/modules/cluster-issuer/README.md index cc38fca..56bb26b 100644 --- a/modules/cluster-issuer/README.md +++ b/modules/cluster-issuer/README.md @@ -10,7 +10,7 @@ Required Modules to deploy Cluster Issuer for internal certificates: | Name | Version | |------|---------| -| [kubernetes](#provider\_kubernetes) | 2.36.0 | +| [kubernetes](#provider\_kubernetes) | 2.38.0 | ## Resources diff --git a/modules/cnpg/README.md b/modules/cnpg/README.md index adf512f..ad72e77 100644 --- a/modules/cnpg/README.md +++ b/modules/cnpg/README.md @@ -11,8 +11,8 @@ Required Modules to deploy Cloudnative PG PostgreSQL Database: | Name | Version | |------|---------| -| [kubernetes](#provider\_kubernetes) | 2.36.0 | -| [random](#provider\_random) | 3.7.1 | +| [kubernetes](#provider\_kubernetes) | 2.38.0 | +| [random](#provider\_random) | 3.7.2 | ## Resources diff --git a/modules/garage/README.md b/modules/garage/README.md index 4084d56..9dc5e8a 100644 --- a/modules/garage/README.md +++ b/modules/garage/README.md @@ -9,8 +9,8 @@ Required Modules to deploy Garage Object Storage: | Name | Version | |------|---------| -| [kubernetes](#provider\_kubernetes) | 2.36.0 | -| [random](#provider\_random) | 3.7.1 | +| [kubernetes](#provider\_kubernetes) | 2.38.0 | +| [random](#provider\_random) | 3.7.2 | ## Resources diff --git a/modules/helm/README.md b/modules/helm/README.md index 4e06379..91a912b 100644 --- a/modules/helm/README.md +++ b/modules/helm/README.md @@ -11,7 +11,7 @@ OpenTofu Module to deploy the following required helm charts: | Name | Version | |------|---------| -| [helm](#provider\_helm) | 3.0.0-pre2 | +| [helm](#provider\_helm) | 3.1.1 | ## Resources diff --git a/modules/keycloak/README.md b/modules/keycloak/README.md index b0bd425..48c744c 100644 --- a/modules/keycloak/README.md +++ b/modules/keycloak/README.md @@ -11,8 +11,8 @@ Required Modules to deploy Keycloak Identity Management: | Name | Version | |------|---------| -| [kubernetes](#provider\_kubernetes) | 2.36.0 | -| [random](#provider\_random) | 3.7.1 | +| [kubernetes](#provider\_kubernetes) | 2.38.0 | +| [random](#provider\_random) | 3.7.2 | ## Resources diff --git a/modules/valkey/README.md b/modules/valkey/README.md index 7d748ec..f2be50b 100644 --- a/modules/valkey/README.md +++ b/modules/valkey/README.md @@ -9,8 +9,8 @@ Required Modules to deploy Valkey In Memory Database: | Name | Version | |------|---------| -| [kubernetes](#provider\_kubernetes) | 2.36.0 | -| [random](#provider\_random) | 3.7.1 | +| [kubernetes](#provider\_kubernetes) | 2.38.0 | +| [random](#provider\_random) | 3.7.2 | ## Resources