Azure DevOps Self‐Hosted Agent — Setup Guide - elyjhone23/ado-pipe GitHub Wiki
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.
- Prerequisites
- Linux — Agent Pool
- Windows — Agent Pool
- Deployment Group (Linux & Windows)
- Environment VM Resource (Linux & Windows)
- Unattended config — full flag reference
- Remove / Re-install
- Troubleshooting
-
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
-
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
- Name: e.g.
-
Environment (for YAML pipelines) — Pipelines → Environments → New environment
- Resource type: Virtual machines
- Follow the registration script — or use the flags below for unattended setup
-
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
| 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.
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.gzcd ~/azagent
./config.sh \
--unattended \
--url https://dev.azure.com/<YOUR_ORG> \
--auth pat \
--token <YOUR_PAT> \
--pool "<YOUR_POOL_NAME>" \
--agent "$(hostname)" \
--replace \
--acceptTeeEulacd ~/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 statusWhy specify your username?
The agent needs to access your app directories (e.g./home/ddt25/infrastructure/...). Running the service asddt25avoids all permission errors in the CD pipeline. Never run the agent service asroot.
Project Settings → Agent pools → <YOUR_POOL_NAME> → Agents tab
The agent should show as Online.
| 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).
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:\agentsis recommended. Restrict folder permissions: only admins and the service account should have write access.
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
|
| 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.
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.
Project Settings → Agent pools → <YOUR_POOL_NAME> → Agents tab — the agent should show as Online.
Deployment groups are used by classic release pipelines to target a specific set of machines.
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 startcd 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 resources are used by YAML pipelines (environment: + resourceType: VirtualMachine).
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 startcd 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.
| 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
|
| Auth type | Additional flags |
|---|---|
--auth pat |
--token <PAT> |
--auth negotiate / --auth alt
|
--userName <domain\user> · --password <pwd>
|
--auth SP |
--clientID · --tenantId · --clientSecret
|
| Flag | Description |
|---|---|
--pool <name> |
Pool to join |
--agent <name> |
Agent display name in Azure DevOps |
--replace |
Replace an existing agent with the same name |
| 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 |
| 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 |
| 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"
|
| 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_TOKENinstead of--token.
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 statuscd 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>"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 serviceAlways use
./svc.shinstead ofsystemctldirectly — pool names with special characters (hyphens, dots) are escaped by systemd and the raw unit name is hard to type correctly.
| 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 |