From 4d3d3316abb29a67395b83b1abe6817c8d3f4d71 Mon Sep 17 00:00:00 2001 From: Viktor Barzin Date: Fri, 10 Apr 2026 14:19:25 +0000 Subject: [PATCH] feat(phpipam): deploy phpIPAM for live IP address management Lightweight IPAM with auto-discovery scanning every 15min via fping. Replaces disabled NetBox (OOM'd). Uses existing MySQL InnoDB cluster with Vault-rotated credentials. Cloudflare DNS + Authentik auth. [ci skip] Co-Authored-By: Claude Opus 4.6 (1M context) --- config.tfvars | Bin 10121 -> 10132 bytes stacks/phpipam/main.tf | 260 ++++++++++++++++++++++++++++++++++ stacks/phpipam/terragrunt.hcl | 8 ++ stacks/vault/main.tf | 10 +- 4 files changed, 277 insertions(+), 1 deletion(-) create mode 100644 stacks/phpipam/main.tf create mode 100644 stacks/phpipam/terragrunt.hcl diff --git a/config.tfvars b/config.tfvars index 213689ff76427007aa2897260666259e395f201a..2ef9c6d244d28b7cf84e40e3a8b7100d410b9efe 100644 GIT binary patch literal 10132 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 diff --git a/stacks/phpipam/main.tf b/stacks/phpipam/main.tf new file mode 100644 index 00000000..dab4cf22 --- /dev/null +++ b/stacks/phpipam/main.tf @@ -0,0 +1,260 @@ +variable "tls_secret_name" { + type = string + sensitive = true +} +variable "mysql_host" { type = string } + +resource "kubernetes_namespace" "phpipam" { + metadata { + name = "phpipam" + labels = { + tier = local.tiers.aux + } + } +} + +resource "kubernetes_manifest" "external_secret" { + manifest = { + apiVersion = "external-secrets.io/v1beta1" + kind = "ExternalSecret" + metadata = { + name = "phpipam-secrets" + namespace = "phpipam" + } + spec = { + refreshInterval = "15m" + secretStoreRef = { + name = "vault-database" + kind = "ClusterSecretStore" + } + target = { + name = "phpipam-secrets" + } + data = [{ + secretKey = "db_password" + remoteRef = { + key = "static-creds/mysql-phpipam" + property = "password" + } + }] + } + } + depends_on = [kubernetes_namespace.phpipam] +} + +module "tls_secret" { + source = "../../modules/kubernetes/setup_tls_secret" + namespace = kubernetes_namespace.phpipam.metadata[0].name + tls_secret_name = var.tls_secret_name +} + +resource "kubernetes_deployment" "phpipam_web" { + metadata { + name = "phpipam-web" + namespace = kubernetes_namespace.phpipam.metadata[0].name + labels = { + app = "phpipam" + tier = local.tiers.aux + } + annotations = { + "reloader.stakater.com/auto" = "true" + } + } + spec { + replicas = 1 + strategy { + type = "Recreate" + } + selector { + match_labels = { + app = "phpipam" + } + } + template { + metadata { + labels = { + app = "phpipam" + } + annotations = { + "diun.enable" = "true" + "dependency.kyverno.io/wait-for" = "mysql.dbaas:3306" + } + } + spec { + container { + image = "phpipam/phpipam-www:v1.7.0" + name = "phpipam-web" + port { + container_port = 80 + } + env { + name = "TZ" + value = "Europe/Sofia" + } + env { + name = "IPAM_DATABASE_HOST" + value = var.mysql_host + } + env { + name = "IPAM_DATABASE_USER" + value = "phpipam" + } + env { + name = "IPAM_DATABASE_PASS" + value_from { + secret_key_ref { + name = "phpipam-secrets" + key = "db_password" + } + } + } + env { + name = "IPAM_DATABASE_NAME" + value = "phpipam" + } + env { + name = "IPAM_TRUST_X_FORWARDED" + value = "true" + } + resources { + requests = { + cpu = "10m" + memory = "64Mi" + } + limits = { + memory = "256Mi" + } + } + } + } + } + } + lifecycle { + ignore_changes = [spec[0].template[0].spec[0].dns_config] + } +} + +resource "kubernetes_deployment" "phpipam_cron" { + metadata { + name = "phpipam-cron" + namespace = kubernetes_namespace.phpipam.metadata[0].name + labels = { + app = "phpipam-cron" + component = "scanner" + tier = local.tiers.aux + } + annotations = { + "reloader.stakater.com/auto" = "true" + } + } + spec { + replicas = 1 + strategy { + type = "Recreate" + } + selector { + match_labels = { + app = "phpipam-cron" + } + } + template { + metadata { + labels = { + app = "phpipam-cron" + component = "scanner" + } + annotations = { + "dependency.kyverno.io/wait-for" = "mysql.dbaas:3306" + } + } + spec { + container { + image = "phpipam/phpipam-cron:v1.7.0" + name = "phpipam-cron" + env { + name = "TZ" + value = "Europe/Sofia" + } + env { + name = "IPAM_DATABASE_HOST" + value = var.mysql_host + } + env { + name = "IPAM_DATABASE_USER" + value = "phpipam" + } + env { + name = "IPAM_DATABASE_PASS" + value_from { + secret_key_ref { + name = "phpipam-secrets" + key = "db_password" + } + } + } + env { + name = "IPAM_DATABASE_NAME" + value = "phpipam" + } + env { + name = "SCAN_INTERVAL" + value = "15m" + } + resources { + requests = { + cpu = "10m" + memory = "64Mi" + } + limits = { + memory = "512Mi" + } + } + security_context { + capabilities { + add = ["NET_RAW"] + } + } + } + } + } + } + lifecycle { + ignore_changes = [spec[0].template[0].spec[0].dns_config] + } +} + +resource "kubernetes_service" "phpipam" { + metadata { + name = "phpipam" + namespace = kubernetes_namespace.phpipam.metadata[0].name + labels = { + app = "phpipam" + } + } + spec { + selector = { + app = "phpipam" + } + port { + name = "http" + port = 80 + target_port = 80 + } + } +} + +module "ingress" { + source = "../../modules/kubernetes/ingress_factory" + namespace = kubernetes_namespace.phpipam.metadata[0].name + name = "phpipam" + tls_secret_name = var.tls_secret_name + protected = true + extra_annotations = { + "gethomepage.dev/enabled" = "true" + "gethomepage.dev/name" = "phpIPAM" + "gethomepage.dev/description" = "IP Address Management" + "gethomepage.dev/icon" = "phpipam.png" + "gethomepage.dev/group" = "Infrastructure" + "gethomepage.dev/pod-selector" = "" + } +} diff --git a/stacks/phpipam/terragrunt.hcl b/stacks/phpipam/terragrunt.hcl new file mode 100644 index 00000000..0d1c8e53 --- /dev/null +++ b/stacks/phpipam/terragrunt.hcl @@ -0,0 +1,8 @@ +include "root" { + path = find_in_parent_folders() +} + +dependency "platform" { + config_path = "../platform" + skip_outputs = true +} diff --git a/stacks/vault/main.tf b/stacks/vault/main.tf index c106dd51..59fd8bba 100644 --- a/stacks/vault/main.tf +++ b/stacks/vault/main.tf @@ -466,7 +466,7 @@ resource "vault_database_secret_backend_connection" "mysql" { allowed_roles = [ "mysql-speedtest", "mysql-wrongmove", "mysql-codimd", "mysql-nextcloud", "mysql-shlink", "mysql-grafana", - "mysql-technitium" + "mysql-technitium", "mysql-phpipam" ] mysql { @@ -553,6 +553,14 @@ resource "vault_database_secret_backend_static_role" "mysql_technitium" { rotation_period = 604800 } +resource "vault_database_secret_backend_static_role" "mysql_phpipam" { + backend = vault_mount.database.path + db_name = vault_database_secret_backend_connection.mysql.name + name = "mysql-phpipam" + username = "phpipam" + rotation_period = 604800 +} + # --- PostgreSQL Static Roles --- /*