Self-Hosted Azure DevOps Agents

Khimananda Oli 7 min read Virtualization
Self-Hosted Azure DevOps Agents

By Khimananda Oli | Last reviewed: August 2026

Microsoft-hosted runners are convenient but often fail compliance audits requiring private networking or specific toolchains. Self-hosted Azure DevOps agents solve this by executing pipeline jobs on infrastructure you fully control, whether on-premises in Kathmandu or in a private AWS VPC. This guide covers the practical setup, security hardening, and operational trade-offs needed to run them reliably in production.

Azure DevOpsPipelines ServiceSelf-Hosted AgentPrivate VM / ContainerInternal ResourcesDBs / APIs / StorageJob QueuePrivate AccessYour Private Network (VPC / On-Prem)No Public Inbound RequiredOutbound HTTPS Only (443)Full Toolchain Control
Self-hosted Azure DevOps agents architecture: outbound-only connectivity enables private resource access without inbound firewall rules

How do you install and configure self-hosted Azure DevOps agents?

The agent is a lightweight .NET Core application that polls Azure Pipelines for work. Installation takes under ten minutes on Ubuntu 22.04/24.04 or Windows Server 2022. Before starting, ensure you have a Personal Access Token (PAT) scoped to Agent Pools (read, manage) and that the target machine can reach dev.azure.com over HTTPS.

Step-by-step Linux installation

  1. Create a dedicated service account. Never run the agent as root in production.
  2. Download the latest agent package from your organization’s agent pool page.
  3. Extract, configure interactively once to validate credentials, then install as a systemd service.
  4. Verify the agent appears online in the Azure DevOps portal before queuing builds.
# Create service user
sudo useradd -m -s /bin/bash azagent

# Download and extract (verify version on your org's download page)
mkdir /opt/azagent && cd /opt/azagent
curl -O https://vstsagentpackage.azureedge.net/agent/3.241.0/vsts-agent-linux-x64-3.241.0.tar.gz
tar zxvf vsts-agent-linux-x64-3.241.0.tar.gz
chown -R azagent:azagent /opt/azagent

# Interactive configuration (run as azagent user)
sudo -u azagent ./config.sh \
  --url https://dev.azure.com/YOUR_ORG \
  --auth pat \
  --token YOUR_PAT_TOKEN \
  --pool Default \
  --agent ubuntu-prod-01 \
  --acceptTeeEula

# Install and start as systemd service
sudo ./svc.sh install azagent
sudo ./svc.sh start azagent
sudo ./svc.sh status azagent

A common mistake is skipping the interactive validation step. If your PAT lacks the correct scope or the agent name conflicts with an existing registration, config.sh will fail silently during service install. Always confirm the agent shows "Online" in the portal before proceeding. For teams managing multiple agents, consider automating this with Ansible playbooks as described in automating server setup with Ansible.

When should you use self-hosted agents instead of Microsoft-hosted runners?

Microsoft-hosted runners are ephemeral VMs managed entirely by Azure. They’re ideal for open-source projects or workloads with no private dependencies. Self-hosted agents become necessary when your requirements exceed what shared infrastructure can provide. The decision isn’t about preference—it’s about constraints.

CriteriaMicrosoft-HostedSelf-Hosted Azure DevOps Agents
Private network accessNot availableFull VPC/on-prem access
Custom toolchainsLimited to pre-installedAny software, any version
Compliance (SOC 2, ISO 27001)Shared tenant concernsIsolated, auditable infra
Build caching / artifactsEphemeral, no persistencePersistent disk, local caches
Cost at scalePer-minute billing adds upFixed VM cost, higher utilization
Maintenance burdenZeroPatching, updates, monitoring
Cold start time30–90 secondsNear-instant (warm pool)

In practice, most teams I work with adopt a hybrid model: Microsoft-hosted for PR validation and public-facing builds, self-hosted for deployment pipelines, integration tests against staging databases, and any job touching internal APIs. This balances cost, security, and maintenance overhead. If you’re evaluating cloud providers for hosting these agents, comparing AWS, Azure, and GCP helps clarify which platform offers the best networking and pricing for your agent fleet.

New Pipeline JobRequires private network access?YesNoSelf-Hosted AgentCustom tools needed?YesNoSelf-Hosted AgentMicrosoft-Hosted
Decision flowchart: when to choose self-hosted Azure DevOps agents versus Microsoft-hosted runners based on network and tooling requirements

How do you secure self-hosted Azure DevOps agents for production?

Running agents on your infrastructure means owning the attack surface. Treat every agent like a production server: hardened, monitored, and least-privilege. After years of audit preparation for SOC 2 and ISO 27001, these controls are non-negotiable.

  • Service isolation: Run each agent under a dedicated non-root user with no shell access beyond the agent directory.
  • PAT rotation: Use short-lived PATs (30–90 days) stored in HashiCorp Vault or Azure Key Vault, never in plaintext config files. Automate rotation via API.
  • Network egress filtering: Allow outbound only to dev.azure.com, *.vsblob.vsassets.io, and your internal artifact feeds. Block all other egress.
  • Immutable base images: Rebuild agent VMs monthly from golden images rather than patching in place. This prevents configuration drift and simplifies audit evidence collection.
  • Workspace cleanup: Configure clean: true in pipeline YAML or set the agent’s VSTS_AGENT_CLEAN_WORKSPACE environment variable to prevent secret leakage between jobs.

For secrets management specifically, integrating HashiCorp Vault eliminates static credentials entirely. Agents fetch dynamic secrets at job runtime, reducing blast radius if a build is compromised. See secrets management with HashiCorp Vault for implementation patterns that work well with Azure Pipelines.

How do you scale and maintain self-hosted Azure DevOps agents efficiently?

A single agent handles one job at a time. At scale, you need autoscaling, health monitoring, and automated recovery. Manual agent management doesn’t survive past five machines.

Autoscaling strategies

For containerized workloads, deploy agents as Kubernetes pods using the official Azure DevOps Agent Helm chart. Scale based on queue depth using KEDA with the Azure Pipelines scaler. For VM-based agents, use Azure Virtual Machine Scale Sets or AWS Auto Scaling Groups with a custom metric derived from the Azure DevOps REST API’s queue length endpoint.

# Example: Check pending jobs via Azure DevOps REST API
curl -s -H "Authorization: Bearer $PAT" \
  "https://dev.azure.com/YOUR_ORG/_apis/distributedtask/pools/Default/jobrequests?api-version=7.0" \
  | jq '[.value[] | select(.result == null)] | length'

Monitoring and alerting

Agents expose health via the Azure DevOps UI, but that’s insufficient for production. Monitor these metrics locally and ship to your observability stack:

  • Agent process uptime and restart count
  • Disk usage in _work directory (alert at 80%)
  • Job duration outliers (detect stuck builds)
  • Failed authentication attempts (indicates PAT expiry or misconfiguration)

Prometheus node_exporter plus a custom script parsing _diag logs gives you actionable signals. Pair this with Grafana dashboards as outlined in monitoring with Prometheus and Grafana to correlate agent health with pipeline throughput.

Azure PipelinesQueue Depth APIKEDA ScalerPolls QueueK8s Agent PodsAuto-scaled 1–20VM Scale SetLegacy / Heavy BuildsCustom MetricQueue LengthPrometheus + GrafanaHealth & ThroughputHybrid scaling: containers for parallelism, VMs for stateful/heavy workloads
Scaling self-hosted Azure DevOps agents: KEDA-driven Kubernetes pods for burst capacity alongside VM scale sets for legacy workloads

Operational checklist for self-hosted Azure DevOps agents

Before marking your agent pool production-ready, verify these items. Missing even one has caused failed audits and midnight incidents in environments I’ve reviewed.

  • Agent runs as non-root with workspace cleanup enabled
  • PAT stored in secrets manager, rotated automatically, scoped minimally
  • Outbound firewall allows only required Azure DevOps endpoints
  • Base image rebuilt monthly; configuration managed via IaC
  • Monitoring covers process health, disk, job duration, and auth failures
  • Disaster recovery documented: how to rebuild entire pool from code in under 30 minutes
  • Audit trail captures agent provisioning, config changes, and secret access

Running self-hosted Azure DevOps agents securely at scale

Self-hosted Azure DevOps agents give you control that Microsoft-hosted runners cannot match, but that control demands discipline. Start with a small, well-monitored pool. Automate provisioning and secret rotation early. Treat agents as production infrastructure, not disposable build boxes. When configured correctly, they become the foundation of compliant, high-throughput CI/CD that passes audits and survives traffic spikes. If your team needs help designing or hardening an agent fleet, reach out to discuss your specific requirements.

Frequently Asked Questions

Self-hosted Azure DevOps Agents are virtual machines or containers you manage that run pipeline jobs for your organization. Unlike Microsoft-hosted agents, you control the OS, installed tools, and network configuration, enabling custom dependencies and persistent caching while retaining full integration with Azure Pipelines.

Download the latest agent package from your pool settings, extract it, and run config.sh with your organization URL and personal access token. Use systemd to create a service file for automatic startup. Ensure the user has necessary permissions for build directories and Docker sockets if containerizing builds.

No.

Yes.

Microsoft-hosted agents provide fresh VMs per job with preinstalled tools but limit customization and runtime duration. Self-hosted Azure DevOps Agents persist between runs, allow custom software installation, support longer timeouts, and connect to private networks, though you assume all maintenance, security patching, and infrastructure costs yourself.

Run agents under least-privilege service accounts, never as root. Restrict network access using firewalls to only required Azure endpoints. Rotate PATs regularly or use managed identities. Isolate build environments using containers or VMs to prevent cross-job contamination and protect secrets stored in environment variables or credential managers.

Check network connectivity to dev.azure.com and verify the agent process is running via systemctl status. Review logs in the _diag folder for authentication failures or proxy misconfigurations. Expired PATs, blocked ports, or insufficient disk space commonly cause offline states. Restart the service after fixing underlying issues to restore connectivity.

Enable auto-update during initial configuration using the --acceptTeeEula and --replace flags. The agent checks for new versions before each job and updates itself when idle. For air-gapped environments, manually download packages and run config.sh again. Monitor release notes for breaking changes and test updates in staging pools first.

Yes.

One.

Minimum requirements include 1 GB RAM, 1 CPU core, and 10 GB free disk space for the agent and workspace. Production workloads typically need 4+ cores and 8+ GB RAM. Ensure .NET 6+ runtime on Windows or compatible glibc on Linux. SSD storage significantly improves checkout and artifact performance.

Profile job steps to identify bottlenecks like slow git clones or dependency installs. Enable persistent caching for package managers and Docker layers. Verify hardware resources aren't exhausted during builds. Check network bandwidth to artifact feeds. Compare timing against Microsoft-hosted baselines to determine if slowness stems from agent specs or pipeline inefficiencies.

Yes, self-hosted Azure DevOps Agents excel at accessing private resources since they run within your network perimeter. Configure VPN connections, VNet peering, or ExpressRoute to reach internal services. Use service connections with managed identities instead of storing credentials. This eliminates the need for public exposure or complex NAT gateway configurations.

Deploy agents on Kubernetes using the official Helm chart or configure VMSS with autoscale rules based on queue depth metrics. Use Azure Functions to trigger scale-out events via REST API. Implement graceful shutdown hooks to prevent job interruption. Combine static agents for baseline load with elastic capacity for peak demand periods.

Active jobs fail immediately upon agent restart or service stop. Always drain the agent first using the --drain flag or disable it via pool settings before maintenance. Queued jobs reassign to other available agents automatically. Schedule restarts during low-activity windows and communicate planned downtime to development teams to minimize disruption.