actualbudget: add enabled flag to factory, disable emo

Emo isn't using the instance and the daily bank-sync CronJob has been
failing because the budget has zero accounts (deleted from the UI),
triggering BankSyncStale. Adds an `enabled` toggle that gates the core
Deployment + Service + Ingress + http-api + CronJob behind a single
plan-time bool while preserving the PVC, so we can flip back to true
later to restore the instance as-was.

Also fixes a latent bug where the http-api Service was always created
even when `enable_http_api=false`.

Apply: 7 resources destroyed (emo deploy/svc/ingress/cf dns/http-api
deploy+svc/cronjob), 0 changes for viktor/anca (moved blocks
migrated their state cleanly to the new [0] addresses). Pushgateway
job bank-sync-emo cleared manually; orphaned external-monitor
synced out by external-monitor-sync.
This commit is contained in:
Viktor Barzin 2026-05-13 19:55:21 +00:00
parent 9fce3c7b09
commit 43affc3cdc
2 changed files with 40 additions and 12 deletions

View file

@ -18,6 +18,11 @@ variable "budget_encryption_password" {
# and are unknown at plan time on first apply, so we cannot base `count` on
# them directly. Callers pass these booleans as hardcoded plan-time constants
# that reflect whether the corresponding credentials are expected to exist.
variable "enabled" {
type = bool
default = true
description = "Deploy this instance. When false, only the PVC is kept (data preservation); deployment, service, ingress, http-api, and cronjob are not created. Flip back to true to bring the instance back."
}
variable "enable_http_api" {
type = bool
default = false
@ -68,6 +73,7 @@ resource "kubernetes_persistent_volume_claim" "data_encrypted" {
}
resource "kubernetes_deployment" "actualbudget" {
count = var.enabled ? 1 : 0
metadata {
name = "actualbudget-${var.name}"
namespace = "actualbudget"
@ -134,6 +140,7 @@ resource "kubernetes_deployment" "actualbudget" {
}
resource "kubernetes_service" "actualbudget" {
count = var.enabled ? 1 : 0
metadata {
name = "budget-${var.name}"
namespace = "actualbudget"
@ -155,6 +162,7 @@ resource "kubernetes_service" "actualbudget" {
}
module "ingress" {
count = var.enabled ? 1 : 0
source = "../../../modules/kubernetes/ingress_factory"
# auth = "app": Actual Budget enforces a server password + per-user login
# on its own sync API. Authentik forward-auth was 302-ing the mobile/web
@ -174,7 +182,7 @@ resource "random_string" "api-key" {
}
resource "kubernetes_deployment" "actualbudget-http-api" {
count = var.enable_http_api ? 1 : 0
count = var.enabled && var.enable_http_api ? 1 : 0
metadata {
name = "actualbudget-http-api-${var.name}"
namespace = "actualbudget"
@ -240,6 +248,7 @@ resource "kubernetes_deployment" "actualbudget-http-api" {
}
resource "kubernetes_service" "actualbudget-http-api" {
count = var.enabled && var.enable_http_api ? 1 : 0
metadata {
name = "budget-http-api-${var.name}"
namespace = "actualbudget"
@ -261,7 +270,7 @@ resource "kubernetes_service" "actualbudget-http-api" {
}
resource "kubernetes_cron_job_v1" "bank-sync" {
count = var.enable_bank_sync ? 1 : 0
count = var.enabled && var.enable_bank_sync ? 1 : 0
metadata {
name = "bank-sync-${var.name}"
namespace = "actualbudget"
@ -382,3 +391,24 @@ resource "kubernetes_cron_job_v1" "bank-sync" {
ignore_changes = [spec[0].job_template[0].spec[0].template[0].spec[0].dns_config]
}
}
# State migration for the new `enabled` toggle (2026-05-13): adding
# count to these resources shifts their addresses to [0]. Without
# moved {}, Terraform would destroy+recreate. Existing http-api / bank-sync
# resources already had count, so no migration needed there.
moved {
from = kubernetes_deployment.actualbudget
to = kubernetes_deployment.actualbudget[0]
}
moved {
from = kubernetes_service.actualbudget
to = kubernetes_service.actualbudget[0]
}
moved {
from = kubernetes_service.actualbudget-http-api
to = kubernetes_service.actualbudget-http-api[0]
}
moved {
from = module.ingress
to = module.ingress[0]
}

View file

@ -120,6 +120,10 @@ module "anca" {
}
# https://budget-emo.viktorbarzin.me/
# Disabled 2026-05-13: Emo isn't using this instance. PVC is preserved so
# we can flip enabled back to true to bring the instance back as-was.
# The empty accounts list (vs. anca/viktor) was causing the daily bank-sync
# CronJob to fail and trigger BankSyncStale.
module "emo" {
source = "./factory"
name = "emo"
@ -128,16 +132,10 @@ module "emo" {
nfs_server = var.nfs_server
depends_on = [kubernetes_namespace.actualbudget]
tier = local.tiers.edge
enable_http_api = true
enable_bank_sync = true
enabled = false
enable_http_api = false
enable_bank_sync = false
budget_encryption_password = lookup(local.credentials["emo"], "password", null)
sync_id = lookup(local.credentials["emo"], "sync_id", null)
homepage_annotations = {
"gethomepage.dev/enabled" = "true"
"gethomepage.dev/name" = "Budget Emo"
"gethomepage.dev/description" = "Personal budget"
"gethomepage.dev/icon" = "actual-budget.png"
"gethomepage.dev/group" = "Finance & Personal"
"gethomepage.dev/pod-selector" = ""
}
homepage_annotations = {}
}