WriteFreely Common — Configuration applicative partagée
WriteFreely_Common est la couche applicative partagée de WriteFreely. Elle n'est pas déployée seule ; elle fournit la configuration propre à WriteFreely sur laquelle s'appuient à la fois WriteFreely_GKE et WriteFreely_CloudRun, afin que les deux variantes de plateforme se comportent de manière identique là où cela compte. Les utilisateurs finaux ne configurent jamais cette couche directement — elle ne possède aucune entrée d'interface de déploiement qui lui soit propre — mais comprendre ce qu'elle fournit explique les valeurs par défaut que vous voyez dans la documentation des plateformes.
Pour l'infrastructure qui provisionne et exécute réellement WriteFreely, consultez les guides de plateforme (WriteFreely_GKE, WriteFreely_CloudRun) et les guides du socle (App_GKE, App_CloudRun, App_Common).
1. Ce que fournit cette couche
| Domaine | Fourni par WriteFreely_Common | Où cela apparaît |
|---|---|---|
| Clés cryptographiques | Génère trois fichiers de clés AES-256 (32 octets) — cookies_auth, cookies_enc, email — et les stocke dans Secret Manager en base64 | Injectées sous forme de WF_KEY_COOKIES_AUTH / WF_KEY_COOKIES_ENC / WF_KEY_EMAIL ; à récupérer via Secret Manager (voir ci-dessous) |
| Image de conteneur | Construit un wrapper personnalisé léger au-dessus de l'image officielle writeas/writefreely, en ajoutant un point d'entrée de génération de configuration ; construit via Cloud Build | Sortie container_image du déploiement de la plateforme |
| Moteur de base de données | Fixe Cloud SQL for MySQL 8.0 (database_type = MYSQL_8_0) comme moteur | §Base de données dans les guides de plateforme |
| Amorçage de la base de données | Définit le job du premier déploiement (db-init) qui crée la base de données, l'utilisateur et les droits | Sortie initialization_jobs |
| Initialisation du schéma | Le point d'entrée exécute writefreely db init à chaque démarrage pour créer les tables | §Comportement de l'application dans les guides de plateforme |
| Stockage objet | Déclare un bucket de données Cloud Storage (writefreely-uploads) | Sortie storage_buckets |
| Paramètres principaux | Génère config.ini à partir des variables DB_* injectées ; définit l'adresse d'écoute, le port, l'hôte public et l'état des inscriptions | Comportement de l'application dans les guides de plateforme |
| Contrôles de santé | Fournit la sonde de démarrage TCP et la sonde de vivacité HTTP / par défaut | §Observabilité dans les guides de plateforme |
2. Clés cryptographiques dans Secret Manager
WriteFreely refuse de démarrer sans ses trois fichiers de clés AES-256 (32 octets bruts chacun, écrits dans keys/cookies_auth.aes256, keys/cookies_enc.aes256 et keys/email.aes256). Si l'on laissait l'application exécuter writefreely keys generate, elle produirait de nouvelles clés aléatoires à chaque démarrage du conteneur — ce qui invalide toutes les sessions au redémarrage et, pire encore, casse tout déploiement multi-instances (chaque instance signerait les cookies avec une clé différente, de sorte qu'un cookie émis par l'instance A serait rejeté par l'instance B, provoquant une boucle de connexion).
WriteFreely_Common génère donc les trois clés une seule fois au moment du plan (sous forme de ressources random_id avec byte_length = 32, encodées en base64), les stocke dans Secret Manager et les injecte comme variables d'environnement secrètes. Le point d'entrée décode chacune d'elles depuis le base64 dans le répertoire keys/ avant de démarrer le serveur :
WF_KEY_COOKIES_AUTH→keys/cookies_auth.aes256— authentifie (signe) les cookies de session.WF_KEY_COOKIES_ENC→keys/cookies_enc.aes256— chiffre le contenu des cookies de session.WF_KEY_EMAIL→keys/email.aes256— chiffre les adresses e-mail stockées.
Les trois secrets Secret Manager sont nommés :
secret-<resource-prefix>-writefreely-cookies-auth
secret-<resource-prefix>-writefreely-cookies-enc
secret-<resource-prefix>-writefreely-email-key
Ces clés ne doivent jamais faire l'objet d'une rotation après le premier déploiement — leur rotation déconnecte tous les utilisateurs et rend indéchiffrables les adresses e-mail chiffrées auparavant. Un sous-module cleanup_orphaned_secrets supprime les éventuels secrets obsolètes de même nom avant leur (re)création, et un time_sleep de 30 secondes protège contre les problèmes de cohérence lecture-après-écriture lorsque les valeurs sont consommées.
Récupérez les clés après le déploiement :
# List the WriteFreely key secrets (names include the resource prefix):
gcloud secrets list --project "$PROJECT" \
--filter="name~cookies-auth OR name~cookies-enc OR name~email-key"
# Read a secret version (base64 of the raw 32-byte key):
gcloud secrets versions access latest --secret=<secret-name> --project "$PROJECT"
Le mot de passe de la base de données est généré et géré séparément par le socle ; le nom de son secret est indiqué dans les sorties du déploiement de la plateforme (database_password_secret). Consultez App_Common pour le modèle partagé de secrets et de Workload Identity.
3. Image de conteneur et point d'entrée
L'image standard writeas/writefreely attend un fichier config.ini et des fichiers de clés pré-générés, et ne dispose d'aucun mécanisme pour obtenir les coordonnées de sa base de données depuis l'environnement. Comme Cloud Run et GKE ne peuvent pas monter un fichier de configuration fourni par l'hôte, WriteFreely_Common intègre un wrapper léger (Dockerfile + entrypoint.sh) au-dessus de l'image officielle et le construit avec Cloud Build (image_source = "custom").
Le Dockerfile dérive son tag de base d'un ARG de build propre à l'application, WRITEFREELY_VERSION (par défaut 0.12.0) — et non de l'APP_VERSION générique, que le socle injecte dans build_args et qui l'écraserait sinon avec latest. WriteFreely_Common convertit une application_version valant latest en tag épinglé reconnu fiable avant de définir l'ARG, ce qui garantit une résolution déterministe de l'image de base.
Le point d'entrée de génération de configuration (entrypoint.sh, un script Alpine /bin/sh) s'exécute avant le binaire WriteFreely et :
- Localise le binaire et la racine des ressources — résout le binaire
writefreelyet le répertoire de travail qui contient réellementtemplates/(WriteFreely résouttemplates/,static/,pages/,keys/etconfig.inirelativement au répertoire courant). - Génère
config.ini— écrit les sections[server],[database]et[app]à partir des variablesDB_HOST/DB_PORT/DB_NAME/DB_USER/DB_PASSWORDinjectées par le socle et des paramètresWF_*(WF_BIND,WF_PORT,WF_PUBLIC_URL,WF_SITE_NAME,WF_SITE_DESCRIPTION,WF_OPEN_REGISTRATION).[database] type = mysqlest fixé. - Installe les clés de chiffrement stables — décode depuis le base64 les variables d'environnement secrètes
WF_KEY_*danskeys/*.aes256; ne génère des clés éphémères qu'en leur absence. - Initialise le schéma — exécute
writefreely db init(en tolérant « tables already exist » afin que les redémarrages n'échouent pas). - Sert l'application —
exec writefreely serveen tant que PID 1, à l'écoute sur0.0.0.0:8080.
L'hôte public utilisé pour les liens générés provient de WF_PUBLIC_URL, avec repli sur CLOUDRUN_SERVICE_URL / GKE_SERVICE_URL injectés par le socle.
4. Moteur de base de données et amorçage
WriteFreely est provisionné sur Cloud SQL for MySQL 8.0 (database_type = MYSQL_8_0) ; les noms par défaut de la base de données et de l'utilisateur sont tous deux writefreely. Au premier déploiement, un job ponctuel (db-init) s'exécute avec mysql:8.0-debian et, de manière idempotente :
- Résout la connexion — privilégie le socket Unix du Cloud SQL Auth Proxy sous
/cloudsqllorsqu'il est monté, sinon se rabat sur TCP viaDB_IP(IP privée), - Attend que le port MySQL 3306 soit joignable,
- Crée (ou met à jour) l'utilisateur de l'application avec le mot de passe généré,
- Crée la base de données de l'application si elle n'existe pas,
- Accorde
ALL PRIVILEGESsur la base de données à l'utilisateur de l'application (ce qui permet au proprewritefreely db initde l'application de créer les tables au démarrage), - Vérifie que l'utilisateur de l'application peut s'authentifier (ce qui alimente le cache serveur
caching_sha2_passwordde MySQL 8), puis arrête proprement le sidecar Cloud SQL Proxy viaquitquitquit.
Le job peut être réexécuté sans risque (CREATE ... IF NOT EXISTS, max_retries = 3). Le schéma des tables lui-même est créé par le point d'entrée de l'application (writefreely db init), et non par ce job. Inspectez directement la base de données avec :
gcloud sql connect <instance-name> --user=<db-user> --database=<db-name> --project "$PROJECT"
Les noms de l'instance, de la base de données et de l'utilisateur figurent dans les sorties du déploiement de la plateforme.
5. Paramètres principaux de l'application
WriteFreely_Common établit l'environnement WriteFreely de base afin que l'application démarre correctement dès le premier lancement :
- Adresse d'écoute et port —
WF_BIND = "0.0.0.0",WF_PORT = "8080";DB_PORT = "3306". - Hôte public —
WF_PUBLIC_URLest défini sur l'URL prévue du service lorsqu'elle est connue, et le point d'entrée se rabat à l'exécution surCLOUDRUN_SERVICE_URL/GKE_SERVICE_URLinjectés par le socle — ainsi, les liens de fédération et les redirections utilisent l'hôte réel. - Inscriptions —
open_registration = falsepar défaut (à remplacer avecWF_OPEN_REGISTRATION),single_user = false,max_blogs = 1,federation = false,public_stats = true. Aucun compte administrateur n'est créé automatiquement — consultez les étapes du premier lancement dans les guides de plateforme. - Métadonnées du site —
WF_SITE_NAME(par défautWriteFreely) etWF_SITE_DESCRIPTION(vide) peuvent être fournis viaenvironment_variables.
Ajustements propres à chaque plateforme, gérés par les wrappers de variante :
- Cloud Run se connecte à MySQL en TCP sur IP privée (
enable_cloudsql_volume = false) ; Cloud SQL MySQL accepte le TCP non chiffré sur IP privée, doncDB_HOSTest l'IP privée de l'instance. - GKE se connecte via le sidecar Cloud SQL Auth Proxy et remplace
DB_HOST = 127.0.0.1(enable_cloudsql_volume = true).
Remarque — reliquats du gabarit WordPress. WriteFreely est une application Go et n'utilise ni PHP ni Redis. Les variables
php_memory_limit,upload_max_filesize,post_max_size,enable_redis,redis_hostetredis_portsont héritées du gabarit du module et ne sont pas utilisées par WriteFreely ; leurs valeurs par défaut sont inertes pour cette application.
6. Comportement des sondes de santé
WriteFreely sert sa page d'accueil sur / et y renvoie un 200 dès que le serveur est démarré et connecté à MySQL — il n'existe pas de point de terminaison /health dédié. Les valeurs par défaut en tiennent compte :
- Sonde de démarrage — TCP sur le port du conteneur (
type = "TCP", délai initial de 30 secondes, période de 15 secondes, seuil de 20 échecs ≈ 5 minutes) — la charge de travail devient Ready dès qu'elle écoute sur le port 8080, indépendamment de la latence de la base de données au premier démarrage. - Sonde de vivacité — HTTP
GET /(délai initial de 300 secondes, période de 60 secondes, seuil de 3 échecs) — redémarre le conteneur si la page d'accueil cesse de répondre.
7. Stockage d'objets
Un bucket de données Cloud Storage dédié (suffixe de nom writefreely-uploads) est déclaré ici et provisionné par le socle, qui accorde également l'accès au compte de service de la charge de travail. Listez-le avec :
gcloud storage buckets list --project "$PROJECT"
Pour la configuration propre à WriteFreely destinée aux utilisateurs (variables par groupe, sorties et exploration de chaque service depuis la console et la CLI), consultez les guides de plateforme : WriteFreely_GKE et WriteFreely_CloudRun.
Guides associés
- WriteFreely sur Google Cloud Run — cette configuration déployée sur Cloud Run.
- WriteFreely sur GKE Autopilot — cette configuration déployée sur GKE.
Need RAD to do something it does not do yet? Request it on the roadmap, or vote on what is already there.