Author SHA1 Message Date
pierre.geeraert 5289cab76e using env files but overcomplicated 2026-10-08 11:31:43 +01:00
34 changed files with 6592 additions and 1251 deletions
-3
View File
@@ -41,6 +41,3 @@ terraform.tfstate*
.terraform.lock.hcl .terraform.lock.hcl
.bw-provider-state .bw-provider-state
.claude
+1 -1
View File
@@ -55,7 +55,7 @@ variable "kubernetes" {
service_port = optional(list(number)) service_port = optional(list(number))
service_type = optional(string, "ClusterIP") service_type = optional(string, "ClusterIP")
service_name = optional(string) service_name = optional(string)
domain_name = optional(list(string)) domain_name = optional(string)
liveness_tcp_socket = optional(number) liveness_tcp_socket = optional(number)
liveness_http_get = optional(string) liveness_http_get = optional(string)
liveness_http_get_path = optional(string) liveness_http_get_path = optional(string)
+11 -2
View File
@@ -4,6 +4,7 @@ kubernetes = {
replicas = 01 replicas = 01
image = "linuxserver/bookstack:latest" image = "linuxserver/bookstack:latest"
service_port = [80, 443] service_port = [80, 443]
domain_name = "bookstack"
database = { database = {
"engine" = "mysql" "engine" = "mysql"
"image" = "lscr.io/linuxserver/mariadb" "image" = "lscr.io/linuxserver/mariadb"
@@ -99,6 +100,7 @@ kubernetes = {
enabled = false enabled = false
name = "stirling-pdf" name = "stirling-pdf"
image = "stirlingtools/stirling-pdf:2.0.0" image = "stirlingtools/stirling-pdf:2.0.0"
domain_name = "stirling"
service_port = [8080] service_port = [8080]
environment = { environment = {
@@ -193,6 +195,7 @@ kubernetes = {
onitama = { onitama = {
enabled = false enabled = false
namespace = "onitama" namespace = "onitama"
domain_name = "onitama"
image = "ghcr.io/jackadamson/onitama:latest" image = "ghcr.io/jackadamson/onitama:latest"
service_port = [8080] service_port = [8080]
requirements = { requirements = {
@@ -339,7 +342,7 @@ kubernetes = {
#replicas = 0 #replicas = 0
image = "ghcr.io/paperless-ngx/paperless-ngx:2.18.4" image = "ghcr.io/paperless-ngx/paperless-ngx:2.18.4"
service_port = [8000] service_port = [8000]
domain_name = ["paperless2"] domain_name = "paperless2"
database = { database = {
image = "postgres:15.6" image = "postgres:15.6"
mountPath = "/var/lib/postgresql/data" mountPath = "/var/lib/postgresql/data"
@@ -588,7 +591,7 @@ kubernetes = {
namespace = "next" namespace = "next"
#replicas = 0 #replicas = 0
image = "nextcloud:29.0.3-apache" image = "nextcloud:29.0.3-apache"
domain_name = ["next"] domain_name = "next"
service_port = [80] service_port = [80]
#extra_manifest = ["/opt/kubernetes/Nextcloud_kube/next.secret.yaml"] #extra_manifest = ["/opt/kubernetes/Nextcloud_kube/next.secret.yaml"]
secret_ref = ["nextcloud-credentials"] secret_ref = ["nextcloud-credentials"]
@@ -1141,6 +1144,7 @@ kubernetes = {
#enabled = false #enabled = false
image = "ghcr.io/requarks/wiki:2.5" image = "ghcr.io/requarks/wiki:2.5"
service_port = [3000] service_port = [3000]
#domain_name = "wikijs"
extra_manifest = ["/opt/kubernetes/Terraform_kube/external_manifests/wikijs/wikijs-db.secret.yaml"] extra_manifest = ["/opt/kubernetes/Terraform_kube/external_manifests/wikijs/wikijs-db.secret.yaml"]
database = { database = {
image = "postgres:17" image = "postgres:17"
@@ -1931,6 +1935,7 @@ kubernetes = {
#disabled because it needs AI to import a pdf and AI integration is not working #disabled because it needs AI to import a pdf and AI integration is not working
enabled = false enabled = false
replicas = 01 replicas = 01
domain_name = "reactive"
image = "ghcr.io/amruthpillai/reactive-resume:latest" image = "ghcr.io/amruthpillai/reactive-resume:latest"
service_port = [3000] service_port = [3000]
environment = { environment = {
@@ -1963,6 +1968,7 @@ kubernetes = {
replicas = 01 replicas = 01
image = "opencloudeu/opencloud-rolling:latest" image = "opencloudeu/opencloud-rolling:latest"
service_port = [9200] service_port = [9200]
#domain_name = "opencloud"
environment = { environment = {
#IDM_CREATE_DEMO_USERS = { #IDM_CREATE_DEMO_USERS = {
@@ -2003,6 +2009,7 @@ kubernetes = {
replicas = 0 replicas = 0
image = "owncloud/server" image = "owncloud/server"
service_port = [8080] service_port = [8080]
domain_name = "owncloud"
database = { database = {
"engine" = "mysql" "engine" = "mysql"
"image" = "lscr.io/linuxserver/mariadb" "image" = "lscr.io/linuxserver/mariadb"
@@ -2058,6 +2065,7 @@ kubernetes = {
replicas = 01 replicas = 01
image = "kopia/kopia" image = "kopia/kopia"
service_port = [51515] service_port = [51515]
domain_name = "kopia"
command = ["start", "--disable-csrf-token-checks", "--insecure", "--address=0.0.0.0:51515", "--server-username=USERNAME", "--server-password=SECRET_PASSWORD"] command = ["start", "--disable-csrf-token-checks", "--insecure", "--address=0.0.0.0:51515", "--server-username=USERNAME", "--server-password=SECRET_PASSWORD"]
environment = { environment = {
KOPIA_PASSWORD = { KOPIA_PASSWORD = {
@@ -2088,6 +2096,7 @@ kubernetes = {
replicas = 01 replicas = 01
image = "ghcr.io/degoog-org/degoog:latest" image = "ghcr.io/degoog-org/degoog:latest"
service_port = [4444] service_port = [4444]
domain_name = "degoog"
environment = { environment = {
DEGOOG_SETTINGS_PASSWORDS = { DEGOOG_SETTINGS_PASSWORDS = {
value = "Crease1-City-Canned" value = "Crease1-City-Canned"
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+20 -8
View File
@@ -43,7 +43,7 @@ resource "kubernetes_deployment_v1" "database-automatic" {
volume_mount { volume_mount {
mount_path = try(each.value.database.mountPath, "/var/lib/postgresql/") mount_path = try(each.value.database.mountPath, "/var/lib/postgresql/")
name = "${each.key}-db-volume" name = "${each.key}-db-pvc"
} }
dynamic "volume_mount" { dynamic "volume_mount" {
@@ -57,6 +57,17 @@ resource "kubernetes_deployment_v1" "database-automatic" {
command = try([each.value.database.command], []) command = try([each.value.database.command], [])
args = each.value.database_args != null ? each.value.database_args : [] args = each.value.database_args != null ? each.value.database_args : []
dynamic "env_from" {
for_each = each.value.database != null && each.value.enabled == true && !(try(each.value.database.shunt, false)) ? ["${each.key}-db-terraform"] : []
content {
dynamic "secret_ref" {
for_each = [1]
content {
name = env_from.value
}
}
}
}
dynamic "env" { dynamic "env" {
for_each = each.value.environment != null ? each.value.environment : {} for_each = each.value.environment != null ? each.value.environment : {}
@@ -71,6 +82,7 @@ resource "kubernetes_deployment_v1" "database-automatic" {
content { content {
name = env.value.value_from.secret_key_ref.name name = env.value.value_from.secret_key_ref.name
key = env.value.value_from.secret_key_ref.key key = env.value.value_from.secret_key_ref.key
# optional = true
} }
} }
} }
@@ -84,9 +96,9 @@ resource "kubernetes_deployment_v1" "database-automatic" {
volume { volume {
name = "${each.key}-db-volume" name = "${each.key}-db-pvc"
host_path { persistent_volume_claim {
path = try(each.value.database.host_path, join("/", [var.storage_path.main_storage, coalesce(each.value.namespace, each.value.connected_namespace, each.key), join("-", [each.key, "db"])])) claim_name = "${each.key}-db-pvc"
} }
} }
@@ -95,8 +107,8 @@ resource "kubernetes_deployment_v1" "database-automatic" {
content { content {
name = "${each.key}-db-backup" name = "${each.key}-db-backup"
host_path { persistent_volume_claim {
path = join("/", [var.storage_path.fast_access, "Backup", coalesce(each.value.namespace, each.value.connected_namespace, each.key), "${each.key}-db-backup"]) claim_name = "${each.key}-db-backup"
} }
} }
} }
@@ -114,7 +126,7 @@ resource "docker_container" "database-automatic" {
hostname = "${coalesce(each.value.name, each.key)}-db" hostname = "${coalesce(each.value.name, each.key)}-db"
networks_advanced { networks_advanced {
name = docker_network.terraform_network[0].name name = docker_network.terraform_network.name
} }
#no ports as they should be able to speak within the same network #no ports as they should be able to speak within the same network
@@ -131,4 +143,4 @@ resource "docker_container" "database-automatic" {
] ]
} }
+43 -9
View File
@@ -46,7 +46,7 @@ resource "kubernetes_deployment_v1" "automatic" {
for_each = each.value.pvc != null ? each.value.pvc : {} for_each = each.value.pvc != null ? each.value.pvc : {}
content { content {
mount_path = volume_mount.value.mount_path mount_path = volume_mount.value.mount_path
name = "${volume_mount.key}-volume" name = "${volume_mount.value.name}-pvc"
sub_path = volume_mount.value.sub_path != null ? volume_mount.value.sub_path : "" sub_path = volume_mount.value.sub_path != null ? volume_mount.value.sub_path : ""
} }
} }
@@ -71,6 +71,29 @@ resource "kubernetes_deployment_v1" "automatic" {
} }
} }
dynamic "env_from" {
for_each = each.value.database != null && each.value.enabled == true && !(try(each.value.database.shunt, false)) ? ["${each.key}-db-terraform"] : []
#for_each = each.value.database != null && each.value.enabled == true ? ["${each.key}-db-terraform"] : []
content {
dynamic "secret_ref" {
for_each = [1]
content {
name = env_from.value
}
}
}
}
dynamic "env_from" {
for_each = each.value.database != null && each.value.enabled == true ? ["${each.key}-db-mapped-terraform"] : []
content {
dynamic "secret_ref" {
for_each = [1]
content {
name = env_from.value
}
}
}
}
dynamic "env_from" { dynamic "env_from" {
for_each = each.value.config_map_ref != null ? each.value.config_map_ref : [] for_each = each.value.config_map_ref != null ? each.value.config_map_ref : []
content { content {
@@ -166,27 +189,33 @@ resource "kubernetes_deployment_v1" "automatic" {
dynamic "volume" { dynamic "volume" {
for_each = each.value.pvc != null ? each.value.pvc : {} for_each = each.value.pvc != null ? each.value.pvc : {}
content { content {
name = "${volume.key}-volume" name = "${volume.value.name}-pvc"
dynamic "persistent_volume_claim" {
for_each = volume.value.pvc ? [1] : []
content {
claim_name = "${volume.value.name}-pvc"
}
}
dynamic "config_map" { dynamic "config_map" {
for_each = volume.value.config_map ? [1] : [] for_each = volume.value.config_map ? [1] : []
content { content {
name = volume.key name = volume.value.name
} }
} }
dynamic "host_path" { dynamic "host_path" {
for_each = volume.value.host_path != null || (!(volume.value.config_map) && !(volume.value.secret)) ? [1] : [] for_each = volume.value.host_path != null ? [1] : []
content { content {
path = coalesce(volume.value.host_path, join("/", [var.storage_path.main_storage, coalesce(each.value.namespace, each.value.connected_namespace, each.key), volume.key])) path = volume.value.host_path
} }
} }
dynamic "secret" { dynamic "secret" {
for_each = volume.value.secret ? [1] : [] for_each = volume.value.secret ? [1] : []
content { content {
secret_name = volume.key secret_name = volume.value.name
} }
} }
@@ -197,8 +226,8 @@ resource "kubernetes_deployment_v1" "automatic" {
content { content {
name = "${each.key}-db-backup" name = "${each.key}-db-backup"
host_path { persistent_volume_claim {
path = join("/", [var.storage_path.fast_access, "Backup", coalesce(each.value.namespace, each.value.connected_namespace, each.key), "${each.key}-db-backup"]) claim_name = "${each.key}-db-backup"
} }
} }
} }
@@ -206,6 +235,11 @@ resource "kubernetes_deployment_v1" "automatic" {
} }
} }
} }
depends_on = [
kubernetes_persistent_volume_claim_v1.automatic-pvc,
kubernetes_config_map_v1.env_file,
kubernetes_secret_v1.env_file,
]
} }
+49
View File
@@ -0,0 +1,49 @@
# Plain KEY=VALUE files (docker --env-file semantics, one pair per line, # comments)
# kept in external_manifests/, rendered into a ConfigMap or Secret at apply time.
# Deployments consume them through the existing config_map_ref / secret_ref fields.
variable "env_files" {
type = map(object({
namespace = string
path = string # relative to this module, e.g. ../external_manifests/bitwarden/global.env
secret = optional(bool, false)
enabled = optional(bool, true)
}))
default = {}
}
locals {
env_files = { for name, f in var.env_files : name => f if f.enabled }
# A duplicate key inside one file fails the plan on purpose.
env_data = {
for name, f in local.env_files : name => {
for line in split("\n", replace(file("${path.module}/${f.path}"), "\r", "")) :
split("=", line)[0] => substr(line, length(split("=", line)[0]) + 1, -1)
if can(regex("^[A-Za-z_][^=\\s]*=", line))
}
}
}
resource "kubernetes_config_map_v1" "env_file" {
for_each = { for name, f in local.env_files : name => f if !f.secret }
metadata {
name = each.key
namespace = each.value.namespace
labels = {
deployment_method = "Terraform"
}
}
data = local.env_data[each.key]
}
resource "kubernetes_secret_v1" "env_file" {
for_each = { for name, f in local.env_files : name => f if f.secret }
metadata {
name = each.key
namespace = each.value.namespace
labels = {
deployment_method = "Terraform"
}
}
data = local.env_data[each.key]
}
-73
View File
@@ -1,73 +0,0 @@
resource "helm_release" "cert_manager" {
name = "cert-manager"
repository = "oci://quay.io"
chart = "jetstack/charts/cert-manager"
version = "v1.21.2"
namespace = "cert-manager"
create_namespace = true
wait = false
set = [
{
name = "crds.enabled"
value = "true"
}
]
}
resource "helm_release" "nginx_ingress" {
name = "traefik"
repository = "https://traefik.github.io/charts"
chart = "traefik"
version = "v41.7.1"
namespace = "traefik"
create_namespace = true
wait = false
set = [
{
name = "ports.web.nodePort"
value = "80"
},
{
name = "ports.websecure.nodePort"
value = "443"
},
{
name = "service.type"
value = "NodePort"
}
]
}
resource "kubernetes_manifest" "letsencrypt_prod" {
manifest = {
"apiVersion" = "cert-manager.io/v1"
"kind" = "ClusterIssuer"
"metadata" = {
"name" = "letsencrypt-prod"
}
"spec" = {
"acme" = {
"email" = "franckrobbin6@gmail.com"
"privateKeySecretRef" = {
"name" = "letsencrypt-prod-account-key"
}
"server" = "https://acme-v02.api.letsencrypt.org/directory"
"solvers" = [
{
"http01" = {
"ingress" = {
"class" = "traefik"
}
}
}
]
}
}
}
}
+35 -32
View File
@@ -15,11 +15,6 @@ provider "kubernetes" {
provider "docker" { provider "docker" {
host = "unix:///var/run/docker.sock" host = "unix:///var/run/docker.sock"
} }
provider "helm" {
kubernetes = {
config_path = "~/.kube/config"
}
}
variable "kubernetes" { variable "kubernetes" {
type = map(object({ type = map(object({
@@ -27,13 +22,15 @@ variable "kubernetes" {
docker = optional(bool) docker = optional(bool)
image = string image = string
pvc = optional(map(object({ pvc = optional(map(object({
name = optional(string) name = string
pvc = optional(bool, false)
config_map = optional(bool, false) config_map = optional(bool, false)
secret = optional(bool, false) secret = optional(bool, false)
local_path = optional(bool, false)
host_path = optional(string) host_path = optional(string)
pvc_size = optional(string)
storage_class_name = optional(string, "nfs-storage-intelligent") storage_class_name = optional(string, "nfs-storage-intelligent")
annotations_fileType = optional(string) annotations_fileType = optional(string)
existing_pvc = optional(bool, false)
mount_path = string mount_path = string
sub_path = optional(string) sub_path = optional(string)
}))) })))
@@ -55,9 +52,7 @@ variable "kubernetes" {
external_port = optional(bool, false) external_port = optional(bool, false)
service_type = optional(string, "ClusterIP") service_type = optional(string, "ClusterIP")
service_name = optional(string) service_name = optional(string)
domain_name = optional(list(string)) domain_name = optional(string)
legacy_domain = optional(bool, false)
exposed = optional(bool, true)
liveness_tcp_socket = optional(number) liveness_tcp_socket = optional(number)
liveness_http_get = optional(string) liveness_http_get = optional(string)
liveness_http_get_path = optional(string) liveness_http_get_path = optional(string)
@@ -80,19 +75,39 @@ variable "kubernetes" {
} }
variable "shunt_docker" {
type = bool
default = true
}
variable "storage_path" { locals {
type = map(string) pvc_list = flatten([
default = { for key, value in var.kubernetes : [
main_storage = "/data/kubernetes", for index, pvc in value.pvc : {
fast_access = "/ssd" key = "${coalesce(value.namespace, value.connected_namespace, key)}/${pvc.name}"
index = index
pvc = pvc.pvc
name = pvc.name
pvc_size = pvc.pvc_size
mount_path = pvc.mount_path
storage_class_name = pvc.storage_class_name
annotations_fileType = pvc.annotations_fileType
existing_pvc = pvc.existing_pvc
sub_path = pvc.sub_path
namespace = coalesce(value.namespace, value.connected_namespace, key)
}] if value.enabled == true && value.pvc != null && value.docker != true
])
# group duplicates instead of throwing an error
pvc_map_grouped = {
for p in local.pvc_list :
p.key => p...
} }
}
# keep only one PVC per key (take the first)
pvc_map = {
for k, list in local.pvc_map_grouped :
k => list[0]
}
pvc_details = values(local.pvc_map)
}
locals { locals {
env_details = flatten([ env_details = flatten([
@@ -129,15 +144,3 @@ resource "kubernetes_manifest" "manifest" {
provider = kubernetes provider = kubernetes
} }
resource "kubernetes_namespace_v1" "automatic" {
for_each = { for key, value in var.kubernetes : key => value if value.enabled == true && value.connected_namespace == "" }
metadata {
annotations = {
name = coalesce(each.value.namespace, each.key)
}
labels = {
deployment_method = "Terraform"
}
name = coalesce(each.value.namespace, each.key)
}
}
+4 -4
View File
@@ -44,7 +44,7 @@ resource "kubernetes_deployment_v1" "redis-automatic" {
volume_mount { volume_mount {
mount_path = "/data" mount_path = "/data"
name = "${each.key}-redis-volume" name = "${each.key}-redis-pvc"
} }
@@ -112,9 +112,9 @@ resource "kubernetes_deployment_v1" "redis-automatic" {
volume { volume {
name = "${each.key}-redis-volume" name = "${each.key}-redis-pvc"
host_path { persistent_volume_claim {
path = try(each.value.redis.host_path, join("/", [var.storage_path.main_storage, coalesce(each.value.namespace, each.value.connected_namespace, each.key), join("-", [each.key, "redis"])])) claim_name = "${each.key}-redis-pvc"
} }
} }
+84 -9
View File
@@ -1,18 +1,93 @@
module "ingress" { resource "kubernetes_service_v1" "automatic_service" {
source = "../modules/ingress" for_each = { for key, value in var.kubernetes : key => value if value.service_port != null && value.enabled == true && value.docker != true }
kubernetes_input = var.kubernetes metadata {
name = "${each.key}-svc"
namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key)
labels = {
deployment_method = "Terraform"
}
annotations = each.value.service_type == "LoadBalancer" ? {
"metallb.universe.tf/ip-allocated-from-pool" = "first-pool"
} : {}
}
spec {
selector = {
app = each.key
}
dynamic "port" {
for_each = each.value.service_port != null ? each.value.service_port : []
content {
port = port.value
target_port = port.value
name = replace("${port.value}${each.key}", "/(.{0,15})(.*)/", "$1")
}
}
# port {
# port = each.value.service_port
# target_port = each.value.service_port
# }
type = each.value.service_type
}
}
resource "kubernetes_service_v1" "automatic_service_database" {
for_each = { for key, value in var.kubernetes : key => value if value.database != null && value.enabled == true && !(try(value.database.shunt, false)) && value.docker != true }
metadata {
name = "${each.key}-db-svc"
namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key)
labels = {
deployment_method = "Terraform"
#username = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_password[each.key].key}"
}
}
spec {
selector = {
app = "${each.key}-db"
}
port {
port = try(each.value.database.port, 5432)
target_port = try(each.value.database.port, 5432)
}
}
} }
module "services" {
source = "../modules/services" resource "kubernetes_service_v1" "automatic_service_redis" {
kubernetes_input = var.kubernetes for_each = { for key, value in var.kubernetes : key => value if value.redis != null && value.enabled == true && value.docker != true }
metadata {
name = "${each.key}-redis-svc"
namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key)
labels = {
deployment_method = "Terraform"
}
}
spec {
selector = {
app = "${each.key}-redis"
}
port {
port = 6379
target_port = 6379
}
}
} }
resource "docker_network" "terraform_network" { resource "docker_network" "terraform_network" {
#avoiding this to create if the shunt_docker is on name = "deployment_network"
count = var.shunt_docker ? 0 : 1
name = "deployment_network"
} }
+86
View File
@@ -0,0 +1,86 @@
resource "kubernetes_persistent_volume_claim_v1" "automatic-pvc" {
for_each = { for key, value in local.pvc_details : "${value.index}" => merge(value, { mew_key = value.index }) if value.pvc && value.existing_pvc != true && value.docker != true }
metadata {
namespace = coalesce(each.value.namespace, each.key)
name = "${each.value.name}-pvc"
labels = {
deployment_method = "Terraform"
}
annotations = {
fileType = try(each.value.annotations_fileType, "file")
}
}
spec {
access_modes = ["ReadWriteMany"]
storage_class_name = each.value.storage_class_name
resources {
requests = {
storage = each.value.pvc_size
}
}
}
}
resource "kubernetes_persistent_volume_claim_v1" "automatic-pvc-database" {
for_each = { for key, value in var.kubernetes : key => value if value.database != null && value.enabled == true && !(try(value.database.shunt, false)) && value.docker != true }
metadata {
namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key)
name = "${each.key}-db-pvc"
labels = {
deployment_method = "Terraform"
}
}
spec {
access_modes = ["ReadWriteMany"]
storage_class_name = "nfs-storage-intelligent"
resources {
requests = {
storage = "1Gi"
}
}
}
}
resource "kubernetes_persistent_volume_claim_v1" "backup-pvc-database" {
for_each = { for key, value in var.kubernetes : key => value if value.database != null && value.enabled == true && value.docker != true }
metadata {
namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key)
name = "${each.key}-db-backup"
labels = {
deployment_method = "Terraform"
}
annotations = {
fileType = "Backup" }
}
spec {
access_modes = ["ReadWriteMany"]
storage_class_name = "nfs-storage-fastaccess"
resources {
requests = {
storage = "1Gi"
}
}
}
}
resource "kubernetes_persistent_volume_claim_v1" "automatic-pvc-redis" {
for_each = { for key, value in var.kubernetes : key => value if value.redis != null && value.enabled == true && value.docker != true }
metadata {
namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key)
name = "${each.key}-redis-pvc"
labels = {
deployment_method = "Terraform"
}
}
spec {
access_modes = ["ReadWriteMany"]
storage_class_name = "nfs-storage-intelligent"
resources {
requests = {
storage = "1Gi"
}
}
}
}
+205 -92
View File
@@ -1,39 +1,44 @@
kubernetes = { kubernetes = {
echo = { reverse-proxy = {
#enabled = false #enabled = false
#docker = true docker = true
image = "ealen/echo-server:latest" image = "nginx:latest"
service_port = [4580] service_port = [80, 443]
external_port = true external_port = true
service_type = "NodePort"
domain_name = ["echo", "hello"]
#command = ["-text=Hello authenticated world!"]
pvc = { pvc = {
echo-config = { nginx-sites-terraform = {
mount_path = "/app/configs" name = "nginx-sites-terraform"
mount_path = "/etc/nginx/conf.d/"
host_path = "/data/kubernetes/reverse-proxy/reverse-proxy-sites"
} }
echo-testing = {
mount_path = "/app/test"
}
}
environment = {
PORT = {
value = 4580
}
PAPERLESS_REDIS = {
value = "redis://paperless-redis-svc:6379"
}
database = {
value = "datgg"
}
}
reverse-proxy-log = {
name = "reverse-proxy-log"
mount_path = "/var/log/nginx/"
host_path = "/data/kubernetes/reverse-proxy/reverse-proxy-log"
}
reverse-proxy-ssl = {
name = "reverse-proxy-ssl"
mount_path = "/etc/nginx/ssl/"
host_path = "/data/kubernetes/reverse-proxy/reverse-proxy-ssl"
}
nginx-configfile = {
name = "nginx-configfile"
mount_path = "/etc/nginx/nginx.conf"
host_path = "/data/kubernetes/reverse-proxy/reverse-proxy-configfile/nginx.conf"
}
}
} }
gitea = { gitea = {
#enabled = false #enabled = false
#docker = true docker = true
image = "gitea/gitea:1.27.0" image = "gitea/gitea:1.27.0"
service_port = [3000]
# no service_port: nginx reaches http://gitea:3000 over deployment_network # no service_port: nginx reaches http://gitea:3000 over deployment_network
database = { database = {
image = "postgres:17" image = "postgres:17"
@@ -47,11 +52,10 @@ kubernetes = {
POSTGRES_DB = { value = "gitea-database" } POSTGRES_DB = { value = "gitea-database" }
GITEA__database__DB_TYPE = { value = "postgres" } GITEA__database__DB_TYPE = { value = "postgres" }
#GITEA__database__HOST = { value = "gitea-db:5432" } # for docker GITEA__database__HOST = { value = "gitea-db:5432" }
GITEA__database__HOST = { value = "gitea-db-svc:5432" } # for k8s GITEA__database__USER = { value = "gitea-KY56Q" }
GITEA__database__USER = { value = "gitea-KY56Q" } GITEA__database__PASSWD = { value = "Modulator-Yearning-Gills3" }
GITEA__database__PASSWD = { value = "Modulator-Yearning-Gills3" } GITEA__database__NAME = { value = "gitea-database" }
GITEA__database__NAME = { value = "gitea-database" }
} }
pvc = { pvc = {
gitea-data = { gitea-data = {
@@ -69,10 +73,8 @@ kubernetes = {
gitea-runner = { gitea-runner = {
#enabled = false #enabled = false
#docker = true docker = true
image = "gitea/act_runner:latest" image = "gitea/act_runner:latest"
exposed = false
connected_namespace = "gitea"
environment = { environment = {
GITEA_INSTANCE_URL = { value = "https://gitea.geeraert.eu/" } GITEA_INSTANCE_URL = { value = "https://gitea.geeraert.eu/" }
GITEA_RUNNER_REGISTRATION_TOKEN = { value = "rqi4mFW8LXoc5MhIrUD1rjzdmKVY8n9X14BP6sWd" } GITEA_RUNNER_REGISTRATION_TOKEN = { value = "rqi4mFW8LXoc5MhIrUD1rjzdmKVY8n9X14BP6sWd" }
@@ -94,31 +96,62 @@ kubernetes = {
} }
echo = {
#enabled = false
docker = true
image = "ealen/echo-server:latest"
service_port = [4580]
external_port = true
command = ["-text=Hello authenticated world!"]
pvc = {
echo-config = {
name = "echo-config"
host_path = "/tmp/data/kubernetes/echo/"
mount_path = "/app/configs"
}
}
environment = {
PAPERLESS_REDIS = {
value = "redis://paperless-redis-svc:6379"
}
database = {
value = "datgg"
}
}
}
bitwarden-admin = { bitwarden-admin = {
#enabled = false enabled = false
namespace = "bitwarden" namespace = "bitwarden"
replicas = 1 replicas = 1
name = "bitwarden-admin" name = "bitwarden-admin"
image = "ghcr.io/bitwarden/admin:2026.1.0" image = "ghcr.io/bitwarden/admin:2026.1.0"
extra_manifest = ["../external_manifests/bitwarden/config.configmap.yml", "../external_manifests/bitwarden/global.env.configmap.yml", "../external_manifests/bitwarden/global.override.env.configmap.yml", "../external_manifests/bitwarden/mssql.env.configmap.yml", "../external_manifests/bitwarden/mssql.override.env.configmap.yml", "../external_manifests/bitwarden/uid.env.configmap.yml", "../external_manifests/bitwarden/bitwarden-identity-cert-password.secret.yml"]
service_port = [5000] service_port = [5000]
exposed = false
config_map_ref = ["global.env", "uid.env", "global.override.env"] config_map_ref = ["global.env", "uid.env", "global.override.env"]
secret_ref = ["global.override.secret"]
environment = {} environment = {}
pvc = { pvc = {
bitwarden-ca-certificates-pvc = { bitwarden-ca-certificates = {
pvc = true
pvc_size = "2Mi"
mount_path = "/etc/bitwarden/ca-certificates" mount_path = "/etc/bitwarden/ca-certificates"
name = "bitwarden-ca-certificates"
} }
bitwarden-core-pvc = { bitwarden-core = {
pvc = true
pvc_size = "2Mi"
mount_path = "/etc/bitwarden/core" mount_path = "/etc/bitwarden/core"
name = "bitwarden-core"
} }
bitwarden-logs-pvc = { bitwarden-logs = {
pvc = true
pvc_size = "2Mi"
mount_path = "/etc/bitwarden/logs" mount_path = "/etc/bitwarden/logs"
name = "bitwarden-logs"
sub_path = "admin" sub_path = "admin"
} }
@@ -128,26 +161,35 @@ kubernetes = {
} }
bitwarden-api = { bitwarden-api = {
#enabled = false enabled = false
connected_namespace = "bitwarden" connected_namespace = "bitwarden"
replicas = 1 replicas = 1
name = "bitwarden-api" name = "bitwarden-api"
image = "gitea.tryton.geeraert.eu/pi-ux-ce/bitbetter_api:2026.1.0" image = "gitea.tryton.geeraert.eu/pi-ux-ce/bitbetter_api:2026.1.0"
service_port = [5000] service_port = [5000]
exposed = false
config_map_ref = ["global.env", "uid.env", "global.override.env"] config_map_ref = ["global.env", "uid.env", "global.override.env"]
secret_ref = ["global.override.secret"]
environment = {} environment = {}
pvc = { pvc = {
bitwarden-ca-certificates-pvc = { bitwarden-ca-certificates = {
pvc = true
pvc_size = "2Mi"
mount_path = "/etc/bitwarden/ca-certificates" mount_path = "/etc/bitwarden/ca-certificates"
name = "bitwarden-ca-certificates"
} }
bitwarden-core-pvc = { bitwarden-core = {
pvc = true
pvc_size = "2Mi"
mount_path = "/etc/bitwarden/core" mount_path = "/etc/bitwarden/core"
name = "bitwarden-core"
} }
bitwarden-logs-pvc = { bitwarden-logs = {
pvc = true
pvc_size = "2Mi"
mount_path = "/etc/bitwarden/logs" mount_path = "/etc/bitwarden/logs"
name = "bitwarden-logs"
sub_path = "api" sub_path = "api"
} }
@@ -156,41 +198,49 @@ kubernetes = {
} }
bitwarden-attachments = { bitwarden-attachments = {
#enabled = false enabled = false
connected_namespace = "bitwarden" connected_namespace = "bitwarden"
replicas = 1 replicas = 1
name = "bitwarden-attachments" name = "bitwarden-attachments"
image = "ghcr.io/bitwarden/attachments:2026.1.0" image = "ghcr.io/bitwarden/attachments:2026.1.0"
service_port = [5000] service_port = [5000]
exposed = false
config_map_ref = ["global.env", "uid.env"] config_map_ref = ["global.env", "uid.env"]
environment = {} environment = {}
pvc = { pvc = {
bitwarden-core-pvc = { bitwarden-core = {
pvc = true
pvc_size = "2Mi"
mount_path = "/etc/bitwarden/core/attachments" mount_path = "/etc/bitwarden/core/attachments"
name = "bitwarden-core"
sub_path = "attachments" sub_path = "attachments"
} }
} }
} }
bitwarden-events = { bitwarden-events = {
#enabled = false enabled = false
connected_namespace = "bitwarden" connected_namespace = "bitwarden"
replicas = 1 replicas = 1
name = "bitwarden-events" name = "bitwarden-events"
image = "ghcr.io/bitwarden/events:2026.1.0" image = "ghcr.io/bitwarden/events:2026.1.0"
service_port = [5000] service_port = [5000]
exposed = false
config_map_ref = ["global.env", "uid.env", "global.override.env"] config_map_ref = ["global.env", "uid.env", "global.override.env"]
secret_ref = ["global.override.secret"]
environment = {} environment = {}
pvc = { pvc = {
bitwarden-ca-certificates-pvc = { bitwarden-ca-certificates = {
pvc = true
pvc_size = "2Mi"
mount_path = "/etc/bitwarden/ca-certificates" mount_path = "/etc/bitwarden/ca-certificates"
name = "bitwarden-ca-certificates"
} }
bitwarden-logs-pvc = { bitwarden-logs = {
pvc = true
pvc_size = "2Mi"
mount_path = "/etc/bitwarden/logs" mount_path = "/etc/bitwarden/logs"
name = "bitwarden-logs"
sub_path = "events" sub_path = "events"
} }
@@ -198,64 +248,82 @@ kubernetes = {
} }
bitwarden-icons = { bitwarden-icons = {
#enabled = false enabled = false
connected_namespace = "bitwarden" connected_namespace = "bitwarden"
replicas = 1 replicas = 1
name = "bitwarden-icons" name = "bitwarden-icons"
image = "ghcr.io/bitwarden/icons:2026.1.0" image = "ghcr.io/bitwarden/icons:2026.1.0"
service_port = [5000] service_port = [5000]
exposed = false
config_map_ref = ["global.env", "uid.env"] config_map_ref = ["global.env", "uid.env"]
environment = {} environment = {}
pvc = { pvc = {
bitwarden-ca-certificates-pvc = { bitwarden-ca-certificates = {
pvc = true
pvc_size = "2Mi"
mount_path = "/etc/bitwarden/ca-certificates" mount_path = "/etc/bitwarden/ca-certificates"
name = "bitwarden-ca-certificates"
} }
bitwarden-logs-pvc = { bitwarden-logs = {
pvc = true
pvc_size = "2Mi"
mount_path = "/etc/bitwarden/logs" mount_path = "/etc/bitwarden/logs"
name = "bitwarden-logs"
sub_path = "icons" sub_path = "icons"
} }
} }
} }
bitwarden-identity = { bitwarden-identity = {
#enabled = false enabled = false
connected_namespace = "bitwarden" connected_namespace = "bitwarden"
replicas = 1 replicas = 1
name = "bitwarden-identity" name = "bitwarden-identity"
extra_manifest = ["/opt/kubernetes/Terraform_kube/external_manifests/bitwarden/identity-svc.svc.yaml"]
image = "gitea.tryton.geeraert.eu/pi-ux-ce/bitbetter_identity:2026.1.0" image = "gitea.tryton.geeraert.eu/pi-ux-ce/bitbetter_identity:2026.1.0"
service_port = [5000] service_port = [5000]
exposed = false
config_map_ref = ["global.env", "uid.env", "global.override.env"] config_map_ref = ["global.env", "uid.env", "global.override.env"]
secret_ref = ["global.override.secret"]
environment = {} environment = {}
pvc = { pvc = {
bitwarden-identity-pvc = { bitwarden-identity = {
pvc = true
pvc_size = "2Mi"
mount_path = "/etc/bitwarden/identity" mount_path = "/etc/bitwarden/identity"
name = "bitwarden-identity"
} }
bitwarden-ca-certificates-pvc = { bitwarden-ca-certificates = {
pvc = true
pvc_size = "2Mi"
mount_path = "/etc/bitwarden/ca-certificates" mount_path = "/etc/bitwarden/ca-certificates"
name = "bitwarden-ca-certificates"
} }
bitwarden-core-pvc = { bitwarden-core = {
pvc = true
pvc_size = "2Mi"
mount_path = "/etc/bitwarden/core" mount_path = "/etc/bitwarden/core"
name = "bitwarden-core"
} }
bitwarden-logs-pvc = { bitwarden-logs = {
pvc = true
pvc_size = "2Mi"
mount_path = "/etc/bitwarden/logs" mount_path = "/etc/bitwarden/logs"
name = "bitwarden-logs"
sub_path = "identity" sub_path = "identity"
} }
} }
} }
bitwarden-mssql = { bitwarden-mssql = {
#enabled = false enabled = false
connected_namespace = "bitwarden" connected_namespace = "bitwarden"
replicas = 1 replicas = 1
name = "bitwarden-mssql" name = "bitwarden-mssql"
image = "ghcr.io/bitwarden/mssql:2026.1.0" image = "ghcr.io/bitwarden/mssql:2026.1.0"
service_port = [1433, 5000] service_port = [1433, 5000]
exposed = false config_map_ref = ["mssql.env", "uid.env"]
config_map_ref = ["mssql.env", "uid.env", "mssql.override.env"] secret_ref = ["mssql.secret"]
environment = {} environment = {}
database = { database = {
shunt = "true" shunt = "true"
@@ -266,111 +334,156 @@ kubernetes = {
} }
pvc = { pvc = {
bitwarden-mssql-pvc = { bitwarden-mssql = {
pvc = true
pvc_size = "2Mi"
mount_path = "/var/opt/mssql/data" mount_path = "/var/opt/mssql/data"
name = "bitwarden-mssql"
sub_path = "data" sub_path = "data"
} }
bitwarden-logs-pvc = { bitwarden-logs = {
pvc = true
pvc_size = "2Mi"
mount_path = "/etc/bitwarden/logs" mount_path = "/etc/bitwarden/logs"
name = "bitwarden-logs"
sub_path = "mssql" sub_path = "mssql"
} }
} }
} }
bitwarden-nginx = { bitwarden-nginx = {
#enabled = false enabled = false
connected_namespace = "bitwarden" connected_namespace = "bitwarden"
replicas = 1 replicas = 1
name = "bitwarden-nginx" name = "bitwarden-nginx"
image = "ghcr.io/bitwarden/nginx:2026.1.0" image = "ghcr.io/bitwarden/nginx:2026.1.0"
service_port = [8080, 5000, 8443] service_port = [5000, 8080, 8443]
exposed = true #no need to set as true but I did it for easy access
legacy_domain = true
domain_name = ["bitwarden"]
config_map_ref = ["uid.env"] config_map_ref = ["uid.env"]
environment = {} environment = {}
pvc = { pvc = {
bitwarden-nginx-pvc = { bitwarden-nginx = {
pvc = true
pvc_size = "2Mi"
mount_path = "/etc/bitwarden/nginx" mount_path = "/etc/bitwarden/nginx"
name = "bitwarden-nginx"
} }
bitwarden-letsencrypt-pvc = { bitwarden-letsencrypt = {
pvc = true
pvc_size = "2Mi"
mount_path = "/etc/letsencrypt" mount_path = "/etc/letsencrypt"
name = "bitwarden-letsencrypt"
} }
bitwarden-ssl-pvc = { bitwarden-ssl = {
pvc = true
pvc_size = "2Mi"
mount_path = "/etc/ssl" mount_path = "/etc/ssl"
name = "bitwarden-ssl"
} }
bitwarden-logs-pvc = { bitwarden-logs = {
pvc = true
pvc_size = "2Mi"
mount_path = "/var/log/nginx" mount_path = "/var/log/nginx"
name = "bitwarden-logs"
sub_path = "nginx" sub_path = "nginx"
} }
} }
} }
bitwarden-notifications = { bitwarden-notifications = {
#enabled = false enabled = false
connected_namespace = "bitwarden" connected_namespace = "bitwarden"
replicas = 1 replicas = 1
name = "bitwarden-notifications" name = "bitwarden-notifications"
image = "ghcr.io/bitwarden/notifications:2026.1.0" image = "ghcr.io/bitwarden/notifications:2026.1.0"
service_port = [5000] service_port = [5000]
exposed = false
config_map_ref = ["global.env", "uid.env", "global.override.env"] config_map_ref = ["global.env", "uid.env", "global.override.env"]
secret_ref = ["global.override.secret"]
environment = {} environment = {}
pvc = { pvc = {
bitwarden-ca-certificates-pvc = { bitwarden-ca-certificates = {
pvc = true
pvc_size = "2Mi"
mount_path = "/etc/bitwarden/ca-certificates" mount_path = "/etc/bitwarden/ca-certificates"
name = "bitwarden-ca-certificates-pvc" name = "bitwarden-ca-certificates"
} }
bitwarden-logs-pvc = { bitwarden-logs = {
pvc = true
pvc_size = "2Mi"
mount_path = "/etc/bitwarden/logs" mount_path = "/etc/bitwarden/logs"
name = "bitwarden-logs"
sub_path = "notifications" sub_path = "notifications"
} }
} }
} }
bitwarden-sso = { bitwarden-sso = {
#enabled = false enabled = false
connected_namespace = "bitwarden" connected_namespace = "bitwarden"
replicas = 1 replicas = 1
name = "bitwarden-sso" name = "bitwarden-sso"
image = "ghcr.io/bitwarden/sso:2026.1.0" image = "ghcr.io/bitwarden/sso:2026.1.0"
service_port = [5000] service_port = [5000]
exposed = false
config_map_ref = ["global.env", "uid.env", "global.override.env"] config_map_ref = ["global.env", "uid.env", "global.override.env"]
secret_ref = ["global.override.secret"]
environment = {} environment = {}
pvc = { pvc = {
bitwarden-identity-pvc = { bitwarden-identity = {
pvc = true
pvc_size = "2Mi"
mount_path = "/etc/bitwarden/identity" mount_path = "/etc/bitwarden/identity"
name = "bitwarden-identity"
} }
bitwarden-core-pvc = { bitwarden-core = {
pvc = true
pvc_size = "2Mi"
mount_path = "/etc/bitwarden/core" mount_path = "/etc/bitwarden/core"
name = "bitwarden-core"
} }
bitwarden-ca-certificates-pvc = { bitwarden-ca-certificates = {
pvc = true
pvc_size = "2Mi"
mount_path = "/etc/bitwarden/ca-certificates" mount_path = "/etc/bitwarden/ca-certificates"
name = "bitwarden-ca-certificates"
} }
bitwarden-logs-pvc = { bitwarden-logs = {
pvc = true
pvc_size = "2Mi"
mount_path = "/etc/bitwarden/logs" mount_path = "/etc/bitwarden/logs"
name = "bitwarden-logs"
sub_path = "sso" sub_path = "sso"
} }
} }
} }
bitwarden-web = { bitwarden-web = {
#enabled = false enabled = false
connected_namespace = "bitwarden" connected_namespace = "bitwarden"
replicas = 1 replicas = 1
name = "bitwarden-web" name = "bitwarden-web"
image = "ghcr.io/bitwarden/web:2026.1.0" image = "ghcr.io/bitwarden/web:2026.1.0"
service_port = [5000] service_port = [5000]
exposed = false
config_map_ref = ["global.env", "uid.env"] config_map_ref = ["global.env", "uid.env"]
environment = {} environment = {}
pvc = { pvc = {
bitwarden-web-pvc = { bitwarden-web = {
pvc = true
pvc_size = "2Mi"
mount_path = "/etc/bitwarden/web" mount_path = "/etc/bitwarden/web"
name = "bitwarden-web"
} }
} }
} }
} }
# Config kept as plain env files in external_manifests/, rendered into ConfigMaps/Secrets by env_files.tf.
# Reference them from a service with config_map_ref / secret_ref (names below).
env_files = {
"global.env" = { namespace = "bitwarden", path = "../external_manifests/bitwarden/global.env" }
"global.override.env" = { namespace = "bitwarden", path = "../external_manifests/bitwarden/global.override.env" }
"uid.env" = { namespace = "bitwarden", path = "../external_manifests/bitwarden/uid.env" }
"mssql.env" = { namespace = "bitwarden", path = "../external_manifests/bitwarden/mssql.env" }
"global.override.secret" = { namespace = "bitwarden", path = "../external_manifests/bitwarden/global.override.secret.env", secret = true }
"mssql.secret" = { namespace = "bitwarden", path = "../external_manifests/bitwarden/mssql.secret.env", secret = true }
}
+12
View File
@@ -0,0 +1,12 @@
ACCEPT_EULA=Y
ASPNETCORE_ENVIRONMENT=Production
globalSettings__baseServiceUri__vault=http://localhost
globalSettings__pushRelayBaseUri=https://push.bitwarden.com
globalSettings__selfHosted=true
globalSettings__baseServiceUri__internalNotifications=http://bitwarden-notifications-svc:5000
globalSettings__baseServiceUri__internalAdmin=http://bitwarden-admin-svc:5000
globalSettings__baseServiceUri__internalIdentity=http://bitwarden-identity-svc:5000
globalSettings__baseServiceUri__internalApi=http://bitwarden-api-svc:5000
globalSettings__baseServiceUri__internalVault=http://bitwarden-web-svc:5000
globalSettings__baseServiceUri__internalSso=http://bitwarden-sso-svc:5000
globalSettings__baseServiceUri__internalScim=http://bitwarden-self-host-scim:5000
@@ -0,0 +1,11 @@
ACCEPT_EULA=Y
adminSettings__admins=pierre@geeraert.eu
globalSettings__baseServiceUri__vault=http://bitwarden.tryton.geeraert.eu
globalSettings__disableUserRegistration=false
globalSettings__installation__id=c36aded0-b0f1-4252-920b-ac4c008fc920
globalSettings__mail__replyToEmail=no-reply@bitwarden.tryton.geeraert.eu
globalSettings__mail__smtp__host=smtp.gmail.com
globalSettings__mail__smtp__port=587
globalSettings__mail__smtp__ssl=false
globalSettings__mail__smtp__username=p3jh6qa2@gmail.com
globalSettings__yubico__clientId=REPLACE
@@ -1,9 +0,0 @@
globalSettings__duo__aKey=p9jCHtnG4NZNZu4SThpVlCuOF1oePGhu53Wa4RJwuyeqRAWQ0aJN7GsKYrGbYIYO
globalSettings__hibpApiKey=REPLACE
globalSettings__identityServer__certificatePassword=test
globalSettings__installation__key=CtQE5U1tMJE4Dzk7N9DU
globalSettings__internalIdentityKey=I5TMbqmEjhw9uBNmFZ9rU6s1KN5xqAKXh7RSPfgyj2XQ4sjlP22SCupFn4IVhYX7
globalSettings__mail__smtp__password=vmxkiidikqwirpuh
globalSettings__oidcIdentityClientKey=w47pWOkPa6mrTkiPuKizitsiRTR6NH8ufI01u77zbZt3LUcKWJ4wchMn6ouiwN7V
globalSettings__sqlServer__connectionString=Data Source=tcp:bitwarden-mssql-svc,1433;Initial Catalog=bitwarden_vault;Persist Security Info=False;User ID=sa;Password=ChQKWDIW73eSHzX1UyvGDAv4pFw6DVKM;MultipleActiveResultSets=False;Connect Timeout=30;Encrypt=True;TrustServerCertificate=True
globalSettings__yubico__key=REPLACE
@@ -0,0 +1,9 @@
globalSettings__duo__aKey=
globalSettings__hibpApiKey=
globalSettings__identityServer__certificatePassword=
globalSettings__installation__key=
globalSettings__internalIdentityKey=
globalSettings__mail__smtp__password=
globalSettings__oidcIdentityClientKey=
globalSettings__sqlServer__connectionString=
globalSettings__yubico__key=
+2
View File
@@ -0,0 +1,2 @@
ACCEPT_EULA=Y
MSSQL_PID=Express
@@ -1 +0,0 @@
SA_PASSWORD=ChQKWDIW73eSHzX1UyvGDAv4pFw6DVKM
@@ -0,0 +1 @@
SA_PASSWORD=
+2
View File
@@ -0,0 +1,2 @@
LOCAL_GID=1001
LOCAL_UID=1001
-1
View File
@@ -1 +0,0 @@
terraform 1.16.5
-171
View File
@@ -1,171 +0,0 @@
resource "kubernetes_deployment_v1" "database-automatic" {
for_each = { for key, value in var.kubernetes : key => value if value.database != null && value.enabled == true && !(try(value.database.shunt, false)) }
metadata {
namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key)
name = "${coalesce(each.value.name, each.key)}-db"
labels = {
app = each.key
deployment_method = "Terraform"
database = "true"
}
}
spec {
replicas = each.value.replicas
selector {
match_labels = {
app = "${each.key}-db"
}
}
template {
metadata {
labels = {
app = "${each.key}-db"
deployment_method = "Terraform"
database = "true"
}
}
spec {
container {
image = try(each.value.database.image, "docker.io/library/postgres:latest")
name = "${coalesce(each.value.name, each.key)}-db"
port {
container_port = 5432
name = "database-port"
}
volume_mount {
mount_path = try(each.value.database.mountPath, "/var/lib/postgresql/")
name = "${each.key}-db-volume"
}
dynamic "volume_mount" {
for_each = try(each.value.database.engine == "sqlserver", false) && !(try(each.value.database.shunt, false)) ? [1] : []
content {
mount_path = "/backup"
name = "${each.key}-db-backup"
}
}
command = try([each.value.database.command], [])
args = each.value.database_args != null ? each.value.database_args : []
dynamic "env_from" {
for_each = each.value.database != null && each.value.enabled == true && !(try(each.value.database.shunt, false)) ? ["${each.key}-db-terraform"] : []
content {
dynamic "secret_ref" {
for_each = [1]
content {
name = env_from.value
}
}
}
}
dynamic "env" {
for_each = each.value.environment != null ? each.value.environment : {}
content {
name = env.key
value = env.value.value != null ? env.value.value : null
dynamic "value_from" {
for_each = env.value.value_from != null ? env.value.value_from : {}
content {
dynamic "secret_key_ref" {
for_each = [1]
content {
name = env.value.value_from.secret_key_ref.name
key = env.value.value_from.secret_key_ref.key
}
}
}
}
}
}
}
volume {
name = "${each.key}-db-volume"
host_path {
path = try(each.value.database.host_path, join("/", [var.storage_path.main_storage, coalesce(each.value.namespace, each.value.connected_namespace, each.key), join("-", [each.key, "db"])]))
}
}
dynamic "volume" {
for_each = try(each.value.database.engine == "sqlserver", false) && !(try(each.value.database.shunt, false)) ? [1] : []
content {
name = "${each.key}-db-backup"
host_path {
path = join("/", [var.storage_path.fast_access, "Backup", coalesce(each.value.namespace, each.value.connected_namespace, each.key), "${each.key}-db-backup"])
}
}
}
}
}
}
}
resource "kubernetes_cron_job_v1" "database-backup" {
for_each = { for key, value in var.kubernetes : key => value if value.database != null && value.enabled == true }
metadata {
name = "${coalesce(each.value.namespace, each.key)}-db-backup"
namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key)
labels = {
app = each.key
deployment_method = "Terraform"
database = "true"
}
}
spec {
failed_jobs_history_limit = 5
schedule = "1 0 * * *"
timezone = "Etc/UTC"
successful_jobs_history_limit = 5
job_template {
metadata {}
spec {
backoff_limit = 4
ttl_seconds_after_finished = 100
template {
metadata {}
spec {
container {
name = "${coalesce(each.value.namespace, each.key)}-db-backup"
image = try(var.database_backup_info[each.value.database.engine].image, var.database_backup_info.postgres.image)
command = ["/bin/sh", "-c"]
args = [try(var.database_backup_info[each.value.database.engine].command, var.database_backup_info.postgres.command)]
env_from {
secret_ref {
name = "${each.key}-db-terraform"
}
}
volume_mount {
mount_path = "/backup"
name = "${each.key}-db-backup"
}
}
volume {
name = "${each.key}-db-backup"
persistent_volume_claim {
claim_name = "${each.key}-db-backup"
}
}
}
}
}
}
}
}
-242
View File
@@ -1,242 +0,0 @@
module "ingress" {
source = "../modules/ingress"
kubernetes_input = var.kubernetes
}
module "services" {
source = "../modules/services"
kubernetes_input = var.kubernetes
}
resource "kubernetes_deployment_v1" "automatic" {
for_each = { for key, value in var.kubernetes : key => value if value.enabled == true }
metadata {
namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key)
name = coalesce(each.value.name, each.key)
labels = {
app = each.key
deployment_method = "Terraform"
}
}
spec {
replicas = each.value.replicas
selector {
match_labels = {
app = each.key
}
}
template {
metadata {
labels = {
app = each.key
deployment_method = "Terraform"
}
}
spec {
container {
image = each.value.image
name = coalesce(each.value.name, each.key)
dynamic "port" {
for_each = each.value.service_port != null ? each.value.service_port : []
content {
container_port = port.value
# name = "${each.key}-${port.value}"
name = replace("${port.value}${each.key}", "/(.{0,15})(.*)/", "$1")
}
}
dynamic "volume_mount" {
for_each = each.value.pvc != null ? each.value.pvc : {}
content {
mount_path = volume_mount.value.mount_path
name = "${volume_mount.key}-volume"
sub_path = volume_mount.value.sub_path != null ? volume_mount.value.sub_path : ""
}
}
dynamic "volume_mount" {
for_each = try(each.value.database.engine == "sqlserver", false) && try(each.value.database.shunt, false) ? [1] : []
content {
mount_path = "/backup"
name = "${each.key}-db-backup"
}
}
dynamic "env_from" {
for_each = each.value.secret_ref != null ? each.value.secret_ref : []
content {
dynamic "secret_ref" {
for_each = [1]
content {
name = env_from.value
}
}
}
}
dynamic "env_from" {
for_each = each.value.database != null && each.value.enabled == true && !(try(each.value.database.shunt, false)) ? ["${each.key}-db-terraform"] : []
#for_each = each.value.database != null && each.value.enabled == true ? ["${each.key}-db-terraform"] : []
content {
dynamic "secret_ref" {
for_each = [1]
content {
name = env_from.value
}
}
}
}
dynamic "env_from" {
for_each = each.value.database != null && each.value.enabled == true ? ["${each.key}-db-mapped-terraform"] : []
content {
dynamic "secret_ref" {
for_each = [1]
content {
name = env_from.value
}
}
}
}
dynamic "env_from" {
for_each = each.value.config_map_ref != null ? each.value.config_map_ref : []
content {
dynamic "config_map_ref" {
for_each = [1]
content {
name = env_from.value
}
}
}
}
command = each.value.command != null ? each.value.command : []
dynamic "env" {
for_each = each.value.environment != null ? each.value.environment : {}
content {
name = env.key
value = env.value.value != null ? env.value.value : null
dynamic "value_from" {
for_each = env.value.value_from != null ? env.value.value_from : {}
content {
dynamic "secret_key_ref" {
for_each = [1]
content {
name = env.value.value_from.secret_key_ref.name
key = env.value.value_from.secret_key_ref.key
}
}
}
}
}
}
dynamic "resources" {
for_each = each.value.requirements != null ? [1] : []
content {
limits = {
cpu = each.value.requirements.limits-cpu
memory = each.value.requirements.limits-memory
}
requests = {
cpu = each.value.requirements.requests-cpu
memory = each.value.requirements.requests-memory
}
}
}
dynamic "security_context" {
for_each = each.value.security_context == true ? [1] : []
content {
privileged = true
#capabilities = {
# add : ["NET_ADMIN", "NET_RAW"]
#}
}
}
dynamic "liveness_probe" {
for_each = each.value.liveness_tcp_socket != null || each.value.liveness_http_get != null ? [""] : []
content {
dynamic "tcp_socket" {
for_each = each.value.liveness_tcp_socket != null ? [""] : []
content {
port = each.value.liveness_tcp_socket
}
}
dynamic "http_get" {
for_each = each.value.liveness_http_get != null ? [""] : []
content {
port = each.value.liveness_http_get
path = coalesce(each.value.liveness_http_get_path, "/")
}
}
initial_delay_seconds = 3
period_seconds = 3
}
}
}
dynamic "dns_config" {
for_each = each.value.dns_nameservers != null ? [1] : []
content {
nameservers = [each.value.dns_nameservers]
}
}
service_account_name = each.value.service_account_name != null ? each.value.service_account_name : null
dynamic "volume" {
for_each = each.value.pvc != null ? each.value.pvc : {}
content {
name = "${volume.key}-volume"
dynamic "config_map" {
for_each = volume.value.config_map ? [1] : []
content {
name = volume.key
}
}
dynamic "host_path" {
for_each = volume.value.host_path != null || (!(volume.value.config_map) && !(volume.value.secret)) ? [1] : []
content {
path = coalesce(volume.value.host_path, join("/", [var.storage_path.main_storage, coalesce(each.value.namespace, each.value.connected_namespace, each.key), volume.key]))
}
}
dynamic "secret" {
for_each = volume.value.secret ? [1] : []
content {
secret_name = volume.key
}
}
}
}
dynamic "volume" {
for_each = try(each.value.database.engine == "sqlserver", false) && try(each.value.database.shunt, false) ? [1] : []
content {
name = "${each.key}-db-backup"
host_path {
path = join("/", [var.storage_path.fast_access, "Backup", coalesce(each.value.namespace, each.value.connected_namespace, each.key), "${each.key}-db-backup"])
}
}
}
}
}
}
}
+903 -22
View File
@@ -23,11 +23,10 @@ provider "bitwarden-secrets" {
variable "kubernetes" { variable "kubernetes" {
type = map(object({ type = map(object({
name = optional(string) name = optional(string)
docker = optional(bool) image = string
image = string
pvc = optional(map(object({ pvc = optional(map(object({
name = optional(string) name = string
pvc = optional(bool, false) pvc = optional(bool, false)
config_map = optional(bool, false) config_map = optional(bool, false)
secret = optional(bool, false) secret = optional(bool, false)
@@ -56,9 +55,7 @@ variable "kubernetes" {
service_port = optional(list(number)) service_port = optional(list(number))
service_type = optional(string, "ClusterIP") service_type = optional(string, "ClusterIP")
service_name = optional(string) service_name = optional(string)
domain_name = optional(list(string)) domain_name = optional(string)
legacy_domain = optional(bool, false)
exposed = optional(bool, true)
liveness_tcp_socket = optional(number) liveness_tcp_socket = optional(number)
liveness_http_get = optional(string) liveness_http_get = optional(string)
liveness_http_get_path = optional(string) liveness_http_get_path = optional(string)
@@ -83,14 +80,6 @@ variable "kubernetes" {
service_account_name = optional(string) service_account_name = optional(string)
environment_variables = optional(map(string), { name = "value" }) environment_variables = optional(map(string), { name = "value" })
security_context = optional(bool, false) security_context = optional(bool, false)
import_database_secret = optional(object({
#putting them a non optional as the code doesn't allow optional value
host = string
name = string
password = string
port = string
username = string
}))
})) }))
} }
@@ -117,16 +106,39 @@ variable "database_backup_info" {
} }
} }
variable "storage_path" { locals {
type = map(string) pvc_list = flatten([
default = { for key, value in var.kubernetes : [
main_storage = "/data/kubernetes", for index, pvc in value.pvc : {
fast_access = "/ssd" key = "${coalesce(value.namespace, value.connected_namespace, key)}/${pvc.name}"
index = index
pvc = pvc.pvc
name = pvc.name
pvc_size = pvc.pvc_size
mount_path = pvc.mount_path
storage_class_name = pvc.storage_class_name
annotations_fileType = pvc.annotations_fileType
existing_pvc = pvc.existing_pvc
sub_path = pvc.sub_path
namespace = coalesce(value.namespace, value.connected_namespace, key)
}] if value.enabled == true && value.pvc != null
])
# group duplicates instead of throwing an error
pvc_map_grouped = {
for p in local.pvc_list :
p.key => p...
} }
# keep only one PVC per key (take the first)
pvc_map = {
for k, list in local.pvc_map_grouped :
k => list[0]
}
pvc_details = values(local.pvc_map)
} }
locals { locals {
env_details = flatten([ env_details = flatten([
for key, value in var.kubernetes : [ for key, value in var.kubernetes : [
@@ -138,6 +150,7 @@ locals {
} }
data "kubernetes_all_namespaces" "allns" {}
resource "kubernetes_namespace_v1" "automatic" { resource "kubernetes_namespace_v1" "automatic" {
for_each = { for key, value in var.kubernetes : key => value if value.enabled == true && value.connected_namespace == "" } for_each = { for key, value in var.kubernetes : key => value if value.enabled == true && value.connected_namespace == "" }
@@ -150,6 +163,7 @@ resource "kubernetes_namespace_v1" "automatic" {
} }
name = coalesce(each.value.namespace, each.key) name = coalesce(each.value.namespace, each.key)
} }
depends_on = [data.kubernetes_all_namespaces.allns]
} }
locals { locals {
@@ -174,3 +188,870 @@ resource "kubernetes_manifest" "manifest" {
provider = kubernetes provider = kubernetes
} }
resource "kubernetes_persistent_volume_claim_v1" "automatic-pvc" {
for_each = { for key, value in local.pvc_details : "${value.index}" => merge(value, { mew_key = value.index }) if value.pvc && value.existing_pvc != true }
metadata {
namespace = coalesce(each.value.namespace, each.key)
name = "${each.value.name}-pvc"
labels = {
deployment_method = "Terraform"
}
annotations = {
fileType = try(each.value.annotations_fileType, "file")
}
}
spec {
access_modes = ["ReadWriteMany"]
storage_class_name = each.value.storage_class_name
resources {
requests = {
storage = each.value.pvc_size
}
}
}
}
resource "kubernetes_persistent_volume_claim_v1" "automatic-pvc-database" {
for_each = { for key, value in var.kubernetes : key => value if value.database != null && value.enabled == true && !(try(value.database.shunt, false)) }
metadata {
namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key)
name = "${each.key}-db-pvc"
labels = {
deployment_method = "Terraform"
}
}
spec {
access_modes = ["ReadWriteMany"]
storage_class_name = "nfs-storage-intelligent"
resources {
requests = {
storage = "1Gi"
}
}
}
}
resource "kubernetes_persistent_volume_claim_v1" "backup-pvc-database" {
for_each = { for key, value in var.kubernetes : key => value if value.database != null && value.enabled == true }
metadata {
namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key)
name = "${each.key}-db-backup"
labels = {
deployment_method = "Terraform"
}
annotations = {
fileType = "Backup" }
}
spec {
access_modes = ["ReadWriteMany"]
storage_class_name = "nfs-storage-fastaccess"
resources {
requests = {
storage = "1Gi"
}
}
}
}
resource "kubernetes_persistent_volume_claim_v1" "automatic-pvc-redis" {
for_each = { for key, value in var.kubernetes : key => value if value.redis != null && value.enabled == true }
metadata {
namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key)
name = "${each.key}-redis-pvc"
labels = {
deployment_method = "Terraform"
}
}
spec {
access_modes = ["ReadWriteMany"]
storage_class_name = "nfs-storage-intelligent"
resources {
requests = {
storage = "1Gi"
}
}
}
}
resource "kubernetes_service_v1" "automatic_service" {
for_each = { for key, value in var.kubernetes : key => value if value.service_port != null && value.enabled == true }
metadata {
name = "${each.key}-svc"
namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key)
labels = {
deployment_method = "Terraform"
}
annotations = each.value.service_type == "LoadBalancer" ? {
"metallb.universe.tf/ip-allocated-from-pool" = "first-pool"
} : {}
}
spec {
selector = {
app = each.key
}
dynamic "port" {
for_each = each.value.service_port != null ? each.value.service_port : []
content {
port = port.value
target_port = port.value
name = replace("${port.value}${each.key}", "/(.{0,15})(.*)/", "$1")
}
}
# port {
# port = each.value.service_port
# target_port = each.value.service_port
# }
type = each.value.service_type
}
}
resource "kubernetes_service_v1" "automatic_service_database" {
for_each = { for key, value in var.kubernetes : key => value if value.database != null && value.enabled == true && !(try(value.database.shunt, false)) }
metadata {
name = "${each.key}-db-svc"
namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key)
labels = {
deployment_method = "Terraform"
#username = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_password[each.key].key}"
}
}
spec {
selector = {
app = "${each.key}-db"
}
port {
port = try(each.value.database.port, 5432)
target_port = try(each.value.database.port, 5432)
}
}
}
resource "kubernetes_service_v1" "automatic_service_redis" {
for_each = { for key, value in var.kubernetes : key => value if value.redis != null && value.enabled == true }
metadata {
name = "${each.key}-redis-svc"
namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key)
labels = {
deployment_method = "Terraform"
}
}
spec {
selector = {
app = "${each.key}-redis"
}
port {
port = 6379
target_port = 6379
}
}
}
resource "kubernetes_deployment_v1" "automatic" {
for_each = { for key, value in var.kubernetes : key => value if value.enabled == true }
metadata {
namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key)
name = coalesce(each.value.name, each.key)
labels = {
app = each.key
deployment_method = "Terraform"
}
}
spec {
replicas = each.value.replicas
selector {
match_labels = {
app = each.key
}
}
template {
metadata {
labels = {
app = each.key
deployment_method = "Terraform"
}
}
spec {
container {
image = each.value.image
name = coalesce(each.value.name, each.key)
dynamic "port" {
for_each = each.value.service_port != null ? each.value.service_port : []
content {
container_port = port.value
# name = "${each.key}-${port.value}"
name = replace("${port.value}${each.key}", "/(.{0,15})(.*)/", "$1")
}
}
dynamic "volume_mount" {
for_each = each.value.pvc != null ? each.value.pvc : {}
content {
mount_path = volume_mount.value.mount_path
name = "${volume_mount.value.name}-pvc"
sub_path = volume_mount.value.sub_path != null ? volume_mount.value.sub_path : ""
}
}
dynamic "volume_mount" {
for_each = try(each.value.database.engine == "sqlserver", false) && try(each.value.database.shunt, false) ? [1] : []
content {
mount_path = "/backup"
name = "${each.key}-db-backup"
}
}
dynamic "env_from" {
for_each = each.value.secret_ref != null ? each.value.secret_ref : []
content {
dynamic "secret_ref" {
for_each = [1]
content {
name = env_from.value
}
}
}
}
dynamic "env_from" {
for_each = each.value.database != null && each.value.enabled == true && !(try(each.value.database.shunt, false)) ? ["${each.key}-db-terraform"] : []
#for_each = each.value.database != null && each.value.enabled == true ? ["${each.key}-db-terraform"] : []
content {
dynamic "secret_ref" {
for_each = [1]
content {
name = env_from.value
}
}
}
}
dynamic "env_from" {
for_each = each.value.database != null && each.value.enabled == true ? ["${each.key}-db-mapped-terraform"] : []
content {
dynamic "secret_ref" {
for_each = [1]
content {
name = env_from.value
}
}
}
}
dynamic "env_from" {
for_each = each.value.config_map_ref != null ? each.value.config_map_ref : []
content {
dynamic "config_map_ref" {
for_each = [1]
content {
name = env_from.value
}
}
}
}
command = each.value.command != null ? each.value.command : []
dynamic "env" {
for_each = each.value.environment != null ? each.value.environment : {}
content {
name = env.key
value = env.value.value != null ? env.value.value : null
dynamic "value_from" {
for_each = env.value.value_from != null ? env.value.value_from : {}
content {
dynamic "secret_key_ref" {
for_each = [1]
content {
name = env.value.value_from.secret_key_ref.name
key = env.value.value_from.secret_key_ref.key
}
}
}
}
}
}
dynamic "resources" {
for_each = each.value.requirements != null ? [1] : []
content {
limits = {
cpu = each.value.requirements.limits-cpu
memory = each.value.requirements.limits-memory
}
requests = {
cpu = each.value.requirements.requests-cpu
memory = each.value.requirements.requests-memory
}
}
}
dynamic "security_context" {
for_each = each.value.security_context == true ? [1] : []
content {
privileged = true
#capabilities = {
# add : ["NET_ADMIN", "NET_RAW"]
#}
}
}
dynamic "liveness_probe" {
for_each = each.value.liveness_tcp_socket != null || each.value.liveness_http_get != null ? [""] : []
content {
dynamic "tcp_socket" {
for_each = each.value.liveness_tcp_socket != null ? [""] : []
content {
port = each.value.liveness_tcp_socket
}
}
dynamic "http_get" {
for_each = each.value.liveness_http_get != null ? [""] : []
content {
port = each.value.liveness_http_get
path = coalesce(each.value.liveness_http_get_path, "/")
}
}
initial_delay_seconds = 3
period_seconds = 3
}
}
}
dynamic "dns_config" {
for_each = each.value.dns_nameservers != null ? [1] : []
content {
nameservers = [each.value.dns_nameservers]
}
}
service_account_name = each.value.service_account_name != null ? each.value.service_account_name : null
dynamic "volume" {
for_each = each.value.pvc != null ? each.value.pvc : {}
content {
name = "${volume.value.name}-pvc"
dynamic "persistent_volume_claim" {
for_each = volume.value.pvc ? [1] : []
content {
claim_name = "${volume.value.name}-pvc"
}
}
dynamic "config_map" {
for_each = volume.value.config_map ? [1] : []
content {
name = volume.value.name
}
}
dynamic "host_path" {
for_each = volume.value.host_path != null ? [1] : []
content {
path = volume.value.host_path
}
}
dynamic "secret" {
for_each = volume.value.secret ? [1] : []
content {
secret_name = volume.value.name
}
}
}
}
dynamic "volume" {
for_each = try(each.value.database.engine == "sqlserver", false) && try(each.value.database.shunt, false) ? [1] : []
content {
name = "${each.key}-db-backup"
persistent_volume_claim {
claim_name = "${each.key}-db-backup"
}
}
}
}
}
}
depends_on = [kubernetes_persistent_volume_claim_v1.automatic-pvc]
}
resource "kubernetes_deployment_v1" "database-automatic" {
for_each = { for key, value in var.kubernetes : key => value if value.database != null && value.enabled == true && !(try(value.database.shunt, false)) }
metadata {
namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key)
name = "${coalesce(each.value.name, each.key)}-db"
labels = {
app = each.key
deployment_method = "Terraform"
database = "true"
}
}
spec {
replicas = each.value.replicas
selector {
match_labels = {
app = "${each.key}-db"
}
}
template {
metadata {
labels = {
app = "${each.key}-db"
deployment_method = "Terraform"
database = "true"
}
}
spec {
container {
image = try(each.value.database.image, "docker.io/library/postgres:latest")
name = "${coalesce(each.value.name, each.key)}-db"
port {
container_port = 5432
name = "database-port"
}
volume_mount {
mount_path = try(each.value.database.mountPath, "/var/lib/postgresql/")
name = "${each.key}-db-pvc"
}
dynamic "volume_mount" {
for_each = try(each.value.database.engine == "sqlserver", false) && !(try(each.value.database.shunt, false)) ? [1] : []
content {
mount_path = "/backup"
name = "${each.key}-db-backup"
}
}
command = try([each.value.database.command], [])
args = each.value.database_args != null ? each.value.database_args : []
dynamic "env_from" {
for_each = each.value.database != null && each.value.enabled == true && !(try(each.value.database.shunt, false)) ? ["${each.key}-db-terraform"] : []
content {
dynamic "secret_ref" {
for_each = [1]
content {
name = env_from.value
}
}
}
}
dynamic "env" {
for_each = each.value.environment != null ? each.value.environment : {}
content {
name = env.key
value = env.value.value != null ? env.value.value : null
dynamic "value_from" {
for_each = env.value.value_from != null ? env.value.value_from : {}
content {
dynamic "secret_key_ref" {
for_each = [1]
content {
name = env.value.value_from.secret_key_ref.name
key = env.value.value_from.secret_key_ref.key
# optional = true
}
}
}
}
}
}
}
volume {
name = "${each.key}-db-pvc"
persistent_volume_claim {
claim_name = "${each.key}-db-pvc"
}
}
dynamic "volume" {
for_each = try(each.value.database.engine == "sqlserver", false) && !(try(each.value.database.shunt, false)) ? [1] : []
content {
name = "${each.key}-db-backup"
persistent_volume_claim {
claim_name = "${each.key}-db-backup"
}
}
}
}
}
}
}
resource "kubernetes_cron_job_v1" "database-backup" {
for_each = { for key, value in var.kubernetes : key => value if value.database != null && value.enabled == true }
metadata {
name = "${coalesce(each.value.namespace, each.key)}-db-backup"
namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key)
labels = {
app = each.key
deployment_method = "Terraform"
database = "true"
}
}
spec {
failed_jobs_history_limit = 5
schedule = "1 0 * * *"
timezone = "Etc/UTC"
successful_jobs_history_limit = 5
job_template {
metadata {}
spec {
backoff_limit = 4
ttl_seconds_after_finished = 100
template {
metadata {}
spec {
container {
name = "${coalesce(each.value.namespace, each.key)}-db-backup"
image = try(var.database_backup_info[each.value.database.engine].image, var.database_backup_info.postgres.image)
command = ["/bin/sh", "-c"]
args = [try(var.database_backup_info[each.value.database.engine].command, var.database_backup_info.postgres.command)]
env_from {
secret_ref {
name = "${each.key}-db-terraform"
}
}
volume_mount {
mount_path = "/backup"
name = "${each.key}-db-backup"
}
}
volume {
name = "${each.key}-db-backup"
persistent_volume_claim {
claim_name = "${each.key}-db-backup"
}
}
}
}
}
}
}
}
resource "kubernetes_deployment_v1" "redis-automatic" {
for_each = { for key, value in var.kubernetes : key => value if value.redis != null && value.enabled == true }
metadata {
namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key)
name = "${coalesce(each.value.name, each.key)}-redis"
labels = {
app = each.key
deployment_method = "Terraform"
redis = "true"
}
}
spec {
replicas = each.value.replicas
selector {
match_labels = {
app = "${each.key}-redis"
}
}
template {
metadata {
labels = {
app = "${each.key}-redis"
deployment_method = "Terraform"
redis = "true"
}
}
spec {
container {
image = try(each.value.redis.image, "docker.io/library/redis:7")
name = "${coalesce(each.value.name, each.key)}-redis"
port {
container_port = 6379
name = "redis-port"
}
volume_mount {
mount_path = "/data"
name = "${each.key}-redis-pvc"
}
dynamic "env" {
for_each = each.value.environment != null ? each.value.environment : {}
content {
name = env.key
value = env.value.value != null ? env.value.value : null
dynamic "value_from" {
for_each = env.value.value_from != null ? env.value.value_from : {}
content {
dynamic "secret_key_ref" {
for_each = [1]
content {
name = env.value.value_from.secret_key_ref.name
key = env.value.value_from.secret_key_ref.key
# optional = true
}
}
}
}
}
}
# resources {
# limits = {
# cpu = each.value.requirements.limits-cpu
# memory = each.value.requirements.limits-memory
# }
# requests = {
# cpu = each.value.requirements.requests-cpu
# memory = each.value.requirements.requests-memory
# }
# }
# dynamic "liveness_probe" {
# for_each = each.value.liveness_tcp_socket != null || each.value.liveness_http_get != null ? [""] : []
# content {
# dynamic "tcp_socket" {
# for_each = each.value.liveness_tcp_socket != null ? [""] : []
# content {
# port = each.value.liveness_tcp_socket
# }
# }
# dynamic "http_get" {
# for_each = each.value.liveness_http_get != null ? [""] : []
# content {
# port = each.value.liveness_http_get
# path = coalesce(each.value.liveness_http_get_path, "/")
# }
# }
# initial_delay_seconds = 3
# period_seconds = 3
# }
# }
}
volume {
name = "${each.key}-redis-pvc"
persistent_volume_claim {
claim_name = "${each.key}-redis-pvc"
}
}
}
}
}
}
resource "kubernetes_config_map_v1" "automatic-configmap" {
metadata {
name = "extra-sites-terraform"
namespace = "reverse-proxy"
annotations = {
"reloader.stakater.com/match" : "true",
}
}
data = {
for key, value in var.kubernetes :
"${value.domain_name}.conf" => templatefile("nginx_config.tftpl", {
name_site = value.domain_name
name_service = "${key}-svc.${coalesce(value.namespace, value.connected_namespace, key)}.svc:${value.service_port.0}"
}) if value.domain_name != null && value.enabled == true
}
}
data "bitwarden-secrets_secret" "configmap_import" {
for_each = {
for pair in flatten([
for k, v in var.kubernetes : [
for id in v.config_map_import : {
map_key = k
secret_id = id
}
] if v.config_map_import != null && v.enabled == true
]) : "${pair.map_key}-${pair.secret_id}" => pair.secret_id
}
id = each.value
}
resource "kubernetes_config_map_v1" "configmap_import" {
for_each = { for key, value in data.bitwarden-secrets_secret.configmap_import : key => value }
metadata {
name = each.value.note
namespace = split("__", each.value.key)[0]
}
data = yamldecode(each.value.value)
}
data "bitwarden-secrets_secret" "secret_import" {
for_each = {
for pair in flatten([
for k, v in var.kubernetes : [
for id in v.secret_import : {
map_key = k
secret_id = id
}
] if v.secret_import != null && v.enabled == true
]) : "${pair.map_key}-${pair.secret_id}" => pair.secret_id
}
id = each.value
}
resource "kubernetes_secret_v1" "secret_import" {
for_each = { for key, value in data.bitwarden-secrets_secret.secret_import : key => value }
metadata {
name = each.value.note
namespace = split("__", each.value.key)[0]
}
data = yamldecode(each.value.value)
}
resource "kubernetes_secret_v1" "automatic-database-secret" {
for_each = { for key, value in var.kubernetes : key => value if value.database != null && value.enabled == true }
metadata {
name = "${each.key}-db-terraform"
namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key)
}
data = {
DB_DATABASE_NAME = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_name[each.key].value}"
DB_DATABASE = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_name[each.key].value}"
POSTGRES_DB = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_name[each.key].value}"
MYSQL_DATABASE = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_name[each.key].value}"
PGDATABASE = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_name[each.key].value}"
DB_HOST = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_host[each.key].value}"
PGHOST = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_host[each.key].value}"
POSTGRES_HOST = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_host[each.key].value}"
DB_PASSWORD = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_password[each.key].value}"
MYSQL_PASSWORD = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_password[each.key].value}"
MYSQL_ROOT_PASSWORD = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_password[each.key].value}"
POSTGRES_PASSWORD = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_password[each.key].value}"
PGPASSWORD = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_password[each.key].value}"
DB_USERNAME = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_username[each.key].value}"
POSTGRES_USER = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_username[each.key].value}"
MYSQL_USER = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_username[each.key].value}"
PGUSER = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_username[each.key].value}"
DATABASE_URL = "postgresql://${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_username[each.key].value}:${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_password[each.key].value}@${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_host[each.key].value}:${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_port[each.key].value}/${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_name[each.key].value}"
}
}
resource "kubernetes_secret_v1" "automatic-database-mapped-secret" {
for_each = { for key, value in var.kubernetes : key => value if value.database != null && value.enabled == true }
metadata {
name = "${each.key}-db-mapped-terraform"
namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key)
}
data = {
"${try(each.value.database.map_name, "DB_DATABASE_NAME")}" = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_name[each.key].value}"
"${try(each.value.database.map_host, "DB_DATABASE_NAME")}" = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_host[each.key].value}"
"${try(each.value.database.map_password, "DB_DATABASE_NAME")}" = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_password[each.key].value}"
"${try(each.value.database.map_username, "DB_DATABASE_NAME")}" = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_username[each.key].value}"
}
}
resource "bitwarden-secrets_secret" "automatic_bitwarden_secret_db_username" {
for_each = { for key, value in var.kubernetes : key => value if value.database != null && value.enabled == true }
key = "${each.key}__db__username"
value = try(each.value.database.username, each.key)
project_id = "b5fc4c48-e951-442f-97ca-b3e800c143cd"
}
resource "bitwarden-secrets_secret" "automatic_bitwarden_secret_db_password" {
for_each = { for key, value in var.kubernetes : key => value if value.database != null && value.enabled == true }
key = "${each.key}__db__password"
project_id = "b5fc4c48-e951-442f-97ca-b3e800c143cd"
length = 32
special = true
min_special = 5
avoid_ambiguous = true
}
resource "bitwarden-secrets_secret" "automatic_bitwarden_secret_db_host" {
for_each = { for key, value in var.kubernetes : key => value if value.database != null && value.enabled == true }
key = "${each.key}__db__host"
project_id = "b5fc4c48-e951-442f-97ca-b3e800c143cd"
value = try(each.value.database.host, "${each.key}-db-svc.${coalesce(each.value.namespace, each.value.connected_namespace, each.key)}.svc")
}
resource "bitwarden-secrets_secret" "automatic_bitwarden_secret_db_port" {
for_each = { for key, value in var.kubernetes : key => value if value.database != null && value.enabled == true }
key = "${each.key}__db__port"
project_id = "b5fc4c48-e951-442f-97ca-b3e800c143cd"
value = try(each.value.database.port, 5432)
}
resource "bitwarden-secrets_secret" "automatic_bitwarden_secret_db_name" {
for_each = { for key, value in var.kubernetes : key => value if value.database != null && value.enabled == true }
key = "${each.key}__db__name"
project_id = "b5fc4c48-e951-442f-97ca-b3e800c143cd"
value = try(each.value.database.name, each.key)
}
-123
View File
@@ -1,123 +0,0 @@
resource "kubernetes_deployment_v1" "redis-automatic" {
for_each = { for key, value in var.kubernetes : key => value if value.redis != null && value.enabled == true }
metadata {
namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key)
name = "${coalesce(each.value.name, each.key)}-redis"
labels = {
app = each.key
deployment_method = "Terraform"
redis = "true"
}
}
spec {
replicas = each.value.replicas
selector {
match_labels = {
app = "${each.key}-redis"
}
}
template {
metadata {
labels = {
app = "${each.key}-redis"
deployment_method = "Terraform"
redis = "true"
}
}
spec {
container {
image = try(each.value.redis.image, "docker.io/library/redis:7")
name = "${coalesce(each.value.name, each.key)}-redis"
port {
container_port = 6379
name = "redis-port"
}
volume_mount {
mount_path = "/data"
name = "${each.key}-redis-volume"
}
dynamic "env" {
for_each = each.value.environment != null ? each.value.environment : {}
content {
name = env.key
value = env.value.value != null ? env.value.value : null
dynamic "value_from" {
for_each = env.value.value_from != null ? env.value.value_from : {}
content {
dynamic "secret_key_ref" {
for_each = [1]
content {
name = env.value.value_from.secret_key_ref.name
key = env.value.value_from.secret_key_ref.key
# optional = true
}
}
}
}
}
}
# resources {
# limits = {
# cpu = each.value.requirements.limits-cpu
# memory = each.value.requirements.limits-memory
# }
# requests = {
# cpu = each.value.requirements.requests-cpu
# memory = each.value.requirements.requests-memory
# }
# }
# dynamic "liveness_probe" {
# for_each = each.value.liveness_tcp_socket != null || each.value.liveness_http_get != null ? [""] : []
# content {
# dynamic "tcp_socket" {
# for_each = each.value.liveness_tcp_socket != null ? [""] : []
# content {
# port = each.value.liveness_tcp_socket
# }
# }
# dynamic "http_get" {
# for_each = each.value.liveness_http_get != null ? [""] : []
# content {
# port = each.value.liveness_http_get
# path = coalesce(each.value.liveness_http_get_path, "/")
# }
# }
# initial_delay_seconds = 3
# period_seconds = 3
# }
# }
}
volume {
name = "${each.key}-redis-volume"
host_path {
path = try(each.value.redis.host_path, join("/", [var.storage_path.main_storage, coalesce(each.value.namespace, each.value.connected_namespace, each.key), join("-", [each.key, "redis"])]))
}
}
}
}
}
}
-198
View File
@@ -1,198 +0,0 @@
data "bitwarden-secrets_secret" "configmap_import" {
for_each = {
for pair in flatten([
for k, v in var.kubernetes : [
for id in v.config_map_import : {
map_key = k
secret_id = id
}
] if v.config_map_import != null && v.enabled == true
]) : "${pair.map_key}-${pair.secret_id}" => pair.secret_id
}
id = each.value
}
resource "kubernetes_config_map_v1" "configmap_import" {
for_each = { for key, value in data.bitwarden-secrets_secret.configmap_import : key => value }
metadata {
name = each.value.note
namespace = split("__", each.value.key)[0]
}
data = yamldecode(each.value.value)
}
data "bitwarden-secrets_secret" "secret_import" {
for_each = {
for pair in flatten([
for k, v in var.kubernetes : [
for id in v.secret_import : {
map_key = k
secret_id = id
}
] if v.secret_import != null && v.enabled == true
]) : "${pair.map_key}-${pair.secret_id}" => pair.secret_id
}
id = each.value
}
resource "kubernetes_secret_v1" "secret_import" {
for_each = { for key, value in data.bitwarden-secrets_secret.secret_import : key => value }
metadata {
name = each.value.note
namespace = split("__", each.value.key)[0]
}
data = yamldecode(each.value.value)
}
resource "kubernetes_secret_v1" "automatic-database-secret" {
for_each = { for key, value in var.kubernetes : key => value if value.database != null && value.enabled == true }
metadata {
name = "${each.key}-db-terraform"
namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key)
}
data = {
DB_DATABASE_NAME = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_name[each.key].value}"
DB_DATABASE = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_name[each.key].value}"
POSTGRES_DB = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_name[each.key].value}"
MYSQL_DATABASE = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_name[each.key].value}"
PGDATABASE = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_name[each.key].value}"
DB_HOST = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_host[each.key].value}"
PGHOST = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_host[each.key].value}"
POSTGRES_HOST = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_host[each.key].value}"
DB_PASSWORD = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_password[each.key].value}"
MYSQL_PASSWORD = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_password[each.key].value}"
MYSQL_ROOT_PASSWORD = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_password[each.key].value}"
POSTGRES_PASSWORD = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_password[each.key].value}"
PGPASSWORD = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_password[each.key].value}"
DB_USERNAME = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_username[each.key].value}"
POSTGRES_USER = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_username[each.key].value}"
MYSQL_USER = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_username[each.key].value}"
PGUSER = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_username[each.key].value}"
DATABASE_URL = "postgresql://${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_username[each.key].value}:${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_password[each.key].value}@${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_host[each.key].value}:${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_port[each.key].value}/${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_name[each.key].value}"
}
}
resource "kubernetes_secret_v1" "automatic-database-mapped-secret" {
for_each = { for key, value in var.kubernetes : key => value if value.database != null && value.enabled == true }
metadata {
name = "${each.key}-db-mapped-terraform"
namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key)
}
data = {
"${try(each.value.database.map_name, "DB_DATABASE_NAME")}" = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_name[each.key].value}"
"${try(each.value.database.map_host, "DB_DATABASE_NAME")}" = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_host[each.key].value}"
"${try(each.value.database.map_password, "DB_DATABASE_NAME")}" = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_password[each.key].value}"
"${try(each.value.database.map_username, "DB_DATABASE_NAME")}" = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_db_username[each.key].value}"
}
}
resource "bitwarden-secrets_secret" "automatic_bitwarden_secret_db_username" {
for_each = { for key, value in var.kubernetes : key => value if value.database != null && value.enabled == true }
key = "${each.key}__db__username"
value = try(each.value.database.username, each.key)
project_id = "b5fc4c48-e951-442f-97ca-b3e800c143cd"
lifecycle {
ignore_changes = [
value, key
]
}
}
resource "bitwarden-secrets_secret" "automatic_bitwarden_secret_db_password" {
for_each = { for key, value in var.kubernetes : key => value if value.database != null && value.enabled == true }
key = "${each.key}__db__password"
project_id = "b5fc4c48-e951-442f-97ca-b3e800c143cd"
length = 32
special = true
min_special = 5
avoid_ambiguous = true
lifecycle {
ignore_changes = [
value, key
]
}
}
resource "bitwarden-secrets_secret" "automatic_bitwarden_secret_db_host" {
for_each = { for key, value in var.kubernetes : key => value if value.database != null && value.enabled == true }
key = "${each.key}__db__host"
project_id = "b5fc4c48-e951-442f-97ca-b3e800c143cd"
value = try(each.value.database.host, "${each.key}-db-svc.${coalesce(each.value.namespace, each.value.connected_namespace, each.key)}.svc")
lifecycle {
ignore_changes = [
value, key
]
}
}
resource "bitwarden-secrets_secret" "automatic_bitwarden_secret_db_port" {
for_each = { for key, value in var.kubernetes : key => value if value.database != null && value.enabled == true }
key = "${each.key}__db__port"
project_id = "b5fc4c48-e951-442f-97ca-b3e800c143cd"
value = try(each.value.database.port, 5432)
lifecycle {
ignore_changes = [
value, key
]
}
}
resource "bitwarden-secrets_secret" "automatic_bitwarden_secret_db_name" {
for_each = { for key, value in var.kubernetes : key => value if value.database != null && value.enabled == true }
key = "${each.key}__db__name"
project_id = "b5fc4c48-e951-442f-97ca-b3e800c143cd"
value = try(each.value.database.name, each.key)
lifecycle {
ignore_changes = [
value, key
]
}
}
# 1. Move the loop logic to a local variable first
locals {
database_secrets_to_import = {
for key, value in var.kubernetes : key => value
if value.database != null && value.enabled == true && can(value.import_database_secret.host)
}
}
# 2. Reference the local map in your import block using each.key and each.value
import {
for_each = local.database_secrets_to_import
to = bitwarden-secrets_secret.automatic_bitwarden_secret_db_host[each.key]
id = each.value.import_database_secret.host
}
import {
for_each = local.database_secrets_to_import
to = bitwarden-secrets_secret.automatic_bitwarden_secret_db_name[each.key]
id = each.value.import_database_secret.name
}
import {
for_each = local.database_secrets_to_import
to = bitwarden-secrets_secret.automatic_bitwarden_secret_db_password[each.key]
id = each.value.import_database_secret.password
}
import {
for_each = local.database_secrets_to_import
to = bitwarden-secrets_secret.automatic_bitwarden_secret_db_port[each.key]
id = each.value.import_database_secret.port
}
import {
for_each = local.database_secrets_to_import
to = bitwarden-secrets_secret.automatic_bitwarden_secret_db_username[each.key]
id = each.value.import_database_secret.username
}
+44 -35
View File
@@ -1,15 +1,20 @@
kubernetes = { kubernetes = {
gluetun = { gluetun = {
#enabled = false # enabled = false
dns_nameservers = "1.1.1.1" dns_nameservers = "1.1.1.1"
replicas = 01 replicas = 01
image = "qmcgaw/gluetun:latest" image = "qmcgaw/gluetun:latest"
exposed = false service_port = [8888]
service_port = [8888] #extra_manifest = ["/opt/kubernetes/Terraform_kube/external_manifests/gluetun/gluetun-secret-netherlandNL-FREE-280.yaml"]
secret_import = ["5527ba11-07e3-415b-8d1f-b3ee0154eb56", "b0d22160-d81a-4702-a3dd-b40e0168d617", "643dbe99-ace0-4ef5-8a2e-b44f014dccb0"] secret_import = ["5527ba11-07e3-415b-8d1f-b3ee0154eb56", "b0d22160-d81a-4702-a3dd-b40e0168d617", "643dbe99-ace0-4ef5-8a2e-b44f014dccb0"]
security_context = true security_context = true
# requirements = {
# limits-cpu = "800Mi"
# limits-memory = "800Mi"
# requests-cpu = "800Mi"
# requests-memory = "800Mi"
# }
environment = { environment = {
WIREGUARD_PRIVATE_KEY = { WIREGUARD_PRIVATE_KEY = {
value_from = { value_from = {
@@ -28,6 +33,9 @@ kubernetes = {
HTTPPROXY_LISTENING_ADDRESS = { HTTPPROXY_LISTENING_ADDRESS = {
value = "0.0.0.0:8888" value = "0.0.0.0:8888"
} }
# DNS_KEEP_NAMESERVER = {
# value = "on"
# }
VPN_SERVICE_PROVIDER = { VPN_SERVICE_PROVIDER = {
value = "protonvpn" value = "protonvpn"
} }
@@ -45,6 +53,9 @@ kubernetes = {
value = "on" value = "on"
} }
# WIREGUARD_ADDRESSES = {
# value = "10.2.0.2/32"
# }
FIREWALL_INPUT_PORTS = { FIREWALL_INPUT_PORTS = {
value = "8081,7878,9696,9091,51413,8080,6881,8989,8191,8888,8000" value = "8081,7878,9696,9091,51413,8080,6881,8989,8191,8888,8000"
} }
@@ -52,23 +63,29 @@ kubernetes = {
value = "ip2location" value = "ip2location"
} }
# HEALTH_TARGET_ADDRESS = {
# value = "protonvpn.com:80"
# }
# FIREWALL_OUTBOUND_SUBNETS = {
# value = "10.0.0.0/24" }
} }
} }
django = { django = {
#enabled = false #enabled =false
namespace = "django" namespace = "django"
domain_name = ["django", "admin", "redirect", "streaming", "stash", "simpsons", "kubernetes", "cloudmanager", "podcast"] image = "gitea.tryton.geeraert.eu/pi-ux-ce/django-python:latest"
image = "gitea.geeraert.eu/pi-ux-ce/django-python:latest"
service_port = [8000] service_port = [8000]
database = { database = {
image = "docker.io/tensorchord/pgvecto-rs:pg14-v0.2.0" image = "docker.io/tensorchord/pgvecto-rs:pg14-v0.2.0"
username = "django_username" username = "django_username"
mountPath = "/var/lib/postgresql/data" mountPath = "/var/lib/postgresql/data"
} }
secret_ref = ["django-bitwarden-credentials"] #redis = {}
secret_ref = ["django-bitwarden-credentials"]
secret_import = ["9fc5a725-75f5-4bab-b595-b474017146c3"] secret_import = ["9fc5a725-75f5-4bab-b595-b474017146c3"]
requirements = { requirements = {
limits-cpu = "800m" limits-cpu = "800m"
@@ -88,6 +105,11 @@ kubernetes = {
ENVIRONMENT = { ENVIRONMENT = {
value = "PRODUCTION" value = "PRODUCTION"
} }
#CELERY_BROKER_URL = {
# value = "redis://django-redis-svc:6379"
#}
#HTTP_PROXY = {
#value = "http://gluetun-svc.gluetun.svc:8888" }
DB_PASSWORD = { DB_PASSWORD = {
value_from = { value_from = {
@@ -135,39 +157,34 @@ kubernetes = {
} }
pvc = { pvc = {
kubeconfig = { kubeconfig-secret = {
secret = true secret = true
name = "kubeconfig"
mount_path = "/kubeconfig" mount_path = "/kubeconfig"
} }
stash-django-pvc = { stash-django-pvc = {
host_path = "/ssd/stash/data-pvc/" host_path = "/ssd/stash/data-pvc/"
name = "stash-django-pvc"
pvc_size = "2Mi"
mount_path = "/stash" mount_path = "/stash"
} }
} }
import_database_secret = {
host = "c73c74e5-b482-4abb-a4b3-b3ed00b0f089"
name = "0a0d6458-86e9-4257-b874-b3ed00b6a11c"
password = "6e947bd5-5646-4838-a93a-b3ed00b0f176"
port = "5e7de818-6131-4372-923c-b3ed00b0efa2"
username = "30ce2424-e67c-42d5-a5ac-b3ed00b0f0fc"
}
} }
django-testing = { django-testing = {
#enabled = false #enabled =false
image = "gitea.geeraert.eu/pi-ux-ce/django-testing:latest" image = "gitea.tryton.geeraert.eu/pi-ux-ce/django-testing:latest"
service_port = [8000] service_port = [8000]
domain_name = ["django-testing", "admin-testing", "redirect-testing", "streaming-testing", "stash-testing", "simpsons-testing", "kubernetes-testing", "cloudmanager-testing", "podcast-testing"]
database = {} database = {}
#redis = {}
requirements = { requirements = {
limits-cpu = "800m" limits-cpu = "800m"
limits-memory = "800Mi" limits-memory = "800Mi"
requests-cpu = "10m" requests-cpu = "10m"
requests-memory = "300Mi" requests-memory = "300Mi"
} }
extra_manifest = ["../external_manifests/django/kubeconfig-testing.secret.yaml"] extra_manifest = ["/opt/kubernetes/Terraform_kube/external_manifests/django/kubeconfig-testing.secret.yaml"]
secret_ref = ["django-bitwarden-credentials"] secret_ref = ["django-bitwarden-credentials"]
secret_import = ["68dce7aa-8e5f-4483-9083-b474016e34fc"] secret_import = ["68dce7aa-8e5f-4483-9083-b474016e34fc"]
environment = { environment = {
@@ -188,21 +205,13 @@ kubernetes = {
value = "cloudmanager" } value = "cloudmanager" }
} }
pvc = { pvc = {
kubeconfig = { kubeconfig-secret = {
secret = true secret = true
name = "kubeconfig"
mount_path = "/kubeconfig" mount_path = "/kubeconfig"
} }
} }
import_database_secret = {
host = "097f10de-63ee-405c-b46a-b41001781e07"
name = "20530a85-e446-4d79-8985-b41001781e07"
password = "a3385f49-ba92-4478-b6f1-b4e100ff01fb"
port = "e15e00eb-db1e-47ea-ab0e-b41001781e09"
username = "3c67d310-7113-45b7-8f3f-b41001781e08"
}
} }
@@ -271,7 +280,7 @@ kubernetes = {
image = "debian" image = "debian"
enabled = false enabled = false
service_port = [19999] service_port = [19999]
domain_name = ["netdata"] domain_name = "netdata"
command = ["sleep", "3600"] command = ["sleep", "3600"]
security_context = true security_context = true
-119
View File
@@ -1,119 +0,0 @@
variable "kubernetes_input" {
type = map(object({
name = optional(string)
docker = optional(bool)
namespace = optional(string)
connected_namespace = optional(string, "")
service_port = optional(list(number))
service_type = optional(string, "ClusterIP")
domain_name = optional(list(string))
legacy_domain = optional(bool, false)
exposed = optional(bool, true)
enabled = optional(bool, true)
}))
}
resource "kubernetes_ingress_v1" "automatic_ingress" {
# Keep your top-level filter for filtering active services
for_each = { for key, value in var.kubernetes_input : key => value if value.service_port != null && value.enabled == true && value.docker != true && value.exposed == true }
metadata {
name = "${each.key}-ingress"
namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key)
annotations = {
"cert-manager.io/cluster-issuer" = "letsencrypt-prod"
"traefik.ingress.kubernetes.io/router.entrypoints" = "websecure"
}
}
spec {
ingress_class_name = "traefik"
# --- DYNAMIC TLS BLOCK ---
# Generates a separate TLS block + secret per domain entry
dynamic "tls" {
for_each = toset(coalesce(each.value.domain_name, [each.key]))
content {
hosts = [join(".", [tls.value, "geeraert.eu"])]
secret_name = "${each.key}-${tls.value}-tls-secret"
}
}
# --- DYNAMIC RULE BLOCK ---
# Loops through the domain list and creates an HTTP path routing rule for each
dynamic "rule" {
for_each = toset(coalesce(each.value.domain_name, [each.key]))
content {
host = join(".", [rule.value, "geeraert.eu"])
http {
path {
path = "/"
backend {
service {
name = "${each.key}-svc"
port {
number = each.value.service_port[0]
}
}
}
}
}
}
}
}
}
resource "kubernetes_ingress_v1" "automatic_ingress_legacy" {
for_each = { for key, value in var.kubernetes_input : key => value if value.service_port != null && value.enabled == true && value.docker != true && value.exposed == true && value.legacy_domain == true }
metadata {
name = "${each.key}-legacy-ingress"
namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key)
annotations = {
"cert-manager.io/cluster-issuer" = "letsencrypt-prod"
"traefik.ingress.kubernetes.io/router.entrypoints" = "websecure"
}
}
spec {
ingress_class_name = "traefik"
# --- DYNAMIC TLS BLOCK ---
# Generates a separate TLS block + secret per domain entry
dynamic "tls" {
for_each = toset(coalesce(each.value.domain_name, [each.key]))
content {
hosts = [join(".", [tls.value, "tryton.geeraert.eu"])]
secret_name = "${each.key}-${tls.value}-tls-secret"
}
}
# --- DYNAMIC RULE BLOCK ---
# Loops through the domain list and creates an HTTP path routing rule for each
dynamic "rule" {
for_each = toset(coalesce(each.value.domain_name, [each.key]))
content {
host = join(".", [rule.value, "tryton.geeraert.eu"])
http {
path {
path = "/"
backend {
service {
name = "${each.key}-svc"
port {
number = each.value.service_port[0]
}
}
}
}
}
}
}
}
}
-97
View File
@@ -1,97 +0,0 @@
variable "kubernetes_input" {
type = map(object({
docker = optional(bool)
namespace = optional(string)
connected_namespace = optional(string, "")
service_port = optional(list(number))
service_type = optional(string, "ClusterIP")
database = optional(map(string))
redis = optional(map(string))
enabled = optional(bool, true)
}))
}
resource "kubernetes_service_v1" "automatic_service" {
for_each = { for key, value in var.kubernetes_input : key => value if value.service_port != null && value.enabled == true && value.docker != true }
metadata {
name = "${each.key}-svc"
namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key)
labels = {
deployment_method = "Terraform"
}
annotations = each.value.service_type == "LoadBalancer" ? {
"metallb.universe.tf/ip-allocated-from-pool" = "first-pool"
} : {}
}
spec {
selector = {
app = each.key
}
dynamic "port" {
for_each = each.value.service_port != null ? each.value.service_port : []
content {
port = port.value
target_port = port.value
name = replace("${port.value}${each.key}", "/(.{0,15})(.*)/", "$1")
node_port = each.value.service_type == "NodePort" ? port.value : 0
}
}
type = each.value.service_type
}
}
resource "kubernetes_service_v1" "automatic_service_database" {
for_each = { for key, value in var.kubernetes_input : key => value if value.database != null && value.enabled == true && !(try(value.database.shunt, false)) && value.docker != true }
metadata {
name = "${each.key}-db-svc"
namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key)
labels = {
deployment_method = "Terraform"
#username = "${resource.bitwarden-secrets_secret.automatic_bitwarden_secret_password[each.key].key}"
}
}
spec {
selector = {
app = "${each.key}-db"
}
port {
port = try(each.value.database.port, 5432)
target_port = try(each.value.database.port, 5432)
}
}
}
resource "kubernetes_service_v1" "automatic_service_redis" {
for_each = { for key, value in var.kubernetes_input : key => value if value.redis != null && value.enabled == true && value.docker != true }
metadata {
name = "${each.key}-redis-svc"
namespace = coalesce(each.value.namespace, each.value.connected_namespace, each.key)
labels = {
deployment_method = "Terraform"
}
}
spec {
selector = {
app = "${each.key}-redis"
}
port {
port = 6379
target_port = 6379
}
}
}
+83
View File
@@ -0,0 +1,83 @@
terraform {
required_version = "> 0.8.0"
}
provider "kubernetes" {
config_path = "~/.kube/config"
}
variable "shunt_kubernetes" {
type = bool
default = true
}
variable "nginx_sites" {
type = map(object({
service = string
docker_service = optional(string)
enabled = optional(bool, true)
proxy_cache = optional(bool, false)
extra-value = optional(string, "")
extra-value-location = optional(string, "")
http2_bool = optional(bool, false)
proxy_pass_https = optional(bool, false)
authentication_required = optional(bool, false)
redirect_to_https_bool = optional(bool, true)
listen_port_80_bool = optional(bool, false)
geoip_blocking = optional(bool, false)
geoip_allow = optional(list(string), ["FR", "GB"])
redirect_to_root_domain = optional(bool, true)
}))
}
resource "kubernetes_config_map" "automatic-configmap" {
#avoiding this to create if the shunt_kubernetes is on
count = var.shunt_kubernetes ? 0 : 1
metadata {
name = "sites-terraform"
namespace = "reverse-proxy"
annotations = {
"reloader.stakater.com/match" : "true",
}
}
data = {
for key, value in var.nginx_sites :
"${key}.conf" => templatefile("nginx_config.tftpl", {
name_site = key
name_service = value.service
proxy_cache = value.proxy_cache
extra-value = value.extra-value
extra-value-location = value.extra-value-location
http2_bool = value.http2_bool
proxy_pass_https = value.proxy_pass_https
authentication_required = value.authentication_required
redirect_to_https_bool = value.redirect_to_https_bool
listen_port_80_bool = value.listen_port_80_bool
geoip_blocking = value.geoip_blocking
geoip_allow = value.geoip_allow
redirect_to_root_domain = value.redirect_to_root_domain
}) if value.enabled == true
}
}
resource "local_file" "nginx_configs" {
for_each = { for key, value in var.nginx_sites : key => value if value.enabled == true && value.docker_service != null }
filename = "/data/kubernetes/reverse-proxy/reverse-proxy-sites/${each.key}.conf"
content = templatefile("nginx_config.tftpl", {
name_site = each.key
name_service = each.value.docker_service
proxy_cache = each.value.proxy_cache
extra-value = each.value.extra-value
extra-value-location = each.value.extra-value-location
http2_bool = each.value.http2_bool
proxy_pass_https = each.value.proxy_pass_https
authentication_required = each.value.authentication_required
redirect_to_https_bool = each.value.redirect_to_https_bool
listen_port_80_bool = each.value.listen_port_80_bool
redirect_to_root_domain = each.value.redirect_to_root_domain
})
}
+144
View File
@@ -0,0 +1,144 @@
############################################
# config file for ${name_site}
############################################
upstream ${name_site}_backend {
server ${name_service};
server 1.1.1.1 backup;
}
server {
server_name ${name_site}.tryton.geeraert.eu www.${name_site}.tryton.geeraert.eu;
%{~ if redirect_to_root_domain~}
if ($host = www.${name_site}.tryton.geeraert.eu) {
return 301 https://${name_site}.geeraert.eu$request_uri;
}
if ($host = ${name_site}.tryton.geeraert.eu) {
return 301 https://${name_site}.geeraert.eu$request_uri;
}
%{~ endif ~}
%{ if redirect_to_root_domain != true }
location / {
proxy_pass %{ if proxy_pass_https}https%{else}http%{ endif }://${name_site}_backend;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
${extra-value-location}
}
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
%{ endif }
access_log /var/log/nginx/access.log my_custom_format;
access_log /var/log/nginx/ip_audit.log ip_audit;
access_log /var/log/nginx/backend_debug.log backend_debug;
${extra-value}
%{~ if http2_bool~}
http2 on;
ssl_protocols TLSv1.2;
%{~ endif ~}
listen 443 ssl;
%{~ if listen_port_80_bool~}
listen 80;
%{~ endif ~}
ssl_certificate /etc/nginx/ssl/live/tryton.geeraert.eu/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/live/tryton.geeraert.eu/privkey.pem;
}
%{~ if redirect_to_https_bool~}
server {
if ($host = www.${name_site}.tryton.geeraert.eu) {
return 301 https://$host$request_uri;
}
if ($host = ${name_site}.tryton.geeraert.eu) {
return 301 https://$host$request_uri;
}
server_name www.${name_site}.tryton.geeraert.eu ${name_site}.tryton.geeraert.eu ;
listen 80;
return 404;
}
%{~ endif ~}
############################################
# config file for ${name_site}
############################################
upstream ${name_site}_backend_root {
server ${name_service};
server 1.1.1.1 backup;
}
server {
server_name ${name_site}.geeraert.eu www.${name_site}.geeraert.eu;
location / {
proxy_pass %{ if proxy_pass_https}https%{else}http%{ endif }://${name_site}_backend_root;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
${extra-value-location}
}
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
access_log /var/log/nginx/access.log my_custom_format;
access_log /var/log/nginx/ip_audit.log ip_audit;
access_log /var/log/nginx/backend_debug.log backend_debug;
${extra-value}
%{~ if http2_bool~}
http2 on;
ssl_protocols TLSv1.2;
%{~ endif ~}
listen 443 ssl;
%{~ if listen_port_80_bool~}
listen 80;
%{~ endif ~}
ssl_certificate /etc/nginx/ssl/live/geeraert.eu/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/live/geeraert.eu/privkey.pem;
}
%{~ if redirect_to_https_bool~}
server {
if ($host = www.${name_site}.geeraert.eu) {
return 301 https://$host$request_uri;
}
if ($host = ${name_site}.geeraert.eu) {
return 301 https://$host$request_uri;
}
server_name www.${name_site}.geeraert.eu ${name_site}.geeraert.eu ;
listen 80;
return 404;
}
%{~ endif ~}
+600
View File
@@ -0,0 +1,600 @@
nginx_sites = {
bitwarden = {
#service = "nginx.bitwarden.svc:8080"
#extra-value-location = <<EOT
#proxy_set_header Host $host;
#proxy_set_header X-Real-IP $remote_addr;
#proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#proxy_set_header Proxy "";
# EOT
service = "bitwarden-nginx-svc.bitwarden.svc:8080"
http2_bool = true
redirect_to_root_domain = false
}
bookstack = {
enabled = false
# service = "webserver.bookstack.svc"
service = "bookstack-svc.bookstack.svc"
proxy_cache = false
}
django = {
service = "django-svc.django:8000"
proxy_cache = true
http2_bool = true
}
admin = {
service = "django-svc.django:8000"
proxy_cache = true
http2_bool = true
}
redirect = {
service = "django-svc.django:8000"
proxy_cache = true
http2_bool = true
}
streaming = {
service = "django-svc.django:8000"
proxy_cache = true
http2_bool = true
}
stash = {
service = "django-svc.django:8000"
proxy_cache = true
http2_bool = true
}
simpsons = {
service = "django-svc.django:8000"
proxy_cache = true
http2_bool = true
}
kubernetes = {
service = "django-svc.django:8000"
proxy_cache = true
http2_bool = true
}
cloudmanager = {
service = "django-svc.django:8000"
proxy_cache = true
http2_bool = true
}
podcast = {
service = "django-svc.django:8000"
proxy_cache = true
http2_bool = true
}
django-testing = {
service = "django-testing-svc.django-testing.svc:8000"
proxy_cache = true
http2_bool = true
}
admin-testing = {
service = "django-testing-svc.django-testing.svc:8000"
proxy_cache = true
http2_bool = true
}
redirect-testing = {
service = "django-testing-svc.django-testing.svc:8000"
proxy_cache = true
http2_bool = true
}
streaming-testing = {
service = "django-testing-svc.django-testing.svc:8000"
proxy_cache = true
http2_bool = true
}
stash-testing = {
service = "django-testing-svc.django-testing.svc:8000"
proxy_cache = true
http2_bool = true
}
simpsons-testing = {
service = "django-testing-svc.django-testing.svc:8000"
proxy_cache = true
http2_bool = true
}
kubernetes-testing = {
service = "django-testing-svc.django-testing.svc:8000"
proxy_cache = true
http2_bool = true
}
cloudmanager-testing = {
service = "django-testing-svc.django-testing.svc:8000"
proxy_cache = true
http2_bool = true
}
podcast-testing = {
service = "django-testing-svc.django-testing.svc:8000"
proxy_cache = true
http2_bool = true
}
echo = {
enabled = true
# service = "echo-server.echo-server.svc:80"
service = "echo-svc.echo.svc"
docker_service = "echo"
proxy_cache = true
http2_bool = true
#extra-value-location = <<EOT
# auth_request /oauth2/auth;
# error_page 401 = @oauth2_signin;
# proxy_set_header X-Auth-Request-Redirect $request_uri;
# EOT
#extra-value = <<EOT
# location = /oauth2/auth {
# internal;
#proxy_pass http://oauthn_backend;
## proxy_pass https://oauthn.tryton.geeraert.eu/oauth2/auth;
# proxy_pass_request_body off;
# proxy_set_header Content-Length "";
# proxy_set_header X-Original-URI $request_uri;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Scheme $scheme;
#}
#location @oauth2_signin {
# return 302 https://$host/oauth2/start?rd=https://$host$request_uri;
# #return 302 https://oauthn.tryton.geeraert.eu/oauth2/start?rd=https://$host$request_uri;
#}
#location /oauth2/ {
#proxy_pass http://oauthn_backend;
#proxy_set_header Host $host;
#proxy_set_header X-Real-IP $remote_addr;
#proxy_set_header X-Scheme $scheme;
#proxy_set_header X-Auth-Request-Redirect $request_uri;
#}
# EOT
}
gitlab = {
service = "webserver.gitlab.svc:443"
proxy_cache = true
extra_value_bool = true
enabled = false
extra-value = <<EOT
client_max_body_size 20m;
proxy_request_buffering off;
EOT
http2_bool = true
proxy_pass_https = true
}
sonarr = {
service = "sonarr-svc.servarr.svc:8989"
geoip_allow = ["FR", "GB", "NL"]
}
keycloak = {
service = "keycloak.keycloak.svc:8080"
enabled = false
extra-value = <<EOT
set_real_ip_from 0.0.0.0/0;
real_ip_header X-Real-IP;
real_ip_recursive on;
EOT
}
nextcloud = {
redirect_to_root_domain = false
service = "webserver.nextcloud.svc"
#service = "nextcloud-svc.next.svc"
proxy_cache = true
http2_bool = true
extra-value = <<EOT
location /.well-known/carddav {
return 301 $scheme://$host/remote.php/dav;
}
location /.well-known/caldav {
return 301 $scheme://$host/remote.php/dav;
}
location = /health {
default_type text/html;
return 200 "<!DOCTYPE html><h2>health check</h2>\n";
}
EOT
}
router = {
service = "192.168.88.1"
authentication_required = true
}
homeassistant = {
enabled = false
service = "homeassistant-svc.homeassistant.svc:8123"
}
octoprint = {
service = "192.168.0.32:5000"
extra-value-location = <<EOT
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; # Crucial for HTTPS to HTTP matching
# Required for OctoPrint WebSockets to function properly
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
client_max_body_size 0; # Allows large file uploads like gcode
EOT
}
onitama = {
service = "onitama-svc.onitama.svc:8080"
enabled = false
}
opentrashmail = {
# service = "opentrashmail.opentrashmail.svc"
service = "1.1.1.1"
enabled = false
}
paperless = {
#service = "webserver.paperless.svc:8000"
service = "paperless-svc.paperless.svc:8000"
}
pihole = {
service = "172.16.0.60:8081"
enabled = false
}
portainer = {
service = "portainer.portainer.svc"
}
prowlarr = {
service = "prowlarr-svc.servarr.svc:9696"
geoip_allow = ["FR", "GB", "NL"]
}
proxmox = {
service = "192.168.6.2:8006"
enabled = false
}
qbittorrent = {
#enabled = false
service = "qbittorrent-svc.servarr.svc:8080"
geoip_allow = ["FR", "GB", "NL"]
}
radarr = {
service = "radarr-svc.servarr.svc:7878"
geoip_allow = ["FR", "GB", "NL"]
}
recommendarr = {
service = "recommendarr-svc.servarr.svc:3000"
enabled = false
}
#reverse = {
# service = "192.168.88.50:8888"
# enabled = false
#}
sickchill = {
service = "sickchill.servarr.svc"
enabled = false
}
transmission = {
service = "192.168.88.52:31091"
enabled = false
}
unifi = {
# service = "unifi.unifi.svc:8443"
service = "192.168.88.244:8443"
proxy_pass_https = true
}
unifi-inform = {
service = "192.168.88.50:8082"
}
dupeguru = {
service = "dupeguru.dupeguru.svc:5800"
enabled = false
authentication_required = true
}
immich = {
#service = "immich-server.immich.svc:2283"
service = "immich-svc.immich.svc:2283"
geoip_allow = ["FR", "GB", "NL"]
extra-value-location = <<EOT
proxy_set_header Connection "upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 60000s;
#adding websocket , usefull for reverse proxy
proxy_set_header Connection "upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_cache_bypass $http_upgrade;
#end of working
EOT
}
immicht = {
service = "immicht-svc.immicht.svc:2283"
enabled = false
}
netdata = {
enabled = false
service = "netdata-agent.netdata.svc:19999"
}
screeps = {
enabled = false
redirect_to_https_bool = false
listen_port_80_bool = true
service = "screeps-svc.screeps.svc:25565"
}
minecraft = {
enabled = false
redirect_to_https_bool = false
listen_port_80_bool = true
service = "minecraft-svc.minecraft.svc:21025"
}
stirling = {
enabled = false
service = "stirling-svc.stirling.svc:8080"
extra-value-location = <<EOT
proxy_set_header Connection "upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 60000s;
#working
proxy_set_header Connection "upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_cache_bypass $http_upgrade;
#end of working
EOT
}
vulcan = {
service = "vulcan.vulcan.svc:80"
enabled = false
}
nginx = {
enabled = false
service = "nginx-svc.nginx.svc"
}
openmediavault = {
service = "192.168.88.29"
# service = "192.168.88.42"
}
pihole = {
service = "web.piholenew.svc"
}
jellyfin = {
enabled = false
service = "jellyfin-svc.jellyfin.svc:8096"
}
gogs = {
enabled = false
service = "gogs-svc.gogs.svc:3000"
}
synology = {
enabled = true
service = "192.168.88.39:5000"
}
gitea = {
enabled = true
service = "webserver.gitea.svc:3000"
docker_service = "gitea:3000"
redirect_to_root_domain = false
}
spider = {
enabled = false
service = "spider-svc.spider.svc:8080"
}
nextcloud-terraform = {
enabled = false
service = "nextcloud-web-svc.nextcloud-terraform.svc:80"
}
paper = {
enabled = false
service = "paper-svc.paper.svc:8000"
}
next = {
enabled = false
service = "next-svc.next.svc"
proxy_cache = true
http2_bool = true
extra-value = <<EOT
location /.well-known/carddav {
return 301 $scheme://$host/remote.php/dav;
}
location /.well-known/caldav {
return 301 $scheme://$host/remote.php/dav;
}
location = /health {
default_type text/html;
return 200 "<!DOCTYPE html><h2>health check</h2>\n";
}
EOT
}
bookstack-terraform = {
enabled = false
service = "bookstack-svc.bookstack-terraform.svc"
}
stash = {
# enabled = false
service = "stash-svc.stash.svc:9999"
#geoip_blocking = false
#extra-value= <<EOT
# proxy_protocol on;
#EOT
extra-value-location = <<EOT
#don't use this as this needs to be run as root or have the CAP_NET_RAW capability) to bind to a non-local IP address.
#Because the backend thinks the request is coming directly from the client, it will try to send the response directly back to that client IP. To prevent this (which would break the connection), you must force the response back through the NGINX server.
#proxy_bind $remote_addr transparent;
##used to be working
proxy_set_header Connection "upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 60000s;
#working
proxy_set_header Connection "upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_cache_bypass $http_upgrade;
#end of working
EOT
geoip_allow = ["FR", "GB", "NL"]
}
neko = {
enabled = false
service = "neko-svc.neko.svc:8080"
http2_bool = true
extra-value-location = <<EOT
proxy_set_header Connection "upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_cache_bypass $http_upgrade;
EOT
}
pinchflat = {
enabled = false
service = "pinchflat-svc.pinchflat.svc:8945"
}
jobspy = {
enabled = false
service = "jobspy-svc.jobspy.svc:8000"
}
poste = {
enabled = false
service = "poste-svc.poste.svc:443"
proxy_pass_https = true
extra-value-location = <<EOT
proxy_set_header Connection "upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 60000s;
#working
proxy_set_header Connection "upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_cache_bypass $http_upgrade;
#end of working
EOT
}
wikijs = {
#enabled = false
geoip_blocking = false
service = "wikijs-svc.wikijs.svc:3000"
extra-value = <<EOT
client_max_body_size 20m;
proxy_request_buffering off;
EOT
}
keycloak = {
enabled = false
service = "keycloak-svc.keycloak.svc:8080"
extra-value = <<EOT
set_real_ip_from 0.0.0.0/0;
real_ip_header X-Real-IP;
real_ip_recursive on;
EOT
}
oauthn = {
enabled = false
service = "oauth2-proxy-svc.oauth2-proxy.svc:4180"
# extra-value = <<EOT
# location /oauth2/ {
# proxy_pass http://oauthn_backend;
# proxy_set_header Host $host;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Scheme $scheme;
# }
# EOT
}
emailproxy = {
enabled = false
service = "emailproxy-svc.paper.svc:80"
}
tdarr = {
enabled = false
service = "tdarr-svc.servarr.svc:8265"
extra-value-location = <<EOT
proxy_set_header Connection "upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 60000s;
#working
proxy_set_header Connection "upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_cache_bypass $http_upgrade;
#end of working
EOT
}
opencloud = {
enabled = false
service = "opencloud-svc.opencloud.svc:9200"
proxy_pass_https = true
}
owncloud = {
enabled = false
service = "owncloud-svc.owncloud.svc:8080"
}
#overleaf = {
# service = "overleaf-svc.overleaf.svc:80"
#}
}
deny_ip = ["1.2.3.4"]