infra/stacks/stem95su/main.tf
Viktor Barzin fd0f4a0365 fix: restore tree dropped by 6d224861; land stem95su gdrive-sync (10m) [ci skip]
6d224861 came from a --no-checkout worktree whose empty index made the
commit drop every file except two. This restores 05b50d2b's full tree and
correctly adds stacks/stem95su/gdrive-sync.tf + the service-catalog stem95su
entry. Forward-only (parent=6d224861, no force-push); [ci skip] since the
live infra was never applied from the broken commit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 08:45:33 +00:00

173 lines
4.8 KiB
HCL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# STEM educational platform for 95. СУ „Проф. Иван Шишманов" (Sofia).
# Public, open static site at stem95su.viktorbarzin.me. Self-contained HTML
# pages + media authored externally (Gemini exports), served by a stock nginx
# straight off the PVE host NFS — NOT baked into an image, so content can be
# updated out-of-band (Nextcloud "PVE NFS Pool" or rsync to /srv/nfs/stem-site)
# without a rebuild. Auto-backed-up offsite by the existing nfs-mirror job.
resource "kubernetes_namespace" "stem95su" {
metadata {
name = "stem95su"
labels = {
"istio-injection" : "disabled"
tier = local.tiers.aux
}
}
lifecycle {
# KYVERNO_LIFECYCLE_V1: goldilocks-vpa-auto-mode ClusterPolicy stamps this label on every namespace
ignore_changes = [metadata[0].labels["goldilocks.fairwinds.com/vpa-update-mode"]]
}
}
module "tls_secret" {
source = "../../modules/kubernetes/setup_tls_secret"
namespace = kubernetes_namespace.stem95su.metadata[0].name
tls_secret_name = var.tls_secret_name
}
# Content lives on the PVE host NFS. NOTE: the nfs_volume module creates only
# the K8s PV+PVC — the export subdir (/srv/nfs/stem-site) must already exist on
# 192.168.1.127 or the pod fails to mount (mount.nfs exit 32). It is created
# during deploy and re-created on demand if ever lost.
module "nfs_content" {
source = "../../modules/kubernetes/nfs_volume"
name = "stem95su-content"
namespace = kubernetes_namespace.stem95su.metadata[0].name
nfs_server = var.nfs_server
nfs_path = "/srv/nfs/stem-site"
storage = "1Gi"
access_modes = ["ReadWriteMany"]
}
# Minimal nginx server block: serve the static dir, with the dashboard
# (stem_board.html) as the directory index so "/" loads the platform home.
# All other pages/assets are reached by their exact filenames (the dashboard
# links to them by name — those must not be renamed).
resource "kubernetes_config_map" "nginx_conf" {
metadata {
name = "stem95su-nginx-conf"
namespace = kubernetes_namespace.stem95su.metadata[0].name
}
data = {
"default.conf" = <<-EOT
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index stem_board.html index.html;
}
EOT
}
}
resource "kubernetes_deployment" "stem95su" {
metadata {
name = "stem95su"
namespace = kubernetes_namespace.stem95su.metadata[0].name
labels = {
run = "stem95su"
tier = local.tiers.aux
}
}
spec {
replicas = 1
selector {
match_labels = {
run = "stem95su"
}
}
template {
metadata {
labels = {
run = "stem95su"
}
}
spec {
container {
image = "nginx:1.28-alpine"
name = "nginx"
resources {
limits = {
memory = "64Mi"
}
requests = {
cpu = "10m"
memory = "64Mi"
}
}
port {
container_port = 80
}
volume_mount {
name = "content"
mount_path = "/usr/share/nginx/html"
read_only = true
}
volume_mount {
name = "nginx-conf"
mount_path = "/etc/nginx/conf.d"
read_only = true
}
readiness_probe {
http_get {
path = "/"
port = 80
}
initial_delay_seconds = 3
period_seconds = 10
}
}
volume {
name = "content"
persistent_volume_claim {
claim_name = module.nfs_content.claim_name
}
}
volume {
name = "nginx-conf"
config_map {
name = kubernetes_config_map.nginx_conf.metadata[0].name
}
}
}
}
}
lifecycle {
ignore_changes = [
spec[0].template[0].spec[0].dns_config, # KYVERNO_LIFECYCLE_V1
]
}
}
resource "kubernetes_service" "stem95su" {
metadata {
name = "stem95su"
namespace = kubernetes_namespace.stem95su.metadata[0].name
labels = {
run = "stem95su"
}
}
spec {
selector = {
run = "stem95su"
}
port {
name = "http"
port = "80"
target_port = "80"
}
}
}
module "ingress" {
source = "../../modules/kubernetes/ingress_factory"
# auth = "none": public static educational site for 95. СУ, open to the internet by design — CrowdSec + ai-bot-block gate bots; no login.
auth = "none"
namespace = kubernetes_namespace.stem95su.metadata[0].name
name = "stem95su"
service_name = kubernetes_service.stem95su.metadata[0].name
port = "80"
host = "stem95su"
dns_type = "proxied"
tls_secret_name = var.tls_secret_name
}