From 719cc3436ef2e9d9f6047624a0c6dfc85eff3320 Mon Sep 17 00:00:00 2001 From: Viktor Barzin Date: Sat, 21 Oct 2023 12:14:31 +0000 Subject: [PATCH] update tls certs; add technitium doh open without recursion for now; add dashy web --- modules/kubernetes/dashy/main.tf | 203 ++++++++++++++++++++++++++ modules/kubernetes/main.tf | 5 + modules/kubernetes/technitium/main.tf | 51 +++++++ secrets/certificate.pfx | Bin 0 -> 4534 bytes secrets/fullchain.pem | Bin 5288 -> 5288 bytes secrets/privkey.pem | Bin 263 -> 263 bytes 6 files changed, 259 insertions(+) create mode 100644 modules/kubernetes/dashy/main.tf create mode 100644 secrets/certificate.pfx diff --git a/modules/kubernetes/dashy/main.tf b/modules/kubernetes/dashy/main.tf new file mode 100644 index 00000000..07b6da45 --- /dev/null +++ b/modules/kubernetes/dashy/main.tf @@ -0,0 +1,203 @@ + +variable "tls_secret_name" {} + +module "tls_secret" { + source = "../setup_tls_secret" + namespace = "dashy" + tls_secret_name = var.tls_secret_name +} + +resource "kubernetes_namespace" "dashy" { + metadata { + name = "dashy" + } +} + +resource "kubernetes_config_map" "config" { + metadata { + name = "config" + namespace = "dashy" + + annotations = { + "reloader.stakater.com/match" = "true" + } + } + + data = { + "conf.yaml" = <<-EOT +--- +pageInfo: + title: Dashy + description: Welcome to your new dashboard! + navLinks: + - title: GitHub + path: https://github.com/Lissy93/dashy + - title: Documentation + path: https://dashy.to/docs +appConfig: + theme: colorful + layout: auto + iconSize: large + language: en +sections: + - name: Getting Started + icon: fas fa-rocket + items: + - &ref_0 + title: Dashy Live + description: Development a project management links for Dashy + icon: https://i.ibb.co/qWWpD0v/astro-dab-128.png + url: https://live.dashy.to/ + target: newtab + id: 0_1481_dashylive + - &ref_1 + title: GitHub + description: Source Code, Issues and Pull Requests + url: https://github.com/lissy93/dashy + icon: favicon + id: 1_1481_github + - &ref_2 + title: Docs + description: Configuring & Usage Documentation + provider: Dashy.to + icon: far fa-book + url: https://dashy.to/docs + id: 2_1481_docs + - &ref_3 + title: Showcase + description: See how others are using Dashy + url: https://github.com/Lissy93/dashy/blob/master/docs/showcase.md + icon: far fa-grin-hearts + id: 3_1481_showcase + - &ref_4 + title: Config Guide + description: See full list of configuration options + url: https://github.com/Lissy93/dashy/blob/master/docs/configuring.md + icon: fas fa-wrench + id: 4_1481_configguide + - &ref_5 + title: Support + description: Get help with Dashy, raise a bug, or get in contact + url: https://github.com/Lissy93/dashy/blob/master/.github/SUPPORT.md + icon: far fa-hands-helping + id: 5_1481_support + filteredItems: + - *ref_0 + - *ref_1 + - *ref_2 + - *ref_3 + - *ref_4 + - *ref_5 + + EOT + } +} + +resource "kubernetes_deployment" "dashy" { + metadata { + name = "dashy" + namespace = "dashy" + labels = { + app = "dashy" + } + annotations = { + "reloader.stakater.com/search" = "true" + } + } + spec { + replicas = 1 + selector { + match_labels = { + app = "dashy" + } + } + template { + metadata { + labels = { + app = "dashy" + } + } + spec { + container { + image = "lissy93/dashy:latest" + name = "dashy" + + port { + container_port = 80 + } + # volume_mount { + # name = "config" + # mount_path = "/app/public/" + # } + + + } + volume { + name = "config" + config_map { + name = "config" + } + } + } + } + } +} + +resource "kubernetes_service" "dashy" { + metadata { + name = "dashy" + namespace = "dashy" + labels = { + app = "dashy" + } + } + + spec { + selector = { + app = "dashy" + } + port { + name = "http" + port = "80" + } + } +} + +resource "kubernetes_ingress_v1" "dashy" { + metadata { + name = "dashy-ingress" + namespace = "dashy" + annotations = { + "kubernetes.io/ingress.class" = "nginx" + //"nginx.ingress.kubernetes.io/auth-tls-verify-client" = "on" + //"nginx.ingress.kubernetes.io/auth-tls-secret" = "default/ca-secret" + # "nginx.ingress.kubernetes.io/auth-url" : "https://$host/oauth2/auth" + "nginx.ingress.kubernetes.io/auth-url" : "https://viktorbarzin.uk.auth0.com//oauth2/auth" + # "nginx.ingress.kubernetes.io/auth-signin" : "https://$host/oauth2/start?rd=$escaped_request_uri" + "nginx.ingress.kubernetes.io/auth-signin" : "https://viktorbarzin.uk.auth0.com//oauth2/start?rd=$escaped_request_uri" + } + } + + spec { + tls { + hosts = ["dashy.viktorbarzin.me"] + secret_name = var.tls_secret_name + } + rule { + host = "dashy.viktorbarzin.me" + http { + path { + path = "/" + backend { + service { + name = "dashy" + port { + number = 80 + } + } + } + } + } + } + } +} diff --git a/modules/kubernetes/main.tf b/modules/kubernetes/main.tf index c4a41b91..d14684de 100644 --- a/modules/kubernetes/main.tf +++ b/modules/kubernetes/main.tf @@ -311,3 +311,8 @@ module "headscale" { # source = "./metrics_api" # tls_secret_name = var.tls_secret_name # } + +module "dashy" { + source = "./dashy" + tls_secret_name = var.tls_secret_name +} diff --git a/modules/kubernetes/technitium/main.tf b/modules/kubernetes/technitium/main.tf index 1447012b..0b3a0fe5 100644 --- a/modules/kubernetes/technitium/main.tf +++ b/modules/kubernetes/technitium/main.tf @@ -58,10 +58,17 @@ resource "kubernetes_deployment" "technitium" { port { container_port = 53 } + port { + container_port = 80 + } volume_mount { mount_path = "/etc/dns" name = "nfs-config" } + volume_mount { + mount_path = "/etc/tls/" + name = "tls-cert" + } } volume { name = "nfs-config" @@ -70,6 +77,12 @@ resource "kubernetes_deployment" "technitium" { server = "10.0.10.15" } } + volume { + name = "tls-cert" + secret { + secret_name = var.tls_secret_name + } + } } } } @@ -99,6 +112,11 @@ resource "kubernetes_service" "technitium-web" { port = "5380" protocol = "TCP" } + port { + name = "technitium-doh" + port = "80" + protocol = "TCP" + } } } @@ -167,3 +185,36 @@ resource "kubernetes_ingress_v1" "technitium" { } } } + +resource "kubernetes_ingress_v1" "technitium-doh" { + metadata { + name = "technitium-doh-ingress" + namespace = "technitium" + annotations = { + "kubernetes.io/ingress.class" = "nginx" + } + } + + spec { + tls { + hosts = ["dns.viktorbarzin.me"] + secret_name = var.tls_secret_name + } + rule { + host = "dns.viktorbarzin.me" + http { + path { + path = "/" + backend { + service { + name = "technitium-web" + port { + number = 80 + } + } + } + } + } + } + } +} diff --git a/secrets/certificate.pfx b/secrets/certificate.pfx new file mode 100644 index 0000000000000000000000000000000000000000..b850eb6b5986badb1e7798831b084e0017da48a9 GIT binary patch literal 4534 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 literal 5288 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 NLnG4dsrNZ{4tD`zd(;2`