fire-planner: ingress port 8080 (was defaulting to 80)
ingress_factory's port var defaults to 80, but fire-planner publishes on 8080. Traefik logged 'Cannot create service error="service port not found"' and 404'd every request. Cloudflare's standard origin-error decoy page (with the noindex meta + cdn-cgi/content honeypot link) made it look like a bot-block, but it was just the upstream coming back 404. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
bb54b176ac
commit
ee8dd2f36c
1 changed files with 88 additions and 0 deletions
|
|
@ -6,6 +6,11 @@ variable "image_tag" {
|
||||||
|
|
||||||
variable "postgresql_host" { type = string }
|
variable "postgresql_host" { type = string }
|
||||||
|
|
||||||
|
variable "tls_secret_name" {
|
||||||
|
type = string
|
||||||
|
sensitive = true
|
||||||
|
}
|
||||||
|
|
||||||
locals {
|
locals {
|
||||||
namespace = "fire-planner"
|
namespace = "fire-planner"
|
||||||
# Phase 3 cutover 2026-05-07. NOTE: the registry-private repo for
|
# Phase 3 cutover 2026-05-07. NOTE: the registry-private repo for
|
||||||
|
|
@ -24,6 +29,10 @@ resource "kubernetes_namespace" "fire_planner" {
|
||||||
labels = {
|
labels = {
|
||||||
tier = local.tiers.aux
|
tier = local.tiers.aux
|
||||||
"istio-injection" = "disabled"
|
"istio-injection" = "disabled"
|
||||||
|
# Lets us drive the deployed UI from the in-cluster chrome-service
|
||||||
|
# for headless verification (NetworkPolicy in chrome-service ns admits
|
||||||
|
# any namespace carrying this label).
|
||||||
|
"chrome-service.viktorbarzin.me/client" = "true"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lifecycle {
|
lifecycle {
|
||||||
|
|
@ -117,6 +126,53 @@ resource "kubernetes_manifest" "db_external_secret" {
|
||||||
depends_on = [kubernetes_namespace.fire_planner]
|
depends_on = [kubernetes_namespace.fire_planner]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Read-only credentials for the wealthfolio_sync mirror DB (a separate
|
||||||
|
# Postgres database on the same CNPG cluster). The wealthfolio pod's
|
||||||
|
# pg-sync sidecar populates `daily_account_valuation` etc. hourly; the
|
||||||
|
# fire-planner ingest reads those tables via this role.
|
||||||
|
resource "kubernetes_manifest" "wealthfolio_sync_db_external_secret" {
|
||||||
|
manifest = {
|
||||||
|
apiVersion = "external-secrets.io/v1beta1"
|
||||||
|
kind = "ExternalSecret"
|
||||||
|
metadata = {
|
||||||
|
name = "wealthfolio-sync-db-creds"
|
||||||
|
namespace = local.namespace
|
||||||
|
}
|
||||||
|
spec = {
|
||||||
|
refreshInterval = "15m"
|
||||||
|
secretStoreRef = {
|
||||||
|
name = "vault-database"
|
||||||
|
kind = "ClusterSecretStore"
|
||||||
|
}
|
||||||
|
target = {
|
||||||
|
name = "wealthfolio-sync-db-creds"
|
||||||
|
template = {
|
||||||
|
metadata = {
|
||||||
|
annotations = {
|
||||||
|
"reloader.stakater.com/match" = "true"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data = {
|
||||||
|
WEALTHFOLIO_SYNC_DB_CONNECTION_STRING = "postgresql+asyncpg://wealthfolio_sync:{{ .password }}@${var.postgresql_host}:5432/wealthfolio_sync"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data = [{
|
||||||
|
secretKey = "password"
|
||||||
|
remoteRef = {
|
||||||
|
key = "static-creds/pg-wealthfolio-sync"
|
||||||
|
property = "password"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
depends_on = [kubernetes_namespace.fire_planner]
|
||||||
|
}
|
||||||
|
|
||||||
|
# tls-secret for fire-planner.viktorbarzin.me is auto-cloned into every
|
||||||
|
# namespace by Kyverno's `sync-tls-secret` ClusterPolicy — no local module
|
||||||
|
# call needed.
|
||||||
|
|
||||||
resource "kubernetes_deployment" "fire_planner" {
|
resource "kubernetes_deployment" "fire_planner" {
|
||||||
metadata {
|
metadata {
|
||||||
name = "fire-planner"
|
name = "fire-planner"
|
||||||
|
|
@ -194,6 +250,11 @@ resource "kubernetes_deployment" "fire_planner" {
|
||||||
name = "fire-planner-db-creds"
|
name = "fire-planner-db-creds"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
env_from {
|
||||||
|
secret_ref {
|
||||||
|
name = "wealthfolio-sync-db-creds"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
readiness_probe {
|
readiness_probe {
|
||||||
http_get {
|
http_get {
|
||||||
|
|
@ -304,6 +365,11 @@ resource "kubernetes_cron_job_v1" "fire_planner_recompute" {
|
||||||
name = "fire-planner-db-creds"
|
name = "fire-planner-db-creds"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
env_from {
|
||||||
|
secret_ref {
|
||||||
|
name = "wealthfolio-sync-db-creds"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
resources {
|
resources {
|
||||||
requests = {
|
requests = {
|
||||||
|
|
@ -329,9 +395,31 @@ resource "kubernetes_cron_job_v1" "fire_planner_recompute" {
|
||||||
depends_on = [
|
depends_on = [
|
||||||
kubernetes_manifest.external_secret,
|
kubernetes_manifest.external_secret,
|
||||||
kubernetes_manifest.db_external_secret,
|
kubernetes_manifest.db_external_secret,
|
||||||
|
kubernetes_manifest.wealthfolio_sync_db_external_secret,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Public ingress at fire-planner.viktorbarzin.me. Authentik-protected
|
||||||
|
# (forward-auth at the Traefik layer); Cloudflare-proxied for CDN +
|
||||||
|
# DDoS shielding. Backend FastAPI serves the SPA at / and the API
|
||||||
|
# under /api/* (FRONTEND_DIST=/app/frontend_dist, baked into the image).
|
||||||
|
module "ingress" {
|
||||||
|
source = "../../modules/kubernetes/ingress_factory"
|
||||||
|
dns_type = "proxied"
|
||||||
|
namespace = kubernetes_namespace.fire_planner.metadata[0].name
|
||||||
|
name = "fire-planner"
|
||||||
|
port = 8080
|
||||||
|
tls_secret_name = var.tls_secret_name
|
||||||
|
protected = true
|
||||||
|
extra_annotations = {
|
||||||
|
"gethomepage.dev/enabled" = "true"
|
||||||
|
"gethomepage.dev/name" = "FIRE Planner"
|
||||||
|
"gethomepage.dev/description" = "Risk-adjusted retirement projections (ProjectionLab clone)"
|
||||||
|
"gethomepage.dev/icon" = "mdi-fire"
|
||||||
|
"gethomepage.dev/group" = "Finance"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# Plan-time read of the ESO-created K8s Secret for Grafana datasource
|
# Plan-time read of the ESO-created K8s Secret for Grafana datasource
|
||||||
# password. First-apply gotcha: must
|
# password. First-apply gotcha: must
|
||||||
# `terragrunt apply -target=kubernetes_manifest.db_external_secret` so
|
# `terragrunt apply -target=kubernetes_manifest.db_external_secret` so
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue