[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fxRXdqyhuhh4S_85Orlm9fxXLKi49rjhTGgDELOID024":3,"$frHveB76jWtX09gW7wHwZJtdGdcyoU4WhAKq9hlxe17g":21},{"id":4,"slug":5,"titleFr":6,"titleEn":7,"titleKm":8,"contentFr":9,"contentEn":10,"contentKm":8,"excerptFr":11,"excerptEn":12,"excerptKm":8,"tags":13,"createdAt":19,"updatedAt":20},119,"migration-gcp-vercel-scaleway","Comment j'ai migré 7 applis vers Scaleway sans perdre une donnée","How I migrated 7 apps to Scaleway without losing a byte",null,"## De GCP/Vercel à Scaleway, sans perdre une donnée\n\nDans [l'article précédent](/blog/pourquoi-scaleway-souverainete), j'expliquais *pourquoi* j'ai rapatrié tout mon perso chez un hébergeur français. Ici, place au *comment* — le récit technique d'une migration de sept applications, plus un backoffice, réalisée par-dessus le weekend.\n\n## Le point de départ\n\nSur GCP et Vercel, j'avais accumulé :\n\n- **7 applis** : ce portfolio (Nuxt), un tracker de pompes, un traducteur khmer, une appli de fiançailles, l'espace de souvenirs de couple « Lys », une API Rust, et des jeux.\n- **Neon** pour les bases PostgreSQL.\n- **Google Cloud Storage** pour les fichiers (photos, coffre du couple : ~5 Go).\n- Une facture compute qui tournait autour de **30 €/mois** — pas énorme, mais du gaspillage pour des services qui dorment 95 % du temps.\n\n## La règle numéro un : zéro perte de données\n\nAvant de toucher à quoi que ce soit, un principe non négociable : **on ne supprime rien tant que tout n'est pas vérifié.** Les buckets GCS ont été *copiés* (jamais déplacés) vers le stockage objet Scaleway avec `rclone`, puis validés par checksum, octet par octet. GCS est resté intact comme sauvegarde jusqu'à la toute fin. Les souvenirs d'un couple ne se « migrent » pas à la légère.\n\n## Le cœur technique : un adaptateur GCS → S3\n\nLe plus élégant du chantier : Scaleway Object Storage parle le protocole **S3**, standard de fait. Plutôt que de réécrire chaque appli, j'ai écrit un petit **adaptateur** qui imite l'API de Google Cloud Storage (`file().save()`, `.download()`, `getFiles()`…) mais tape sur S3 en dessous, via le SDK AWS. Résultat : le code métier des applis n'a quasiment pas bougé, seule la couche stockage a été échangée.\n\n```js\nconst s3 = new S3Client({\n  region: 'fr-par',\n  endpoint: 'https://s3.fr-par.scw.cloud',\n  forcePathStyle: true,\n  credentials: { accessKeyId, secretAccessKey },\n})\n```\n\n## Serverless Containers + scale-to-zero\n\nChaque appli a été containerisée (Docker), poussée sur le registry Scaleway, et déployée en *Serverless Container* configuré en **min-scale = 0** : quand personne ne s'en sert, zéro conteneur tourne, zéro euro dépensé. Au premier accès, ça démarre à froid en une poignée de secondes. Pour un usage perso, le compromis est idéal.\n\nTout est regroupé sous des sous-domaines de `chetana.fr`, avec certificats TLS Let's Encrypt provisionnés automatiquement — un simple enregistrement DNS + une commande, et le HTTPS est là.\n\n## Les pièges rencontrés (pour ceux qui suivront)\n\n- **Repointer les URLs internes.** En supprimant mon ancienne API, j'ai cassé sans le voir le backend du portfolio (blog, expériences, compétences disparus). Leçon : tracer *toutes* les dépendances entre services avant de couper quoi que ce soit.\n- **La variable `PORT` est réservée** sur les conteneurs Scaleway (elle est injectée automatiquement) — impossible de la définir soi-même.\n- **`container update` remplace toute la map d'environnement** : changer une variable oblige à toutes les repasser, sous peine de perdre les secrets.\n- **CORS et redirections** : les anciennes URLs `*.chetana.dev` renvoient désormais un 301/308 vers `chetana.fr`, pour ne casser aucun lien partagé.\n\n## Le résultat\n\nSept applis + ce backoffice (celui-là même avec lequel j'écris cet article ✍️), toutes en France, sous un seul domaine, avec une facture compte qui tend vers zéro au repos. La base de données (Neon) suivra bientôt vers Scaleway Serverless SQL pour co-localiser data et calcul.\n\nMigration bouclée. Et accessoirement, ce texte est le tout premier article publié depuis le nouveau backoffice, sur la nouvelle infra. Méta, non ? 🇫🇷","## From GCP/Vercel to Scaleway, without losing a byte\n\nIn [the previous article](/blog/pourquoi-scaleway-souverainete) I explained *why* I brought all my personal stuff home to a French host. Here comes the *how* — the technical story of migrating seven apps, plus a backoffice, over a weekend.\n\n## The starting point\n\nOn GCP and Vercel I had accumulated:\n\n- **7 apps**: this portfolio (Nuxt), a push-up tracker, a Khmer translator, an engagement app, our couple's memory space \"Lys\", a Rust API, and some games.\n- **Neon** for the PostgreSQL databases.\n- **Google Cloud Storage** for files (photos, our couple's vault: ~5 GB).\n- A compute bill hovering around **€30/month** — not huge, but wasteful for services that sleep 95% of the time.\n\n## Rule number one: zero data loss\n\nBefore touching anything, one non-negotiable principle: **delete nothing until everything is verified.** The GCS buckets were *copied* (never moved) to Scaleway Object Storage with `rclone`, then validated by checksum, byte by byte. GCS stayed intact as a backup until the very end. You don't \"migrate\" a couple's memories lightly.\n\n## The technical heart: a GCS → S3 adapter\n\nThe most elegant part: Scaleway Object Storage speaks the **S3** protocol, the de-facto standard. Rather than rewrite every app, I wrote a small **adapter** that mimics the Google Cloud Storage API (`file().save()`, `.download()`, `getFiles()`…) but hits S3 underneath, via the AWS SDK. The result: the apps' business code barely moved — only the storage layer was swapped.\n\n```js\nconst s3 = new S3Client({\n  region: 'fr-par',\n  endpoint: 'https://s3.fr-par.scw.cloud',\n  forcePathStyle: true,\n  credentials: { accessKeyId, secretAccessKey },\n})\n```\n\n## Serverless Containers + scale-to-zero\n\nEach app was containerized (Docker), pushed to the Scaleway registry, and deployed as a *Serverless Container* set to **min-scale = 0**: when no one uses it, zero containers run, zero euros spent. On first hit, it cold-starts in a few seconds. For personal use, the trade-off is ideal.\n\nEverything sits under `chetana.fr` subdomains, with Let's Encrypt TLS certificates provisioned automatically — one DNS record plus one command, and HTTPS is live.\n\n## Pitfalls hit along the way (for those who'll follow)\n\n- **Repoint internal URLs.** Deleting my old API silently broke the portfolio's backend (blog, experiences, skills all vanished). Lesson: map *all* dependencies between services before cutting anything.\n- **The `PORT` variable is reserved** on Scaleway containers (it's injected automatically) — you can't set it yourself.\n- **`container update` replaces the whole environment map**: changing one variable forces you to re-pass them all, or you lose your secrets.\n- **CORS and redirects**: old `*.chetana.dev` URLs now return a 301/308 to `chetana.fr`, so no shared link breaks.\n\n## The result\n\nSeven apps + this backoffice (the very one I'm writing this article from ✍️), all in France, under a single domain, with a compute bill trending to zero at rest. The database (Neon) will soon follow to Scaleway Serverless SQL to co-locate data and compute.\n\nMigration done. And incidentally, this text is the very first article published from the new backoffice, on the new infrastructure. Meta, isn't it? 🇫🇷","Le récit technique : GCP/Vercel/Neon → Scaleway, adaptateur GCS→S3, scale-to-zero, TLS auto, et les pièges rencontrés en chemin.","The technical story: GCP/Vercel/Neon → Scaleway, a GCS→S3 adapter, scale-to-zero, auto TLS, and the pitfalls hit along the way.",[14,15,16,17,18],"scaleway","migration","devops","s3","docker","2026-05-11T10:00:00","2026-07-06T16:40:30.687196",[]]