Aller au contenu principal
pipelinebrut.fr — CI/CD · automatisation · terrain
Transfer

Automatiser les transferts SFTP dans un pipeline CI

Par Julien Mercier

Automatiser les transferts SFTP dans un pipeline CI

Dans beaucoup d’équipes, le transfert de fichiers reste un angle mort du pipeline. Le code est versionné, les builds sont reproductibles, les déploiements sont tracés, mais dès qu’il faut pousser un export, un lot d’assets, un fichier de configuration ou un paquet applicatif vers un serveur distant, on retombe souvent sur un script artisanal, une clé SSH copiée à la main ou une étape exécutée hors pipeline. C’est précisément là que les incidents apparaissent : fichiers incomplets, droits mal appliqués, erreurs silencieuses, doublons, ou transfert lancé trop tôt alors que le build n’est pas terminé.

Le protocole SFTP, basé sur SSH, reste une option très utilisée pour ces échanges entre environnements. On le retrouve chez des hébergeurs mutualisés, dans des DMZ, sur des serveurs d’intégration historiques, chez des partenaires externes, ou dans des workflows B2B où il faut déposer et récupérer des fichiers à heure fixe. L’objectif n’est donc pas de remplacer SFTP à tout prix, mais de l’intégrer proprement dans une chaîne CI afin de fiabiliser l’envoi, sécuriser les accès et éviter qu’un transfert casse la build ou le déploiement.

Dans cet article, on voit comment structurer un transfert SFTP dans un pipeline CI avec des outils réellement utilisés comme OpenSSH, sftp, scp, rsync via SSH, GitLab CI/CD, GitHub Actions ou Jenkins, et quelles pratiques permettent d’obtenir un flux robuste en PME comme en scale-up.

Pourquoi SFTP pose souvent problème dans un pipeline CI

Sur le papier, transférer un fichier via SFTP semble simple : une clé SSH, un hôte distant, un répertoire cible. En pratique, un pipeline CI introduit plusieurs contraintes supplémentaires :

  • l’exécution est non interactive : aucune saisie manuelle de mot de passe ou de confirmation d’empreinte n’est possible ;
  • les runners sont éphémères : ils ne conservent pas forcément l’état d’une exécution à l’autre ;
  • le transfert dépend du build : il ne doit démarrer que si les artefacts sont valides ;
  • les erreurs réseau sont réelles : coupures, timeouts, latence, DNS défaillant, saturation d’un serveur distant ;
  • la sécurité est plus exigeante : une clé privée mal gérée dans la CI devient un point d’entrée critique.

Le problème n’est donc pas le protocole lui-même, mais le fait qu’il soit souvent ajouté en fin de chaîne comme une simple commande shell. Une commande isolée peut fonctionner 99 fois, puis échouer à la centième sans mécanisme de reprise, sans journal exploitable et sans séparation claire entre l’étape de build, l’étape de vérification et l’étape de livraison.

Les cas d’usage les plus fréquents

Automatiser un transfert SFTP dans une CI n’est pas réservé aux grosses architectures. On le rencontre dans des situations très concrètes :

  • envoi d’un package ZIP ou TAR.GZ vers un serveur d’intégration ou de recette ;
  • dépôt d’exports CSV, XML ou JSON vers un partenaire métier ;
  • publication de fichiers statiques vers un serveur web qui n’expose pas d’API de déploiement ;
  • distribution d’artefacts vers une machine intermédiaire dans un réseau privé ;
  • synchronisation de médias, templates, certificats ou fichiers de configuration entre environnements.

Dans une PME, il est fréquent qu’un ERP, un outil comptable ou une plateforme e-commerce attende un fichier sur un répertoire SFTP précis. Dans une scale-up, le besoin peut concerner des flux plus volumineux, avec plusieurs environnements, des partenaires externes et des exigences de traçabilité plus fortes.

Choisir le bon outil pour le bon type de transfert

Le terme SFTP est souvent utilisé comme synonyme de “transfert de fichiers par SSH”, mais plusieurs outils répondent à des besoins différents.

sftp : le choix le plus direct

La commande sftp, fournie avec OpenSSH sur de nombreux systèmes, est adaptée quand il faut déposer ou récupérer quelques fichiers dans un flux simple. Elle permet d’exécuter des commandes batch non interactives, ce qui la rend compatible avec un job CI.

Exemple typique : envoyer un artefact généré par la build vers un répertoire distant après validation.

scp : simple, mais limité

scp reste pratique pour copier rapidement un fichier ou un dossier. En revanche, il offre moins de contrôle qu’un vrai flux SFTP batch, et il est moins adapté dès qu’il faut gérer des répertoires, des vérifications ou des reprises propres. Pour un pipeline critique, il vaut mieux éviter d’en faire l’unique brique si le besoin dépasse une simple copie ponctuelle.

rsync via SSH : souvent le meilleur compromis

Quand il faut synchroniser des répertoires, éviter de retransférer des fichiers inchangés ou préserver une certaine efficacité sur des volumes plus importants, rsync via SSH est souvent plus robuste. Ce n’est pas du SFTP à proprement parler, mais dans beaucoup d’environnements, c’est la meilleure réponse opérationnelle à un besoin de transfert sécurisé dans un pipeline.

Son avantage est concret : il peut comparer source et destination, transférer uniquement les différences et fournir des logs détaillés. Si votre contrainte métier impose strictement SFTP, il faut rester sur sftp. Si la contrainte est simplement “transfert sécurisé sur SSH”, rsync mérite d’être considéré.

Le principe clé : séparer build, artefact et transfert

L’erreur classique consiste à compiler puis transférer immédiatement dans le même script, sans matérialiser l’artefact. Une approche plus fiable consiste à découper le pipeline en trois étapes distinctes :

  • build : compilation ou génération des fichiers ;
  • packaging : création d’un artefact versionné, identifiable et archivé par la CI ;
  • transfer : envoi de cet artefact vers la cible distante.

Cette séparation change tout. Si le transfert échoue, la build n’est pas à refaire. Si le serveur SFTP distant est temporairement indisponible, l’artefact reste disponible dans la CI et peut être renvoyé. Et si un audit est nécessaire, on sait exactement quel fichier a été produit et expédié.

Dans GitLab CI/CD, cela passe naturellement par les artifacts entre jobs. Dans GitHub Actions, on peut utiliser upload-artifact et download-artifact. Dans Jenkins, on retrouve la même logique via l’archivage d’artefacts et des stages séparés.

Sécuriser l’authentification sans fragiliser la CI

Le point le plus sensible reste la gestion des identifiants. En CI, la bonne pratique est d’utiliser une clé SSH dédiée au pipeline, avec des droits limités au strict nécessaire. Évitez les comptes mutualisés et les clés personnelles de développeurs.

Utiliser des variables secrètes

GitLab CI/CD, GitHub Actions, Jenkins et la plupart des plateformes permettent de stocker des secrets chiffrés. La clé privée SSH, le nom d’hôte, le port éventuel et le chemin cible doivent être injectés au runtime via ces mécanismes, pas stockés dans le dépôt.

Vérifier l’empreinte du serveur

Beaucoup de scripts désactivent la vérification de l’hôte avec des options du type StrictHostKeyChecking=no. C’est pratique, mais risqué. En production, mieux vaut enregistrer l’empreinte du serveur dans un fichier known_hosts géré par la CI. Cela évite les confirmations interactives tout en protégeant contre une connexion au mauvais serveur.

Limiter les permissions côté serveur

Si le compte SFTP ne doit écrire que dans un répertoire précis, il faut le configurer en conséquence côté serveur. Dans certains contextes, un compte chrooté ou restreint à un dossier de dépôt réduit fortement le risque. Ce point dépend de l’administration SSH du serveur cible, mais il fait partie de la fiabilité globale du pipeline.

Exemple concret avec OpenSSH et un job CI

Un scénario réaliste consiste à construire un fichier release.tar.gz, à l’archiver comme artefact de pipeline, puis à le transférer en fin de chaîne vers un serveur distant via sftp en mode batch.

Le flux logique est le suivant :

  • le job de build produit release.tar.gz ;
  • la CI conserve cet artefact ;
  • le job de transfert récupère l’artefact, initialise l’agent SSH, charge la clé privée, ajoute le serveur dans known_hosts, puis exécute sftp -b avec un fichier de commandes.

L’intérêt du mode batch est qu’il rend le transfert déterministe. On peut y placer des commandes comme le changement de répertoire distant, l’envoi du fichier et éventuellement un renommage final.

Pourquoi le renommage final est une bonne pratique

Déposer directement un fichier sous son nom final peut poser problème si un processus distant le lit pendant l’écriture. Une technique simple consiste à :

  • envoyer le fichier sous un nom temporaire, par exemple release.tar.gz.part ;
  • vérifier que l’upload s’est bien terminé ;
  • renommer le fichier côté distant en release.tar.gz.

Ce schéma limite les lectures de fichiers incomplets. C’est particulièrement utile quand un partenaire ou un service aval surveille un répertoire et traite les nouveaux fichiers dès leur apparition.

Éviter qu’un transfert casse le reste du pipeline

La question n’est pas seulement “comment transférer”, mais “comment échouer proprement”. Tous les transferts n’ont pas le même statut dans une chaîne CI.

Différencier transfert bloquant et transfert non bloquant

Si le transfert est la livraison finale d’un artefact critique, son échec doit faire échouer le pipeline. En revanche, si l’envoi alimente un environnement secondaire, un miroir ou un partenaire non bloquant, il peut être pertinent de l’isoler dans un job distinct, avec une politique d’échec différente et une alerte dédiée.

GitLab CI/CD permet par exemple de jouer sur les stages, les dépendances et certains comportements d’échec. GitHub Actions permet aussi de séparer clairement les jobs de build et d’upload. L’idée est d’éviter qu’un incident SFTP ponctuel invalide toute la chaîne de qualité si ce transfert n’est pas essentiel à la release.

Ajouter des mécanismes de retry mesurés

Un timeout réseau ponctuel ne justifie pas toujours un échec définitif. Un petit nombre de tentatives supplémentaires peut suffire. Il faut toutefois rester mesuré : un retry infini masque les vrais incidents et allonge inutilement le temps de pipeline. En pratique, quelques tentatives espacées sont souvent suffisantes pour absorber les erreurs transitoires.

Journaliser clairement l’échec

Un transfert qui échoue avec un simple code retour sans contexte est difficile à diagnostiquer. Les logs doivent permettre de distinguer rapidement :

  • une erreur DNS ou réseau ;
  • un problème d’authentification SSH ;
  • un répertoire distant inexistant ;
  • un manque de droits en écriture ;
  • un artefact local absent ou mal nommé.

Dans la pratique, cela implique d’être explicite dans le script de job, de vérifier la présence des fichiers avant transfert et d’éviter les commandes trop compactes qui rendent les logs illisibles.

Contrôler l’intégrité et la complétude du transfert

Le succès apparent d’une commande ne garantit pas toujours que le fichier attendu est exploitable côté destination. Pour des flux sensibles, il faut aller plus loin que “la commande s’est terminée sans erreur”.

Vérifier la taille ou le checksum

Si le contexte le permet, comparer un checksum calculé avant et après transfert apporte une garantie forte. Les outils disponibles côté distant déterminent la méthode possible. Sur des environnements Linux, des commandes comme sha256sum sont courantes. Si vous n’avez accès qu’à SFTP sans shell distant, vous pouvez au minimum contrôler la taille du fichier ou mettre en place un fichier manifeste déposé avec l’artefact.

Déposer un fichier témoin

Dans certains échanges inter-applicatifs, on envoie le fichier principal puis un fichier de validation distinct, par exemple un petit fichier .done ou un manifeste. Le système aval ne traite les données qu’à la réception de ce témoin. Ce n’est pas propre à SFTP, mais c’est une pratique très répandue pour fiabiliser les traitements batch.

Exemple d’architecture simple en PME

Imaginons une PME qui génère chaque nuit un export CSV depuis son application, puis le dépose sur le serveur SFTP d’un prestataire logistique. Le pipeline peut être structuré ainsi :

  • job 1 : génération du CSV et contrôle de sa structure ;
  • job 2 : archivage du fichier comme artefact CI ;
  • job 3 : transfert SFTP vers un répertoire d’entrée distant avec nom temporaire ;
  • job 4 : renommage final ou dépôt d’un fichier témoin.

Si le serveur du prestataire est indisponible, le CSV reste disponible dans la CI. L’équipe peut relancer uniquement le job d’envoi. On évite ainsi de regénérer des données qui ont peut-être déjà changé entre-temps.

Exemple d’approche plus industrialisée en scale-up

Dans une structure plus grande, on retrouve souvent plusieurs cibles SFTP selon les environnements ou les partenaires. La bonne pratique consiste alors à standardiser le transfert via un composant commun :

  • un script unique ou une image de job réutilisable ;
  • des variables d’environnement pour l’hôte, le port, l’utilisateur et le chemin cible ;
  • une convention de nommage des artefacts ;
  • une politique homogène de logs, retries et vérifications.

Cette standardisation évite que chaque équipe réinvente son script SFTP avec ses propres options SSH, ses exceptions et ses angles morts. Elle facilite aussi les revues de sécurité.

GitLab CI, GitHub Actions, Jenkins : ce qui change vraiment

Les trois plateformes permettent d’automatiser un transfert SFTP, mais avec des nuances de mise en œuvre.

GitLab CI/CD

GitLab CI/CD est particulièrement adapté quand on veut enchaîner des stages clairs avec des artifacts et des variables protégées. Le transfert peut être réservé à certaines branches, à un tag de release ou à un environnement donné. La séparation build/package/deploy y est naturelle.

GitHub Actions

GitHub Actions fonctionne très bien pour ce type de besoin, surtout si le dépôt est déjà sur GitHub. Les secrets sont simples à gérer, et les artefacts peuvent transiter entre jobs. Il existe aussi des actions communautaires autour de SSH et du transfert de fichiers, mais il faut rester prudent et privilégier des composants maintenus et vérifiables. Quand la sécurité est sensible, s’appuyer directement sur OpenSSH dans un runner est souvent plus transparent.

Jenkins

Jenkins reste fréquent dans les SI où l’historique CI/CD est important. Il permet évidemment ce type d’automatisation, soit via pipeline scripté, soit via des plugins. Là encore, la prudence s’impose avec les plugins tiers : moins il y a de dépendances spécifiques, plus le comportement est lisible et portable.

Les erreurs fréquentes à éviter

  • mettre la clé privée dans le dépôt : c’est un risque de sécurité évident ;
  • désactiver toute vérification d’hôte : pratique à court terme, dangereux en production ;
  • transférer avant de figer l’artefact : on perd en traçabilité et en reproductibilité ;
  • écraser un fichier directement sous son nom final : cela expose à des lectures partielles ;
  • mélanger build, tests et transfert dans une seule commande : le diagnostic devient pénible ;
  • ne pas prévoir de reprise : le moindre incident réseau impose une relance complète ;
  • ne pas surveiller les logs : un transfert “réussi” peut masquer un mauvais répertoire cible ou une donnée non consommée.

Quand préférer autre chose que SFTP

SFTP est robuste et largement disponible, mais ce n’est pas toujours le meilleur choix. Si vous contrôlez les deux extrémités, une API HTTP sécurisée, un stockage objet compatible S3, un registre d’artefacts ou un mécanisme natif de déploiement peut offrir plus de traçabilité et de contrôle. Des outils comme Nexus Repository, JFrog Artifactory ou les registres d’artefacts intégrés aux plateformes CI/CD répondent souvent mieux à la distribution d’artefacts applicatifs.

En revanche, dès qu’il faut échanger avec un système tiers, un hébergement ancien ou un partenaire qui impose un dépôt de fichiers, SFTP reste un standard réaliste. L’enjeu n’est donc pas de le juger dépassé, mais de l’orchestrer proprement.

Une méthode pragmatique pour fiabiliser vos transferts

Si vous devez mettre en place un transfert SFTP dans un pipeline CI sans complexifier inutilement l’existant, une base saine tient en quelques principes :

  • produire un artefact unique et versionné avant tout envoi ;
  • utiliser une clé SSH dédiée, stockée comme secret ;
  • gérer explicitement known_hosts ;
  • transférer en mode batch avec logs lisibles ;
  • déposer d’abord sous un nom temporaire puis renommer ;
  • ajouter un contrôle de complétude adapté au contexte ;
  • séparer le job de transfert du reste du pipeline ;
  • prévoir une relance simple sans rebuilder.

Cette approche ne demande pas une refonte complète de la CI. Elle consiste surtout à traiter le transfert comme une étape de livraison à part entière, avec ses propres exigences de sécurité, d’observabilité et de reprise.

Conclusion

Automatiser les transferts SFTP dans un pipeline CI n’a rien d’un détail technique. C’est souvent le maillon qui relie un build propre à une exploitation réellement utilisable. Quand cette étape est improvisée, les problèmes apparaissent vite : artefacts introuvables, déploiements bloqués, fichiers incomplets ou erreurs silencieuses. À l’inverse, quand le transfert est conçu comme un job distinct, adossé à des artefacts, à une authentification SSH maîtrisée et à des contrôles simples, il devient fiable et relançable.

Pour une PME, cela permet déjà d’éviter beaucoup d’opérations manuelles et de réduire les incidents de livraison. Pour une scale-up, c’est une base indispensable pour standardiser les échanges entre équipes, environnements et partenaires. SFTP n’est pas le protocole le plus moderne dans tous les cas, mais il reste un outil concret, largement supporté, et parfaitement exploitable dans une CI à condition de ne pas le traiter comme un simple copier-coller de fin de script.

Sur un média comme Pipeline Brut, le sujet mérite d’être regardé pour ce qu’il est vraiment : non pas une tâche annexe, mais une routine d’automatisation qui doit être aussi fiable que le build lui-même.