Azure DevOps Self‐Hosted Agent — Setup Guide - elyjhone23/ado-pipe GitHub Wiki

Azure DevOps Self-Hosted Agent — Setup Guide

Practical reference for installing, re-installing, and removing a self-hosted Azure DevOps agent on Linux and Windows in unattended mode. Covers agent pools, deployment groups, and environment VM resources.


Table of Contents


Prerequisites

In Azure DevOps

  1. Agent pool (for pipeline agents) — Project Settings → Agent pools → Add pool

    • Type: Self-hosted
    • Name: e.g. MyDodiTech-PRD
    • Grant access permission to all pipelines
  2. Deployment group (for classic release pipelines) — Pipelines → Deployment groups → New

    • Name: e.g. MyDodiTech-PRD-DG
    • Note the project name — you need it for --projectName
  3. Environment (for YAML pipelines) — Pipelines → Environments → New environment

    • Resource type: Virtual machines
    • Follow the registration script — or use the flags below for unattended setup
  4. PAT (Personal Access Token) — User settings (avatar) → Personal access tokens → New Token

    • Scope: Agent Pools → Read & Manage (also covers deployment groups/environments)
    • Copy the token — it is shown only once

Linux — Agent Pool

On the VM

Requirement Check Install
curl curl --version sudo apt-get install -y curl
libicu (glibc) dpkg -l libicu* sudo apt-get install -y libicu-dev
git ≥ 2.9 git --version sudo apt-get install -y git

The agent ships its own .NET runtime — no separate .NET install needed.

1 — Download the agent

mkdir -p ~/azagent && cd ~/azagent

AGENT_URL=$(curl -s https://api.github.com/repos/microsoft/azure-pipelines-agent/releases/latest \
  | grep browser_download_url \
  | grep linux-x64 \
  | cut -d '"' -f 4 \
  | head -1)

curl -fsSL "$AGENT_URL" -o agent.tar.gz
tar xzf agent.tar.gz
rm agent.tar.gz

2 — Configure (register) the agent

cd ~/azagent

./config.sh \
  --unattended \
  --url https://dev.azure.com/<YOUR_ORG> \
  --auth pat \
  --token <YOUR_PAT> \
  --pool "<YOUR_POOL_NAME>" \
  --agent "$(hostname)" \
  --replace \
  --acceptTeeEula

3 — Install and start the systemd service

cd ~/azagent

# Install the service running as your own user (replace ddt25 with your username)
sudo ./svc.sh install ddt25

# Start it
sudo ./svc.sh start

# Verify it is running
sudo ./svc.sh status

Why specify your username?
The agent needs to access your app directories (e.g. /home/ddt25/infrastructure/...). Running the service as ddt25 avoids all permission errors in the CD pipeline. Never run the agent service as root.

4 — Verify in Azure DevOps

Project Settings → Agent pools → <YOUR_POOL_NAME>Agents tab

The agent should show as Online.


Windows — Agent Pool

On the VM

Requirement Details
OS Windows 10 (21H2 / 1809 / 1607), Windows 11, or Windows Server 2012+
PowerShell 3.0 or higher
.NET Not required — the agent ships its own runtime

Run all setup commands from an elevated PowerShell window. Never use PowerShell ISE or git-bash (mintty).

1 — Download and extract

New-Item -ItemType Directory -Force -Path C:\agents
# Download the latest windows-x64 agent from https://github.com/microsoft/azure-pipelines-agent/releases
# Then extract:
Add-Type -AssemblyName System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::ExtractToDirectory("$env:USERPROFILE\Downloads\vsts-agent-win-x64-*.zip", "C:\agents")

Keep the agent folder path free of spaces. C:\agents is recommended. Restrict folder permissions: only admins and the service account should have write access.

2 — Configure as a Windows service with a service account

cd C:\agents

.\config.cmd `
  --unattended `
  --url https://dev.azure.com/<YOUR_ORG> `
  --auth pat `
  --token <YOUR_PAT> `
  --pool "<YOUR_POOL_NAME>" `
  --agent "$env:COMPUTERNAME" `
  --replace `
  --runAsService `
  --windowsLogonAccount "DOMAIN\svc-azagent" `
  --windowsLogonPassword "<SERVICE_ACCOUNT_PASSWORD>"
Flag Purpose
--runAsService Register and start agent as a Windows service (requires admin)
--windowsLogonAccount Service account in DOMAIN\user or [email protected] format
--windowsLogonPassword Password for the account (omit for gMSA or built-in accounts like NT AUTHORITY\NETWORK SERVICE)
--enableservicesidtypeunrestricted Optional — sets SERVICE_SID_TYPE_UNRESTRICTED instead of the default SERVICE_SID_TYPE_NONE

Service account options

Account type --windowsLogonAccount value Password required?
Domain account DOMAIN\svc-azagent Yes
UPN format [email protected] Yes
Group Managed Service Account (gMSA) DOMAIN\svc-azagent$ No — omit --windowsLogonPassword
Built-in Network Service NT AUTHORITY\NETWORK SERVICE No — omit --windowsLogonPassword
Local System NT AUTHORITY\SYSTEM No — omit --windowsLogonPassword

Prefer a dedicated domain account or gMSA over built-in accounts. The account only needs the permissions your pipeline tasks require — do not use an admin account.

3 — Verify the Windows service

The agent installs itself as a Windows service named:

vstsagent.<org-name>.<agent-name>

Check it from PowerShell:

Get-Service "vstsagent.*"

Or open services.msc and look for Azure Pipelines Agent / VSTS Agent.

4 — Verify in Azure DevOps

Project Settings → Agent pools → <YOUR_POOL_NAME>Agents tab — the agent should show as Online.


Deployment Group (Linux & Windows)

Deployment groups are used by classic release pipelines to target a specific set of machines.

Linux

cd ~/azagent

./config.sh \
  --unattended \
  --url https://dev.azure.com/<YOUR_ORG> \
  --auth pat \
  --token <YOUR_PAT> \
  --deploymentGroup \
  --deploymentGroupName "<YOUR_DG_NAME>" \
  --projectName "<YOUR_PROJECT_NAME>" \
  --agent "$(hostname)" \
  --replace \
  --acceptTeeEula \
  --addDeploymentGroupTags \
  --deploymentGroupTags "web,app"

sudo ./svc.sh install ddt25
sudo ./svc.sh start

Windows (with service account)

cd C:\agents

.\config.cmd `
  --unattended `
  --url https://dev.azure.com/<YOUR_ORG> `
  --auth pat `
  --token <YOUR_PAT> `
  --deploymentGroup `
  --deploymentGroupName "<YOUR_DG_NAME>" `
  --projectName "<YOUR_PROJECT_NAME>" `
  --agent "$env:COMPUTERNAME" `
  --replace `
  --addDeploymentGroupTags `
  --deploymentGroupTags "web,app" `
  --runAsService `
  --windowsLogonAccount "DOMAIN\svc-azagent" `
  --windowsLogonPassword "<PASSWORD>"
Flag Purpose
--deploymentGroup Register as a deployment group agent instead of a pool agent
--deploymentGroupName <name> Name of the deployment group to join
--projectName <name> Azure DevOps project that owns the deployment group
--addDeploymentGroupTags Enable tag assignment on this agent
--deploymentGroupTags <tags> Comma-separated tags, e.g. "web,db"

Environment VM Resource (Linux & Windows)

Environment resources are used by YAML pipelines (environment: + resourceType: VirtualMachine).

Linux

cd ~/azagent

./config.sh \
  --unattended \
  --url https://dev.azure.com/<YOUR_ORG> \
  --auth pat \
  --token <YOUR_PAT> \
  --pool "<YOUR_POOL_NAME>" \
  --agent "$(hostname)" \
  --replace \
  --acceptTeeEula \
  --addvirtualmachineresourcetags \
  --virtualmachineresourcetags "web,app"

sudo ./svc.sh install ddt25
sudo ./svc.sh start

Windows (with service account)

cd C:\agents

.\config.cmd `
  --unattended `
  --url https://dev.azure.com/<YOUR_ORG> `
  --auth pat `
  --token <YOUR_PAT> `
  --pool "<YOUR_POOL_NAME>" `
  --agent "$env:COMPUTERNAME" `
  --replace `
  --addvirtualmachineresourcetags `
  --virtualmachineresourcetags "web,app" `
  --runAsService `
  --windowsLogonAccount "DOMAIN\svc-azagent" `
  --windowsLogonPassword "<PASSWORD>"
Flag Purpose
--addvirtualmachineresourcetags Enable environment VM resource tag assignment
--virtualmachineresourcetags <tags> Comma-separated tags, e.g. "web,db"

Environment VM resources are registered through the agent pool — they appear in the environment after the agent connects and the environment's VM resource is linked.


Unattended config — full flag reference

Required

Flag Description
--unattended No interactive prompts — all settings must be on the command line
--url <url> Org URL, e.g. https://dev.azure.com/myorg
--auth <type> pat · SP (service principal) · negotiate · alt · integrated

Authentication

Auth type Additional flags
--auth pat --token <PAT>
--auth negotiate / --auth alt --userName <domain\user> · --password <pwd>
--auth SP --clientID · --tenantId · --clientSecret

Pool / agent identity

Flag Description
--pool <name> Pool to join
--agent <name> Agent display name in Azure DevOps
--replace Replace an existing agent with the same name

General setup

Flag Description
--work <dir> Work directory for job data (default: _work under agent root)
--acceptTeeEula Accept TEE EULA — required on Linux/macOS
--disableloguploads Do not stream console logs to the server

Windows-only startup

Flag Description
--runAsService Configure agent as a Windows service (requires admin)
--runAsAutoLogon Configure auto-logon and start agent on boot (requires admin)
--windowsLogonAccount <account> Service/logon account (domain\user or [email protected])
--windowsLogonPassword <pwd> Logon password (omit for gMSA and built-in accounts)
--enableservicesidtypeunrestricted Set service SID type to SERVICE_SID_TYPE_UNRESTRICTED
--overwriteAutoLogon Overwrite existing auto-logon (use with --runAsAutoLogon)
--noRestart Suppress machine restart after auto-logon config

Deployment group only

Flag Description
--deploymentGroup Register as a deployment group agent
--deploymentGroupName <name> Deployment group to join
--projectName <name> Project that owns the deployment group
--addDeploymentGroupTags Enable tag assignment
--deploymentGroupTags <tags> Comma-separated tag list, e.g. "web,db"

Environment VM resource only

Flag Description
--addvirtualmachineresourcetags Enable environment resource tag assignment
--virtualmachineresourcetags <tags> Comma-separated tag list, e.g. "web,db"

Any flag can also be set as an environment variable by uppercasing it and prepending VSTS_AGENT_INPUT_.
Example: VSTS_AGENT_INPUT_TOKEN instead of --token.


Remove / Re-install

Linux

cd ~/azagent

# 1. Stop and uninstall the service
sudo ./svc.sh stop
sudo ./svc.sh uninstall

# 2. Unregister from Azure DevOps
./config.sh remove --unattended --auth pat --token <YOUR_PAT>

# 3. Re-register with new settings
./config.sh \
  --unattended \
  --url https://dev.azure.com/<YOUR_ORG> \
  --auth pat \
  --token <YOUR_PAT> \
  --pool "<YOUR_NEW_POOL_NAME>" \
  --agent "$(hostname)" \
  --replace \
  --acceptTeeEula

# 4. Re-install and start the service
sudo ./svc.sh install ddt25
sudo ./svc.sh start
sudo ./svc.sh status

Windows

cd C:\agents

# 1. Remove agent (stops and uninstalls the service automatically)
.\config.cmd remove --unattended --auth pat --token <YOUR_PAT>

# 2. Re-register with new settings
.\config.cmd `
  --unattended `
  --url https://dev.azure.com/<YOUR_ORG> `
  --auth pat `
  --token <YOUR_PAT> `
  --pool "<YOUR_NEW_POOL_NAME>" `
  --agent "$env:COMPUTERNAME" `
  --replace `
  --runAsService `
  --windowsLogonAccount "DOMAIN\svc-azagent" `
  --windowsLogonPassword "<PASSWORD>"

Quick reference — svc.sh commands (Linux)

sudo ./svc.sh install [username]   # Create systemd service (run as username)
sudo ./svc.sh start                # Start the service
sudo ./svc.sh stop                 # Stop the service
sudo ./svc.sh status               # Show service status
sudo ./svc.sh uninstall            # Remove the systemd service

Always use ./svc.sh instead of systemctl directly — pool names with special characters (hyphens, dots) are escaped by systemd and the raw unit name is hard to type correctly.


Troubleshooting

Symptom Likely cause Fix
Permission denied on VM paths (Linux) Agent runs as wrong user Reinstall service with sudo ./svc.sh install <your-user>
Agent shows Offline Service not started Linux: sudo ./svc.sh start · Windows: Start-Service "vstsagent.*"
--replace conflict Old agent still registered Run config remove first, then re-register
Pool / deployment group not found Name typo or not created Create pool/DG in Project Settings first
escaping is likely not reversible warning (Linux) Hyphen in pool name Harmless — use ./svc.sh wrappers, not systemctl directly
Windows service fails to start Wrong service account or password Verify account with runas /user:DOMAIN\svc-azagent cmd, check Event Viewer
Windows service starts but agent goes Offline Account lacks network access Grant Log on as a service right; check firewall for dev.azure.com
Deployment group agent not visible Wrong --projectName Must match the Azure DevOps project name exactly (case-sensitive)
Environment tags not applied Missing --addvirtualmachineresourcetags Add the flag — tags are only set when this flag is present
Auto-logon agent does not start after reboot Registry key not saved See runAsAutoLogon troubleshooting
⚠️ **GitHub.com Fallback** ⚠️