Article principal : Plateforme de développeur interne avec Backstage : architecture pour startup
Ce tutoriel s’inscrit dans la série Platform Engineering et Backstage. Pour la vue d’ensemble du sujet, lire d’abord le guide principal.
Pourquoi TechDocs résout enfin le problème de la documentation morte
Toute organisation tech a son cimetière de documentation. Confluence devenu illisible, wiki interne abandonné, fichiers Word qui décrivent une architecture refaite il y a deux ans. Le problème n’est pas le manque d’outils — il en existe pléthore — c’est la distance entre la documentation et le code. Quand la doc vit dans un système séparé, elle pourrit dès le premier sprint où les développeurs sont sous pression. TechDocs propose une approche radicale : la documentation d’un service vit dans le dépôt du service, écrite en Markdown, revue dans les pull requests, compilée et servie automatiquement par Backstage. Cette colocation est ce qui fait la différence entre une doc à jour et un musée poussiéreux.
Ce tutoriel construit un pipeline TechDocs complet pour une startup. À la fin, vous aurez TechDocs activé sur Backstage, MkDocs configuré dans un service exemple, un job GitHub Actions qui compile la documentation à chaque merge sur main et la pousse dans un bucket S3, et le portail qui sert la doc rendue à partir du bucket. Vous saurez aussi écrire un mkdocs.yml propre et utiliser les extensions courantes — diagrammes Mermaid, mise en évidence syntaxique, tables des matières automatiques. Le tutoriel suppose une instance Backstage v1.50.0 fonctionnelle et un compte AWS pour le bucket S3.
Étape 1 — Comprendre les trois choix d’architecture
Avant la moindre commande, il faut comprendre les trois variables qui définissent une mise en place TechDocs. La documentation officielle les détaille mais on peut les résumer simplement.
Le builder répond à la question qui compile la documentation ?. La valeur local signifie que Backstage compile à la volée quand un utilisateur ouvre une page de doc. C’est pratique pour démarrer mais ça met de la charge sur le backend et ralentit la première visite. La valeur external signifie que la compilation se fait ailleurs — typiquement dans un job CI à chaque merge — et que Backstage se contente de servir un artefact pré-compilé. C’est la configuration recommandée pour la production.
Le generator répond à comment compile-t-on ?. La valeur docker est le défaut et lance MkDocs dans un container officiel qui contient toutes les extensions Backstage. La valeur local exécute directement mkdocs build sur la machine, ce qui suppose que MkDocs et les bons plugins sont installés. docker est plus simple à mettre en place ; local est plus rapide en CI où on peut installer les dépendances Python une fois pour toutes.
Le publisher répond à où stocke-t-on les artefacts ?. Les valeurs supportées officiellement sont local (système de fichiers du backend Backstage), awsS3, googleGcs, azureBlobStorage. La pratique recommandée pour la production est awsS3 ou googleGcs, qui découple le stockage de la documentation du conteneur Backstage et permet de le scaler indépendamment.
Étape 2 — Activer TechDocs en mode local pour valider
On commence toujours par le mode builder: local + publisher: local pour valider que TechDocs fonctionne avant d’externaliser. La configuration tient en quelques lignes dans app-config.yaml. Sur un Backstage généré par npx @backstage/create-app@latest, le plugin TechDocs est déjà installé — il suffit de l’activer correctement et de pointer la configuration.
techdocs:
builder: 'local'
generator:
runIn: 'docker'
publisher:
type: 'local'
Avec cette configuration, Backstage compile la doc à la volée en lançant un container MkDocs à la première visite, et stocke le résultat dans tmpdir du backend. Pour qu’une entité Component voie sa documentation rendue, on ajoute l’annotation backstage.io/techdocs-ref: dir:. dans son catalog-info.yaml, ce qui indique à Backstage que la doc se trouve dans le dossier courant du repo. La valeur dir:. est la plus courante. On peut aussi pointer un sous-dossier comme dir:./docs-source ou un autre repo entier avec url:https://github.com/....
Étape 3 — Préparer un service avec MkDocs
Côté repository de service, MkDocs s’attend à trouver à la racine un fichier mkdocs.yml et un dossier docs/ contenant les fichiers Markdown. La structure minimale fonctionnelle ressemble à ceci. On crée les fichiers dans le repo du service exemple — celui qu’on a généré au tutoriel Scaffolder ou n’importe lequel.
mkdir -p docs
cat > docs/index.md <<'EOF'
# Order API
Service de gestion des commandes.
## Architecture
Le service expose une API REST construite avec Fastify et persiste
ses donnees dans PostgreSQL.
## Endpoints principaux
- POST /orders : creation d'une commande
- GET /orders/:id : consultation
- POST /orders/:id/cancel : annulation
EOF
cat > mkdocs.yml <<'EOF'
site_name: Order API
nav:
- Accueil: index.md
- Architecture: architecture.md
- Operations: operations.md
plugins:
- techdocs-core
EOF
Le plugin techdocs-core est crucial : c’est lui qui apporte le thème Backstage, le rendu Mermaid, le support des admonitions et plusieurs autres extensions standard. Sans lui, la doc compile mais affiche un look MkDocs générique qui dépare avec le portail. Le fichier docs/index.md est le point d’entrée par défaut. La section nav est facultative mais explicite — sans elle, MkDocs construit la table des matières à partir de l’ordre alphabétique des fichiers, ce qui est rarement ce qu’on veut.
On ajoute aussi l’annotation dans le catalog-info.yaml du service. Sans cette annotation, la fiche du service dans Backstage n’affiche pas l’onglet Docs. Au prochain refresh du catalogue, l’onglet Docs apparaît, et un clic dessus déclenche la première compilation. Patience la première fois — le pull du container MkDocs et la compilation prennent une à deux minutes.
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: order-api
annotations:
backstage.io/techdocs-ref: dir:.
spec:
type: service
lifecycle: experimental
owner: platform-team
Si la compilation échoue avec un message de plugin manquant, c’est que techdocs-core n’est pas dans la liste des plugins du mkdocs.yml. Si elle échoue avec une erreur Docker, c’est que Docker n’est pas démarré sur la machine qui héberge Backstage — vérifier avec docker ps.
Étape 4 — Enrichir le mkdocs.yml avec les extensions utiles
Le mkdocs.yml de production gagne à activer plusieurs extensions Markdown qui transforment l’expérience de lecture. Les principales sont les admonitions (encadrés Note, Warning, Danger), le détail-summary collapsible, la mise en évidence syntaxique du code, l’onglet de copie de code, les tables des matières latérales et le rendu Mermaid pour les diagrammes.
site_name: Order API
nav:
- Accueil: index.md
- Architecture: architecture.md
- Operations: operations.md
- Reference API: api.md
plugins:
- techdocs-core
markdown_extensions:
- admonition
- pymdownx.details
- pymdownx.superfences:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:pymdownx.superfences.fence_code_format
- pymdownx.highlight:
anchor_linenums: true
- pymdownx.inlinehilite
- pymdownx.snippets
- pymdownx.tabbed:
alternate_style: true
- toc:
permalink: true
Cette configuration est la combinaison la plus utilisée pour la doc technique. admonition permet d’écrire !!! warning pour produire un encadré rouge. pymdownx.superfences avec le custom_fence Mermaid permet d’écrire des diagrammes en code à l’intérieur du Markdown. pymdownx.tabbed autorise les blocs onglets pratiques pour les exemples multi-langues. Le toc avec permalink: true ajoute une icône de lien à côté de chaque titre, utile pour partager une URL ancrée précise.
Étape 5 — Bascule sur le builder externe avec GitHub Actions
Le mode local atteint vite ses limites. Dès qu’on a plus de cinq services documentés, la compilation à la volée fait sentir sa latence et stresse le backend. La bonne pratique est de pré-compiler en CI et de pousser l’artefact dans un bucket. On bascule donc builder: external et on ajoute un workflow GitHub Actions dans chaque repo de service.
# app-config.yaml de Backstage
techdocs:
builder: 'external'
publisher:
type: 'awsS3'
awsS3:
bucketName: 'mon-org-techdocs'
region: 'eu-west-1'
credentials:
accessKeyId: ${TECHDOCS_AWS_ACCESS_KEY_ID}
secretAccessKey: ${TECHDOCS_AWS_SECRET_ACCESS_KEY}
Backstage en mode external ne compile plus. Il télécharge depuis le bucket S3 le contenu pré-compilé et le sert. Si l’artefact n’existe pas dans le bucket, l’utilisateur voit un message Documentation has not been generated yet — c’est attendu et le workflow CI doit alimenter le bucket. Côté repo de service, le workflow ressemble à ce qui suit. On lui donne les credentials AWS via les secrets GitHub.
# .github/workflows/techdocs.yml
name: Publish TechDocs
on:
push:
branches: [main]
paths:
- 'docs/**'
- 'mkdocs.yml'
- '.github/workflows/techdocs.yml'
jobs:
publish-techdocs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- uses: actions/setup-python@v5
with:
python-version: 3.12
- name: Install techdocs-cli and mkdocs-techdocs-core
run: |
npm install -g @techdocs/cli
pip install "mkdocs-techdocs-core==1.*"
- name: Generate docs
run: techdocs-cli generate --no-docker --verbose
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: eu-west-1
- name: Publish to S3
run: |
techdocs-cli publish \
--publisher-type awsS3 \
--storage-name mon-org-techdocs \
--entity default/Component/order-api
Ce workflow se déclenche à chaque push sur main qui touche les fichiers de doc, le mkdocs.yml ou le workflow lui-même. Il installe Node 22 et Python 3.12, installe le CLI @techdocs/cli et le paquet mkdocs-techdocs-core dans sa branche 1.x (la convention 1.* reprise de la doc officielle prend le dernier patch publié — la branche 1.6.x au moment de la rédaction), génère la doc, puis la pousse dans le bucket S3 avec une référence d’entité au format namespace/Kind/name. La référence doit correspondre exactement à ce qui est dans le catalogue, sinon Backstage ne retrouve pas l’artefact.
Étape 6 — Provisionner le bucket S3 avec les bonnes permissions
Avant que le workflow CI ne tourne, le bucket doit exister et l’utilisateur IAM utilisé par GitHub Actions doit avoir les droits de lecture-écriture dessus. La création se fait soit dans la console AWS, soit via l’AWS CLI. La nomenclature recommandée est {org}-techdocs, par exemple mon-org-techdocs. Pas besoin d’activer Static Website Hosting — Backstage interroge le bucket via l’API S3 standard, pas via HTTP public.
aws s3api create-bucket \
--bucket mon-org-techdocs \
--region eu-west-1 \
--create-bucket-configuration LocationConstraint=eu-west-1
# Bloquer l'acces public (recommande)
aws s3api put-public-access-block \
--bucket mon-org-techdocs \
--public-access-block-configuration \
BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true
La configuration BlockPublicAcls=true garantit que les artefacts ne fuiteront pas par accident — Backstage se débrouille avec des credentials IAM, pas besoin d’exposer le bucket publiquement. La policy IAM minimale pour l’utilisateur Backstage et l’utilisateur GitHub Actions ressemble à ceci, avec les permissions GetObject, PutObject et ListBucket.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:ListBucket"],
"Resource": "arn:aws:s3:::mon-org-techdocs"
},
{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
"Resource": "arn:aws:s3:::mon-org-techdocs/*"
}
]
}
Cette policy est attachée à un utilisateur IAM dédié à TechDocs. On crée deux utilisateurs distincts si on veut séparer les credentials de Backstage (lecture) de ceux de la CI (écriture), avec deux policies plus restrictives chacune. Pour une startup en démarrage, un seul utilisateur avec lecture-écriture suffit largement.
Étape 7 — Vérifier le pipeline de bout en bout
Toutes les pièces sont en place. On valide en exécutant un cycle complet. On modifie un fichier dans docs/ du repo de service, on commit et on pousse sur main. Le workflow GitHub Actions se déclenche, compile, et pousse l’artefact dans le bucket S3. On voit dans le log du workflow l’étape Publish to S3 qui se termine avec succès. On retourne dans Backstage, on ouvre la fiche du service, on clique sur l’onglet Docs.
aws s3 ls s3://mon-org-techdocs/default/component/order-api/ --recursive | head -20
La commande liste les fichiers générés dans le bucket. On doit voir typiquement une vingtaine de fichiers : un index.html à la racine, des sous-pages architecture/index.html, des assets CSS et JS, le sitemap XML, le fichier 404.html. Si le listage est vide, c’est que le workflow CI n’a pas écrit dans le bucket — vérifier les credentials et les permissions IAM dans les logs GitHub Actions. Si le listage est plein mais Backstage affiche encore not generated yet, c’est que la référence d’entité ne correspond pas au format attendu — le path dans le bucket suit la convention {namespace}/{kind}/{name} en lowercase.
Étape 8 — Étendre TechDocs aux autres services en industrialisant
Maintenant que la pipeline fonctionne sur un service, l’objectif est de la rendre disponible sur tous les services sans répéter le travail. La méthode propre passe par le scaffolder. On modifie le template de microservice (cf. tutoriel Scaffolder) pour inclure dans le squelette généré le fichier mkdocs.yml, le dossier docs/ avec un index.md de démarrage, et le workflow .github/workflows/techdocs.yml pré-configuré.
Tout nouveau service créé via le golden path part désormais avec sa documentation prête à recevoir du contenu. Le développeur n’a qu’à éditer les fichiers Markdown, et la pipeline CI fait le reste. Pour les services existants, on prépare un script qui ouvre une pull request sur chaque repo concerné avec ces fichiers ajoutés — le scaffolder lui-même peut servir cette opération via une action publish:github:pull-request.
L’étape suivante, plus mature, est de faire écrire un peu de doc à chaque service par injonction douce : ajouter une vérification dans la pipeline CI qui échoue (ou avertit) si la doc d’un service n’a pas été modifiée depuis plus de six mois. Cette pression sociale légère, combinée à la facilité d’écriture, suffit à maintenir une documentation vivante sur la plupart des services critiques.
Erreurs fréquentes
| Erreur | Cause | Solution |
|---|---|---|
| Documentation has not been generated yet | Artefact absent du bucket | Lancer manuellement techdocs-cli publish ou attendre la CI |
| 404 sur les pages internes | Mauvais chemin de référence d’entité | Utiliser {namespace}/{kind}/{name} en lowercase |
| MkDocs build fails: plugin techdocs-core not found | Plugin Python non installé | pip install mkdocs-techdocs-core |
| S3 AccessDenied | Policy IAM incomplète | Ajouter s3:ListBucket sur l’arn du bucket sans /* |
| Mermaid diagram pas rendu | Extension pymdownx.superfences manquante | Ajouter le custom_fence Mermaid au mkdocs.yml |
| L’onglet Docs n’apparaît pas | Annotation techdocs-ref manquante | Ajouter backstage.io/techdocs-ref: dir:. |
| Build CI très lent (> 5 min) | Pip non caché | Activer cache: pip dans setup-python |
Tutoriels associés
- Installer Backstage en local avec Node 22 et Yarn 4 : tutoriel pas à pas
- Software Catalog Backstage : référencer ses services avec catalog-info.yaml
- Scaffolder Backstage : créer un template de microservice Node.js
Pour aller plus loin
Retour au guide principal : Plateforme de développeur interne avec Backstage : architecture pour startup.
- Backstage — TechDocs Overview (présentation générale)
- Backstage — TechDocs Getting Started (configuration)
- Backstage — TechDocs Configuration (référence app-config)
- Backstage — TechDocs CI/CD (workflows externes)
- MkDocs (générateur de documentation statique)
- mkdocs-techdocs-core (paquet Python officiel)
FAQ
Faut-il vraiment un bucket S3 ou Google Cloud Storage est-il équivalent ?
Les deux fonctionnent identiquement bien. Le choix dépend du fournisseur cloud principal de l’organisation. La configuration côté Backstage est juste un autre publisher.type, et le CLI TechDocs supporte les deux. Azure Blob Storage est aussi une option valide pour les organisations Microsoft.
Combien coûte le stockage TechDocs sur S3 ?
Un service typique avec une dizaine de pages compile en environ deux à cinq mégaoctets. Une organisation avec deux cents services consomme moins d’un gigaoctet, ce qui facture quelques cents par mois sur S3 Standard. Le coût principal vient des requêtes GetObject quand des utilisateurs consultent la doc, mais reste négligeable à l’échelle d’une startup.
Peut-on versionner la doc par environnement (dev / staging / prod) ?
Pas nativement. La doc dans TechDocs est associée à une entité du catalogue, et chaque entité n’a qu’une version de doc. Le pattern recommandé est de garder la doc unique et de marquer dans le contenu les comportements spécifiques par environnement. Pour les besoins plus pointus, on duplique l’entité Component avec un suffixe d’environnement, mais c’est rarement utile.
MkDocs supporte-t-il LaTeX et les équations mathématiques ?
Oui via l’extension pymdownx.arithmatex couplée à MathJax. La configuration est documentée dans Material for MkDocs et fonctionne aussi avec le plugin techdocs-core. Cas d’usage typique : services data avec formules statistiques ou financières.
Comment générer la doc d’une API à partir d’un fichier OpenAPI ?
Deux options. La première est d’utiliser l’extension mkdocs-render-swagger-plugin qui rend Swagger UI dans la doc. La seconde est de laisser Backstage gérer la spec OpenAPI via le kind API du catalogue (cf. tutoriel Software Catalog) et de pointer la doc vers la fiche API correspondante. La deuxième approche est généralement préférable parce qu’elle évite la duplication.
Peut-on lier les pages de doc entre services ?
Oui, via les liens Markdown classiques. La syntaxe à utiliser est [texte](/docs/default/component/autre-service/). Backstage résout cette URL relative correctement à condition d’utiliser le namespace, le kind et le nom corrects. Pour des liens vers des entités API ou Resource, remplacer component par api ou resource.
L’extension Mermaid est-elle vraiment nécessaire ?
Pour de la doc technique, oui. Pouvoir écrire un diagramme de séquence ou un schéma d’architecture en quelques lignes de Markdown plutôt qu’avec un outil graphique change profondément la pratique de documentation. Les diagrammes deviennent versionnables, diff-ables, modifiables par n’importe qui dans l’équipe — bénéfices équivalents à ceux du docs-as-code en général.