DevOps Elastic Hayway
Document

SUBSCRIBE TO GET FULL ACCESS TO THE E-BOOKS FOR FREE 🎁SUBSCRIBE NOW

Professional Dropdown with Icon

SUBSCRIBE NOW TO GET FREE ACCESS TO EBOOKS

Azure DevOpsLesson 21 / 3111 min readUpdated October 7, 2026

Azure DevOps Self-hosted Agent on Linux: Install, Register and Run as a Service

À la fin de ce tutoriel, vous saurez choisir self-hosted vs Microsoft-hosted, préparer une machine Linux (Ubuntu 24.04 / 22.04), créer un agent pool, enregistrer un agent Azure Pipelines avec un PAT (placeholder <PAT> uniquement), le lancer en service systemd, le cibler depuis un YAML, et appliquer une checklist sécurité — sans coller de secrets en clair.

Niveau : Intermédiaire · Temps estimé : 60–90 min · Versions testées : Azure DevOps Services (portail 2026), agent Linux x64, Ubuntu 24.04 · Dernière vérification : 2026-09-12

Slug live (menu) : azure-devops-self-hosted-agents · WP post : 1070 · URL : https://devopelastichayway.com/azure-devops-self-hosted-agents/ · Série : Azure DevOps · Région lab Azure (si VM) : canadacentral

Prérequis

  • Organisation Azure DevOps où vous êtes Project Collection Administrator (ou Administrator sur un agent pool)
  • Droits pour créer un PAT avec le scope Agent Pools (Read & manage)
  • Machine lab Linux x64 : Ubuntu 24.04 recommandé (22.04 OK avec libicu70) ou VM Azure canadacentral (B1s/B2s) — pas de production
  • Accès sortant HTTPS vers dev.azure.com (et téléchargement agent) ; sudo ; Git, curl, jq
  • Familiarité de base avec un azure-pipelines.yml (trigger, steps)
  • Budget : 0 € en local ; quelques cents/heure si VM Azure (deallocate après le lab)

Coût & minutes : les jobs self-hosted ne consomment en général pas les minutes Microsoft-hosted (vérifiez Billing). Le PAT d’enregistrement est un secret : durée courte, scopes minimaux, jamais commitné.

Maillage utile : Agents Microsoft-hosted · Azure DevOps Tools · Release pipeline · draft P4 agents self-hosted.

Ce que nous allons construire

Organisation Azure DevOps
  └── Agent pool « linux-onprem » (ou ado-lab-self)
        └── Agent « build-ubuntu-01 » (Linux, Online)
Machine lab (user azagent)
  └── ~/myagent/
        ├── config.sh  (URL org + pool + PAT au prompt)
        ├── svc.sh     (unité systemd)
        └── _work/     (workspaces des jobs)
YAML pipeline
  └── pool: name: linux-onprem   # sans vmImage

(Schéma maison à brancher à la publish : cover assets/web/devopelastichayway/cover-azure-pipelines-agents-self-hosted-1200x630.webp, alt : « Agent self-hosted Azure DevOps : pool, machine Linux, PAT d’enregistrement, YAML pool name ».)

Un agent self-hosted est une machine que vous contrôlez qui interroge Azure DevOps pour exécuter des jobs. Contrairement aux agents Microsoft-hosted (VM jetable, réseau public, caches vides), vous gagnez accès privé, caches persistants et outils custom — au prix du patching et de la confiance accordée à l’hôte.

Étape 1 — Microsoft-hosted vs self-hosted : quand choisir quoi

Critère Microsoft-hosted Self-hosted
Setup Aucun Installer + maintenir agent et outils
Coût Free 1 job parallèle (~1 800 min/mois), puis ~40 USD/mois/job 1 job parallèle self-hosted puis ~15 USD/mois/job + votre VM
Réseau Internet public seulement On‑prem, VNet, registres privés, bases internes
Cache VM propre à chaque run Couches Docker, packages, repos → builds plus rapides
Matériel / logiciels Images fixes GPU, licences, OS spécifiques
Sécurité Isolé, jetable À votre charge : patch, isolation, rotation credentials

Motifs valides : minutes hosted saturées, outils absents des images, accès réseau privé, cache disque, conformité. À éviter : contourner la sécurité, agent root exposé, PAT large partagé, code de forks non fiables sur votre réseau (préférez hosted pour les PR de forks).

Étape 2 — Préparer l’hôte Linux

L’agent (runtime .NET) exige ICU. Vos pipelines demanderont Git, Docker, Node, .NET, Java… Installez le socle et un compte non root dédié.

sudo apt update && sudo apt install -y curl git jq libicu74 ca-certificates
# Ubuntu 22.04 : libicu70 — RHEL 9 : dnf install -y libicu
sudo useradd -m -s /bin/bash azagent
# Optionnel Docker (builds d’images) :
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker azagent

Ouvrez uniquement le sortant 443 vers Azure DevOps. Traitez l’hôte comme de la prod : patches, monitoring, pas de sessions interactives quotidiennes.

Lab bonus — smoke ICU : si l’agent refuse de démarrer (« Couldn’t find a valid ICU package »), vérifiez libicu* ou testez temporairement DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 (lab uniquement, pas une excuse pour ignorer ICU en réel).

Étape 3 — Créer l’agent pool

  1. Organization settings → Pipelines → Agent pools → Add pool.
  2. Type Self-hosted, nom parlant : linux-onprem (ou ado-lab-self en série P4).
  3. En lab vous pouvez cocher l’accès large aux pipelines ; en entreprise, autorisez pipeline par pipeline.
  4. Ouvrez le pool → Security : votre compte en Administrator (requis pour enregistrer des agents).
  5. New agent → Linux x64 → notez le lien de téléchargement du jour.

Alternative : pool au niveau Project settings si votre org l’autorise.

Étape 4 — PAT d’enregistrement (placeholder seulement)

Le PAT sert surtout à l’enregistrement ; ensuite l’agent utilise son propre jeton OAuth. Créez un PAT dédié (avatar → Personal access tokens → New Token) :

Champ Valeur lab
Name pat-agent-linux-onprem-YYYYMM
Expiration Courte (7 jours)
Scopes Agent Pools (Read & manage) uniquement

Règles d’or : affiché une fois ; coffre / gestionnaire ; dans ce cours uniquement <PAT> ; jamais dans Git, Slack, README, captures ; révoquez après enregistrement ou en fin de lab ; jamais echo <PAT> dans un job.

# INTERDIT
PAT=xxxxxxxxxxxxxxxx
curl ... -H "Authorization: Basic <vrai-jeton>"

Étape 5 — Télécharger et configurer l’agent

Sous l’utilisateur azagent (téléchargez toujours depuis le portail / release officielle — la version change) :

sudo -iu azagent
mkdir -p ~/myagent && cd ~/myagent
# Lien exact : bouton New agent du pool (recommandé)
# Ou dernière release linux-x64 via API GitHub microsoft/azure-pipelines-agent :
AGENT_URL=$(curl -s https://api.github.com/repos/microsoft/azure-pipelines-agent/releases/latest 
  | jq -r '.assets[] | select(.name | test("vsts-agent-linux-x64-.*tar.gz$")) | .browser_download_url')
echo "$AGENT_URL"
curl -fsSL "$AGENT_URL" -o agent.tar.gz
tar zxf agent.tar.gz && rm agent.tar.gz
./config.sh

Réponses typiques : Server URL https://dev.azure.com/<org> · Auth PAT · jeton collé au prompt · Pool linux-onprem · Agent name build-ubuntu-01 · Work folder _work.

Mode non interactif (cloud-init / Ansible) — le secret vient d’un coffre, pas de l’historique shell :

./config.sh --unattended 
  --url "https://dev.azure.com/<your-organization>" 
  --auth pat --token "$AZP_TOKEN" 
  --pool linux-onprem 
  --agent "$(hostname)" 
  --work _work 
  --acceptTeeEula 
  --replace

Étape 6 — Service systemd et premier Online

./run.sh suffit pour un smoke test. Pour survivre aux reboots :

exit   # revenir à un compte sudo
cd /home/azagent/myagent
sudo ./svc.sh install azagent
sudo ./svc.sh start
sudo ./svc.sh status
sudo journalctl -u 'vsts.agent.*' -f

Dans le pool : badge Online. Onglet Capabilities : Agent.OS, docker, git… Ajoutez des capacités utilisateur (gpu=true) et ciblez-les avec demands dans le YAML.

Lab bonus — diagnostic : lancez un job hello-world, puis vérifiez journalctl et l’espace disque de _work. Si Offline : DNS/proxy vers dev.azure.com ; ./config.sh --proxyurl derrière un proxy d’entreprise.

Étape 7 — Cibler le pool depuis YAML

# azure-pipelines.yml — self-hosted : PAS de vmImage
trigger:
  branches:
    include: [main]

pool:
  name: linux-onprem
  demands:
    - docker   # optionnel

variables:
  imageName: myapp

steps:
  - checkout: self
    clean: true
  - script: |
      docker build -t $(imageName):$(Build.BuildId) .
      docker image ls $(imageName)
    displayName: Build container image
  - script: |
      echo "Running on $(Agent.Name) / $(Agent.OS)"
      df -h $(Agent.WorkFolder)
    displayName: Agent diagnostics

Premier run : Permit la pipeline sur le pool (autorisation one-shot). Pour une machine précise : demands: Agent.Name -equals build-ubuntu-01. Un agent = un job à la fois ; scalez avec plusieurs dossiers agents ou une VM/conteneur par agent.

Étape 8 — Exploitation, Docker éphémère et sécurité

Updates : ADO met souvent à jour l’agent automatiquement ; sinon Update all agents sur le pool. Disque : activez la maintenance du pool pour purger _work ; docker system prune si besoin. Retrait :

sudo ./svc.sh stop && sudo ./svc.sh uninstall
sudo -u azagent ./config.sh remove --auth pat --token "$AZP_TOKEN"

Alternative Docker / K8s : agent conteneur qui s’enregistre au start et se désinscrit (./run.sh --once) ; sur Kubernetes, scaler type KEDA azure-pipelines. Utile pour code non fiable — moins de « snowflake » qu’un agent longue durée.

Checklist sécurité (non négociable) :

  1. User non privilégié — jamais root pour tourner les jobs.
  2. PAT scope unique Agent Pools, expiration courte, révocation après enregistrement si possible.
  3. Pas d’accès « all pipelines » sur org partagée — approve par projet.
  4. Hôte patché, monitoring, firewall sortant 443 seulement.
  5. PR de forks → Microsoft-hosted uniquement.
  6. Pas de secrets longue durée sur le disque agent ; préférez Variable groups / Key Vault / OIDC.
  7. Ne partagez pas un même agent entre projets hostiles (fuite via _work).

Scénario terrain : un stagiaire commit un PAT Full access « pour que ça marche ». Révoquez immédiatement, auditez les pools, régénérez un PAT Agent Pools minimal, et documentez l’incident dans votre runbook lab.

Lab bonus — cache, demands et maintenance

Après le hello-world, enchaînez ces micro-labs (toujours hors prod) :

  1. Demands : ajoutez une capacité utilisateur lab=true sur l’agent (pool → agent → Capabilities) puis exigez-la dans le YAML. Confirmez qu’un agent sans la capacité laisse le job en file.
  2. Cache disque : lancez deux builds Docker successifs sur le même hôte et comparez la durée ; documentez pourquoi le second est plus rapide (couches locales) et le risque associé (état partagé entre jobs).
  3. Maintenance : activez l’historique de maintenance du pool pour purger les anciens dossiers _work, puis vérifiez l’espace disque avant/après.
  4. Failover mental : simulez un agent Offline (svc.sh stop) et observez la queue ; redémarrez et validez la reprise. Notez le runbook en trois lignes pour votre équipe.

Checklist anti-dérive self-hosted

  • [ ] Pool nommé, permissions pipeline explicites (pas « all pipelines » en org partagée)
  • [ ] Compte azagent sans sudo quotidien ; Docker group seulement si nécessaire
  • [ ] PAT <PAT> court, scope Agent Pools, révoqué ou daté de rotation
  • [ ] systemd installé et testé après reboot
  • [ ] YAML sans vmImage sur ce pool ; demands documentées
  • [ ] Forks / code non fiable exclus de cet hôte
  • [ ] VM canadacentral deallocatée hors lab ; _work et images Docker nettoyés
  • [ ] Lien menu / slug azure-devops-self-hosted-agents aligné avec ce draft à la publish ()

Ces exercices consolidement le choix self-hosted sans remplacer les agents Microsoft-hosted : gardez les deux options dans votre boîte à outils Azure Pipelines, et documentez pourquoi chaque pipeline cible tel pool.

Étape 9 — Vérification de fin de parcours

  1. Pool linux-onprem créé ; agent Online au moins une fois.
  2. Un run YAML affiche Agent.Name=build-ubuntu-01 (ou le nom choisi).
  3. PAT : scopes minimaux, absent du Git et de ce fichier.
  4. Vous savez stopper/désinstaller et révoquer le jeton.
  5. Décision documentée : rester self-hosted ou revenir à ubuntu-latest pour la suite CI/CD.

Nettoyage

  • svc.sh stop si la machine dort ; révoquez / régénérez les PAT agent.
  • Pool vide : supprimez seulement s’il n’est plus référencé.
  • VM Azure canadacentral : deallocate pour couper le compute.
  • Ne laissez pas un YAML pointant vers un pool fantôme (queue infinie).
  • Conteneurs : retirez images/volumes lab ; révoquez AZP_TOKEN.

Erreurs fréquentes

Symptôme Cause Correction
Couldn’t find a valid ICU package libicu manquant Installer libicu74 / libicu70
Access denied… Manage permissions for pool Pas Admin du pool Security du pool → Administrator
Agent Offline Service stop, DNS, proxy svc.sh start ; journalctl ; --proxyurl
Job waits forever for an available agent Mauvais pool.name, demands, permissions Nom exact ; Permit pipeline ; demands
vmImage + name self-hosted Confusion hosted/self Self-hosted : name seul
PAT dans l’historique Git Copier-coller Révoquer + purge / nouveau repo lab
Disk full _work / Docker Maintenance pool ; prune Docker
Auth failed au config.sh PAT expiré / mauvais scope Nouveau PAT Agent Pools au prompt

Quiz (5 questions)

1. Pourquoi un PAT court avec scope Agent Pools seulement ?
– A. Azure Boards le facture à l’heure
– B. Limiter la surface si fuite ; l’enregistrement n’a pas besoin de Full access
– C. YAML refuse les scopes longs

2. Comment cibler un pool self-hosted ?
– A. pool: name: linux-onprem (sans vmImage)
– B. pool: vmImage: linux-onprem
– C. Uniquement via Azure Boards

3. Où doivent tourner les builds de PR provenant de forks non fiables ?
– A. Sur votre agent on‑prem root
– B. De préférence sur Microsoft-hosted
– C. Sur n’importe quel agent avec Docker.sock ouvert au monde

4. Que faire si l’agent reste Offline après reboot ?
– A. Supprimer l’organisation
– B. Vérifier le service systemd (svc.sh / journalctl) et la connectivité HTTPS
– C. Mettre le PAT en clair dans le README

5. Un agent self-hosted exécute combien de jobs en parallèle par défaut ?
– A. Illimité
– B. Un job à la fois
– C. Exactement 10

Réponses : 1‑B · 2‑A · 3‑B · 4‑B · 5‑B

Pour aller plus loin

Maillage série Azure DevOps

← Lié Azure DevOps Microsoft-hosted agents
→ Suite Azure Release Pipeline / CI build
Aussi Azure DevOps Tools · Sécurité & gouvernance · YAML pipelines

Retour parcours Azure DevOps — hub de la série et leçons sœurs.

Share your love

Leave a Reply

Your email address will not be published. Required fields are marked *