Aller au contenu principal

ActualBudget sur Google Cloud Run

ActualBudget sur Google Cloud Run

Actual Budget est une application de finances personnelles axée sur la confidentialité et le fonctionnement en local (local-first), construite autour de la budgétisation par enveloppes à base zéro. Le composant actual-server est un serveur de synchronisation Node.js léger qui stocke chaque budget sous forme de fichier SQLite et le synchronise entre l'interface web et les clients de bureau et mobiles. Ce module déploie le serveur Actual Budget sur Cloud Run v2 en s'appuyant sur le socle App_CloudRun, qui provisionne et gère l'infrastructure Google Cloud partagée.

Ce guide se concentre sur les services cloud utilisés par ActualBudget et sur la manière de les explorer et de les exploiter depuis la console Google Cloud et la ligne de commande. Pour les mécanismes communs à toutes les applications Cloud Run — identité du service, entrée et équilibrage de charge, mise à l'échelle et concurrence, CI/CD, Cloud Armor, IAP, Binary Authorization, VPC Service Controls, sauvegardes et cycle de vie du déploiement — reportez-vous au guide du socle App_CloudRun plutôt que de les répéter ici.


1. Vue d'ensemble​

ActualBudget s'exécute sous forme d'un unique conteneur Node.js sur Cloud Run v2. Comme il gère son propre stockage SQLite, le déploiement assemble un ensemble volontairement restreint de services Google Cloud :

FonctionnalitéService Google CloudRemarques
CalculCloud Run v2Service Node.js, 1 vCPU / 1 GiB par défaut, instance unique (min = max = 1)
Base de donnéesAucuneActualBudget conserve les données de budget dans des fichiers SQLite — database_type = "NONE", pas de Cloud SQL
Données persistantesCloud Storage (GCS FUSE)Un bucket storage dédié monté sur /data contient les fichiers de budget SQLite et les fichiers utilisateur
Image de conteneurArtifact Registry + Cloud BuildBuild léger encapsulant actualbudget/actual-server, mis en miroir dans votre registre
SecretsSecret ManagerUn jeton d'API (enable_api_key), activé par défaut et requis dès que ingress_settings = "all"
EntréeURL Cloud Run / Cloud Load BalancingVaut all par défaut (public) — nécessaire pour atteindre directement l'interface web ; passez à internal pour un accès limité au VPC

Valeurs par défaut judicieuses à connaître d'emblée :

  • Pas de base de données externe. ActualBudget conserve tout sous forme de fichiers SQLite sous /data ; il n'y a ni instance Cloud SQL, ni job db-init, ni Redis (enable_redis = false), ni sidecar Cloud SQL Auth Proxy.
  • Un bucket GCS storage est provisionné automatiquement par ActualBudget_Common et monté sur /data via GCS FUSE (enable_gcs_storage_volume = true). ACTUAL_SERVER_FILES = /data/server-files et ACTUAL_USER_FILES = /data/user-files font pointer les deux arborescences de persistance vers ce montage, afin que rien n'aboutisse sur le disque éphémère du conteneur.
  • Instance unique par conception. min_instance_count = 1 et max_instance_count = 1 — le serveur sert un seul ensemble partagé de fichiers SQLite depuis un seul volume ; exécuter plusieurs réplicas expose à des conflits d'écriture.
  • L'entrée vaut all (public) par défaut, associée à une clé d'API obligatoire. ingress_settings = "all" est la valeur par défaut du module — nécessaire pour atteindre directement l'interface web — et validation.tf impose une précondition au moment du plan (ingress_settings != "all" || enable_api_key) qui rejette une entrée publique à moins que enable_api_key ne vaille aussi true. Comme enable_api_key vaut également true par défaut, les valeurs par défaut seules passent la validation et le déploiement est accessible publiquement avec une protection par jeton d'API déjà provisionnée. Passez plutôt à ingress_settings = "internal" pour un accès limité au VPC.
  • Clé d'API activée par défaut. Le mot de passe du serveur est toujours défini de manière interactive sur l'écran d'accueil de première exécution, mais enable_api_key = true (la valeur par défaut du module) provisionne en plus un jeton d'API de 32 caractères (ACTUAL_TOKEN) dans Secret Manager — requis par la précondition d'entrée ci-dessus dès que ingress_settings = "all".
  • Épinglage de version. Le Dockerfile lit un ARG de build propre à l'application, ACTUALBUDGET_VERSION ; application_version = "latest" fige le build sur 25.7.1.
  • Les sondes de santé ciblent / — le serveur répond sur son chemin racine avec un HTTP 200 dès qu'il écoute, sans authentification.
  • Plutôt adapté à un usage mono-utilisateur / léger sur Cloud Run. SQLite sur GCS FUSE ne tolère pas les écritures concurrentes intensives ; pour un stockage de production durable, préférez la variante ActualBudget_GKE avec un PVC en mode bloc.

2. Services Google Cloud et comment les explorer​

Toutes les commandes supposent que PROJECT et REGION sont définis. Les noms des services et des ressources figurent dans les sorties du déploiement.

A. Cloud Run — le service ActualBudget​

ActualBudget s'exécute comme un service Cloud Run v2 limité à une seule instance. Chaque déploiement crée une révision immuable ; lors d'une mise à jour, le trafic bascule vers la révision saine la plus récente.

  • Console : Cloud Run → sélectionnez le service pour les révisions, le trafic, les journaux et les métriques.
  • CLI :
    gcloud run services list --project "$PROJECT" --region "$REGION" \
    --filter="metadata.name~actualbudget"
    gcloud run services describe <service-name> --project "$PROJECT" --region "$REGION"
    gcloud run revisions list --service <service-name> --project "$PROJECT" --region "$REGION"

Consultez App_CloudRun pour la mise à l'échelle, la concurrence, l'environnement d'exécution et la répartition du trafic.

B. Cloud Storage — le niveau de données persistantes​

Tout l'état d'ActualBudget — les bases de données de budget SQLite, les fichiers du serveur et les données utilisateur par fichier — réside sur un bucket Cloud Storage dédié, monté dans le conteneur sur /data via GCS FUSE (environnement d'exécution gen2 requis). Le bucket survit aux déploiements de révisions, aux redémarrages et aux redéploiements ; c'est le seul endroit où existent les données de budget, considérez-le donc comme l'élément à protéger et à sauvegarder.

  • Console : Cloud Storage → Buckets.
  • CLI :
    gcloud storage buckets list --project "$PROJECT" --filter="name~actualbudget"
    gcloud storage ls -r gs://<storage-bucket>/ # bucket name is in the Outputs

Consultez App_CloudRun pour le comportement des montages GCS Fuse et CMEK.

C. Artifact Registry et Cloud Build — l'image de conteneur​

ActualBudget_Common fournit un Dockerfile léger (FROM actualbudget/actual-server:${ACTUALBUDGET_VERSION}) que Cloud Build construit dans le dépôt Artifact Registry de votre projet — les déploiements récupèrent donc l'image depuis votre registre et non depuis Docker Hub, et sont compatibles avec Binary Authorization.

  • Console : Artifact Registry → Repositories ; Cloud Build → History.
  • CLI :
    gcloud artifacts repositories list --project "$PROJECT" --location "$REGION"
    gcloud builds list --project "$PROJECT" --region "$REGION" --limit 5

D. Secret Manager — jeton d'API​

enable_api_key = true est la valeur par défaut du module : un jeton aléatoire de 32 caractères est généré, stocké dans Secret Manager sous le nom secret-<prefix>-<app>-api-key et injecté dans le service en tant que variable d'environnement secrète ACTUAL_TOKEN — utile pour les automatisations qui doivent appeler le serveur avant que l'interface ne soit configurée, et requis par validation.tf dès que ingress_settings = "all" (également la valeur par défaut).

  • Console : Security → Secret Manager.
  • CLI :
    gcloud secrets list --project "$PROJECT" --filter="name~api-key"
    gcloud secrets versions access latest --secret=<secret-name> --project "$PROJECT"

Consultez App_CloudRun pour les détails d'injection et de rotation.

E. Réseau et entrée​

Le service utilise par défaut ingress_settings = "all" ; l'URL run.app est donc accessible publiquement d'emblée (nécessaire pour atteindre directement l'interface web) — associée à la valeur par défaut obligatoire enable_api_key = true (voir §2.D). Pour un accès limité au VPC, définissez ingress_settings = "internal" ; pour un domaine personnalisé, Cloud CDN, Cloud Armor et éventuellement IAP en frontal, utilisez internal-and-cloud-load-balancing.

  • Console : Cloud Run (URL du service) ; Network services → Load balancing.
  • CLI :
    gcloud run services describe <service-name> --region "$REGION" --format='value(status.url)'
    # Tunnel to an internal-only service from your workstation:
    gcloud run services proxy <service-name> --region "$REGION" --port 8080

Consultez App_CloudRun.

F. Cloud Logging et Monitoring​

Les journaux des conteneurs sont envoyés à Cloud Logging ; les métriques de Cloud Run sont envoyées à Cloud Monitoring. Un test de disponibilité peut être activé via uptime_check_config (désactivé par défaut ; il nécessite un point de terminaison accessible publiquement — condition remplie d'emblée par la valeur par défaut ingress_settings = "all", mais pas si vous passez à internal).

  • Console : Logging → Logs Explorer ; Monitoring → Dashboards / Alerting.
  • CLI :
    gcloud run services logs read <service-name> --project "$PROJECT" --region "$REGION" --limit 50

3. Comportement de l'application ActualBudget​

  • Aucun job d'initialisation. Il n'y a pas de base de données à amorcer ; le serveur crée ses fichiers SQLite sous /data au premier démarrage. Des initialization_jobs personnalisées sont acceptées pour des tâches de chargement ou de migration de données, mais aucune n'est fournie par défaut.
  • Configuration de première exécution. Au premier accès, l'interface web affiche un écran d'accueil sur lequel vous définissez le mot de passe du serveur — il n'y a aucun identifiant prédéfini à récupérer. Faites-le immédiatement après le déploiement ; le service est accessible publiquement par défaut (ingress_settings = "all") et, tant qu'aucun mot de passe n'est défini, quiconque atteint l'URL peut s'approprier le serveur.
  • Organisation des données. ACTUAL_SERVER_FILES = /data/server-files (métadonnées du serveur et base de données des comptes) et ACTUAL_USER_FILES = /data/user-files (données de synchronisation par budget). Les deux résident sur le montage GCS FUSE ; les données de budget survivent donc aux redémarrages et aux redéploiements.
  • Modèle de synchronisation local-first. Les clients (web, bureau, mobile) conservent une copie locale complète du budget et n'utilisent le serveur que pour synchroniser les modifications chiffrées entre appareils — une brève indisponibilité du serveur n'empêche pas de travailler dans un client.
  • Contrainte d'écrivain unique. Le serveur suppose un accès exclusif à ses fichiers SQLite. Gardez max_instance_count = 1 ; une validation au moment du plan impose min_instance_count <= max_instance_count.
  • Mises à jour de version. Modifiez application_version et relancez l'apply — Cloud Build produit une nouvelle image et Cloud Run déploie une nouvelle révision. latest construit la version figée 25.7.1.
  • Point de terminaison de santé. Les sondes de démarrage et de vivacité émettent GET /, qui renvoie un HTTP 200 sans authentification dès que le serveur HTTP écoute.
  • Vérification :
    SERVICE=$(gcloud run services list --project "$PROJECT" --region "$REGION" \
    --filter="metadata.name~actualbudget" --format="value(metadata.name)" --limit=1)
    SERVICE_URL=$(gcloud run services describe "$SERVICE" \
    --project "$PROJECT" --region "$REGION" --format="value(status.url)")
    curl -s -o /dev/null -w "%{http_code}\n" "$SERVICE_URL/" # expect 200 with the default ingress=all (403/404 if switched to internal)

4. Variables de configuration​

Les variables sont regroupées exactement comme elles apparaissent sur la plateforme de déploiement. Seuls les paramètres propres à ActualBudget ou notables pour lui sont listés ; toutes les autres entrées sont héritées d'App_CloudRun avec leur comportement standard.

Groupe 1 — Projet et identité​

VariableValeur par défautDescription
project_id(obligatoire)Projet Google Cloud cible.
regionus-central1Région du service et des ressources régionales.

Groupe 2 — Environnement de déploiement​

VariableValeur par défautDescription
tenant_iddemoCourt suffixe qui rend les noms de ressources uniques par environnement.
support_users[]Adresses e-mail recevant l'accès au projet et les alertes de surveillance.

Toutes les autres entrées suivent le comportement standard d'App_CloudRun.

Groupe 3 — Identité de l'application​

VariableValeur par défautDescription
application_nameactualbudgetNom de base des ressources. Ne pas modifier après le premier déploiement.
application_versionlatestTag de version de l'image ; latest construit la version figée 25.7.1. Incrémentez-le pour déclencher un nouveau build et une nouvelle révision.
enable_api_keytrueGénère un jeton d'API de 32 caractères dans Secret Manager et l'injecte en tant que ACTUAL_TOKEN. Requis dès que ingress_settings = "all" (la valeur par défaut du module) — validation.tf rejette une entrée publique sans lui.

Toutes les autres entrées suivent le comportement standard d'App_CloudRun.

Groupe 4 — Exécution et mise à l'échelle​

VariableValeur par défautDescription
cpu_limit1000mactual-server est un processus Node.js léger ; 1 vCPU suffit.
memory_limit1GiUne mémoire modeste suffit pour des fichiers de budget typiques.
min_instance_count1Garde l'instance unique active. Définissez 0 pour la mise à l'échelle à zéro si un démarrage à froid à la première requête est acceptable.
max_instance_count1Gardez 1 — un seul volume SQLite partagé, un seul écrivain.
container_port5006Port HTTP natif d'actual-server.
execution_environmentgen2Requis pour le montage GCS FUSE /data.
enable_cloudsql_volumefalsePas de Cloud SQL — laissez false.

Toutes les autres entrées suivent le comportement standard d'App_CloudRun.

Groupe 5 — Accès et réseau​

VariableValeur par défautDescription
ingress_settingsallPublic par défaut (nécessaire pour atteindre directement l'interface web) ; validation.tf exige enable_api_key = true lorsque cette valeur est all. Définissez internal pour un accès limité au VPC, ou internal-and-cloud-load-balancing derrière un équilibreur de charge HTTPS.
enable_iapfalseAjoute une authentification par identité Google devant l'interface (chemin via l'équilibreur de charge).

Toutes les autres entrées suivent le comportement standard d'App_CloudRun.

Groupe 6 — Variables d'environnement et secrets​

VariableValeur par défautDescription
environment_variables{}Variables d'environnement en clair supplémentaires. ACTUAL_PORT, ACTUAL_SERVER_FILES et ACTUAL_USER_FILES sont injectées automatiquement.
secret_environment_variables{}Références Secret Manager supplémentaires. Le secret ACTUAL_TOKEN est raccordé automatiquement lorsque enable_api_key = true.

Toutes les autres entrées suivent le comportement standard d'App_CloudRun.

Groupes 7–10 — Sauvegarde, CI/CD, SQL personnalisé, domaine et CDN​

Comportement standard d'App_CloudRun — consultez App_CloudRun. Notez que les entrées SQL personnalisées (groupe 9) sont sans effet pour ActualBudget, puisqu'il n'y a pas d'instance Cloud SQL.

Groupe 11 — Cloud Storage et système de fichiers​

VariableValeur par défautDescription
create_cloud_storagetrueLe bucket de données storage est toujours déclaré par ActualBudget_Common.
gcs_volumes[]Montages GCS FUSE supplémentaires ; le montage de stockage /data est ajouté automatiquement.
enable_nfsfalseInutile — la persistance repose sur le bucket GCS.

Toutes les autres entrées suivent le comportement standard d'App_CloudRun.

Groupe 12 — Backend de base de données​

VariableValeur par défautDescription
database_typeNONEFixé à NONE par ActualBudget_Common — ActualBudget n'a pas de base de données SQL.

Toutes les autres entrées de ce groupe sont transmises par souci de compatibilité, mais ne sont pas utilisées.

Groupe 13 — Jobs et tâches planifiées​

VariableValeur par défautDescription
initialization_jobs[]Aucun job par défaut. Fournissez le vôtre uniquement pour un chargement ou une migration de données personnalisés.
cron_jobs[]Jobs récurrents déclenchés par Cloud Scheduler.

Groupe 14 — Observabilité et santé​

VariableValeur par défautDescription
startup_probeHTTP /, délai initial de 15 s, 10 échecsRéussit dès que le serveur Node écoute.
liveness_probeHTTP /, délai initial de 30 s, période de 30 sChemin racine, sans authentification.
uptime_check_configdésactivéN'activez-le qu'une fois le point de terminaison accessible publiquement (entrée all ou équilibreur de charge).

Toutes les autres entrées suivent le comportement standard d'App_CloudRun.

Groupe 23 — VPC Service Controls et journalisation d'audit​

enable_vpc_sc, vpc_cidr_ranges, vpc_sc_dry_run, organization_id, enable_audit_logging — comportement standard d'App_CloudRun ; consultez App_CloudRun.


5. Sorties​

Renvoyées après un déploiement réussi — le moyen le plus rapide de localiser et d'explorer les ressources en cours d'exécution.

SortieDescription
service_nameNom du service Cloud Run.
actualbudget_urlURL run.app du service. Accessible publiquement par défaut (ingress_settings = "all") ; limitée au VPC lorsque ingress_settings = "internal".
service_locationRégion dans laquelle le service s'exécute.
stage_servicesDétails des services par étape (Cloud Deploy).
load_balancer_ip / load_balancer_urlIP / URL de l'équilibreur de charge HTTPS externe (lorsqu'il est activé).
storage_bucketsBuckets Cloud Storage créés (y compris le bucket de stockage /data).
network_name / network_exists / regionsRéseau VPC, présence, régions.
container_image / container_registryImage déployée et dépôt Artifact Registry.
monitoring_enabled / monitoring_notification_channels / uptime_check_namesÉtat de la surveillance, canaux, tests de disponibilité.
initialization_jobsNoms des éventuels jobs de configuration personnalisés (vide par défaut).
deployment_id / tenant_id / resource_prefixIdentifiants de nommage.
project_id / project_numberIdentifiants du projet.
cicd_enabled / github_repository_url / github_repository_owner / github_repository_name / cicd_configurationÉtat et détails du CI/CD.
artifact_registry_repository / cloudbuild_trigger_name / cloudbuild_trigger_idRegistre et déclencheur de build.
vpc_sc_enabled / vpc_sc_perimeter_name / vpc_sc_dry_run_modeÉtat de VPC-SC.
audit_logging_enabled / artifact_registry_cmek_enabledÉtat des journaux d'audit et de CMEK.

6. Pièges de configuration et valeurs par défaut judicieuses​

Le module intègre une validation au moment du plan pour les erreurs de configuration les plus dommageables (par exemple min_instance_count <= max_instance_count), mais plusieurs paramètres méritent une attention particulière :

Risque : Critique (perte de données / panne / sécurité) — Élevé (service dégradé) — Moyen (coût ou dégradation partielle) — Faible (mineur).

ParamètreValeur judicieuseRisqueConséquence en cas d'erreur
max_instance_count1CritiquePlusieurs instances écrivent les mêmes fichiers SQLite sur un seul volume partagé — risque de corruption/de conflit.
Mot de passe du serveur à la première exécutionà définir immédiatementCritiqueTant qu'aucun mot de passe n'est défini, quiconque atteint l'URL peut s'approprier le serveur et ses données de budget.
Contenu du bucket de stockagene jamais le supprimer manuellementCritique/data sur le bucket GCS est la seule copie des bases de données de budget ; supprimer le bucket efface tous les budgets.
container_port5006CritiquePort natif d'actual-server ; une valeur différente fait échouer toutes les sondes de santé.
execution_environmentgen2ÉlevéLes montages de volumes GCS FUSE nécessitent gen2 ; gen1 laisse /data non monté et les données sur un disque éphémère.
ingress_settings = "all" (la valeur par défaut)définir le mot de passe du serveur immédiatement après le déploiementCritiqueLe service est accessible publiquement par défaut ; un serveur non revendiqué peut être approprié par le premier venu qui atteint l'URL. Définissez plutôt internal si l'accès public n'est pas nécessaire.
ingress_settings = "all" avec enable_api_key = falsecombinaison non valideCritiquevalidation.tf impose ingress_settings != "all" || enable_api_key au moment du plan — cette combinaison fait échouer le plan d'emblée au lieu de déployer de manière non sécurisée. Les deux valeurs par défaut satisfont déjà la précondition (all + true), si bien que les valeurs par défaut seules se déploient sans erreur ; seul un remplacement explicite par enable_api_key = false en laissant l'entrée à all déclenche l'échec.
Charge d'écriture multi-utilisateur intensivepasser à ActualBudget_GKE (PVC en mode bloc)ÉlevéSQLite ne tolère pas GCS FUSE sous des écritures concurrentes intensives ; Cloud Run convient à un usage mono-utilisateur / léger.
enable_api_keytrue (la valeur par défaut)MoyenSans ACTUAL_TOKEN, l'accès programmatique à l'API repose uniquement sur le mot de passe du serveur. Également requis par la précondition d'entrée ci-dessus dès que ingress_settings = "all".
min_instance_count1 (ou 0 pour réduire les coûts)Moyen0 ajoute un démarrage à froid à la première requête après une période d'inactivité ; les données sont en sécurité dans les deux cas (l'état est sur GCS).
uptime_check_configà activer tant que l'entrée est publiqueFaibleSi ingress_settings passe à internal, le test ne peut pas atteindre le service et échouera systématiquement.

Pour le comportement du socle évoqué tout au long de cette page — identité du service, mise à l'échelle et concurrence, entrée et équilibrage de charge, CI/CD, Cloud Armor, IAP, Binary Authorization, VPC-SC, sauvegardes et mise en miroir des images — consultez App_CloudRun. La configuration applicative propre à ActualBudget partagée avec la variante GKE est décrite dans ActualBudget_Common.

Need RAD to do something it does not do yet? Request it on the roadmap, or vote on what is already there.